1

Compiling with Clang/GCC and running on Linux:

When running the following code I encountered what was to me unanticipated behavior: when entering a single character ("X") I will be prompted to enter another character ("Y") presumably because the buffer isn't full. When I enter a second character ("Y") putchar only displays the second character ("Y" - it neither returns the first "X" nor are there any new lines/line breaks). I presume this is because putchar is reading the stream from the end to the beginning and is reading the buffer as "[NEW LINE] Y [NEW LINE]" and that the original "X" is already beyond the buffer allocated for the three variables. But this reading from the end to the beginning of the stream doesn't seem to align with putchar's usual behaviour - if I type in four characters "XYZA" and hit enter, it returns the stream from beginning to end, understandable truncated: "XYZ".

My first question is if my presumptions above are true, my second question is: if so, why is putchar not outputting the new lines that presumably are in the buffer. If I got "[NEW LINE] Y [NEW LINE]" as output it would be clear to me what's going on, but I just get "Y". Why is that? Does putchar trim whitespace elements, or is getchar reading the new line in some way that doesn't translate into an escape-sequenced character?

I've tried a number of combinations of using the enter key but don't see how this is working. I'd like to know what it's doing.

int main() {
    int a,b,c;

    printf("Type three letters: ");

    a = getchar();
    putchar(a);
    b = getchar();
    putchar(b);
    c = getchar();
    putchar(c);
}

When running the above:

  • If I type three characters it returns the three characters.

  • If I type two characters (e.g. "XY") it returns two characters, presumably because the third character is the new line generated by hitting enter. This DOES display a new line after "XY" is displayed, which makes the following behavior that much more perplexing to me:

  • If I type one character, it prompts me for another character, when I type in another character it only returns the second character. Why is this? It seems to me that it's reading the buffer from the end to the beginning and trimming white-space, but this seems unlikely. I don't understand this behavior.

  • Even though I only get one character from the last example, which to me seems to be because putchar is reading from the end to the beginning of the stream, when typing four characters it reads as it should from beginning to end: if I type four characters it returns the first three characters in the buffer.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
NewStack
  • 39
  • 4
  • Is this on a UNIX-like OS or on Windows? I ask because on Windows (and MS-DOS), newline is CR+LF, which might explain the behavior you describe. – Ruud Helderman Jul 28 '19 at 18:28
  • 1
    I'm compiling in Clang and running it on Linux, I just updated the question to reflect this information. Thank you! – NewStack Jul 28 '19 at 19:07
  • 2
    Add more printing so you can see what you're dealing with. For example, replace each `putchar()` with the appropriate variation of `printf("[%c] = %d\n", a, a);`. This will show you what is going on much better than just using `putchar()` will. – Jonathan Leffler Jul 28 '19 at 20:38
  • Hi Jonathan, that did give me more information but still does not clarify the core issue for me. What I see when I apply that code is that the buffer stream is the first character, the line feed, and then the second character. That doesn't for me answer why the final stream as printed by put char would only contain the last character typed. This isn't clear to me - if the buffer is: first letter, line feed, second letter and putchar waits for the buffer to be full and then prints the full buffer, I should get "X [LINE FEED] Y" with the code in the original post, but I'm getting only "Y"? – NewStack Jul 28 '19 at 21:42

1 Answers1

1

stdin is usually line buffered. Nothing is given to the first getchar() until '\n' is entered.

Also '\n' is one of the characters entered.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • But then why am I only prompted for the second letter and not the third? By your answer it would seem to me the behaviour would be: Enter a letter, New Line (puts first letter in buffer), Enter a second letter, New Line (puts second letter in buffer), Enter a third letter, New Line (puts third letter in buffer). But this is not how it behaves, after entering the first letter it waits for a second, then after entering the second it returns the second and ends the program. It never asks for a third, and all that should be in the buffer at that point is is "X [NEW LINE] Y [NEW LINE]" – NewStack Jul 28 '19 at 18:25
  • 1
    @NewStack "Enter a letter, New Line (puts first letter in buffer) Enter a second letter, New Line ..." --> _new line_ is the 2nd letter. The ""Enter a letter, New Line (puts first letter in buffer)" puts 2 letters in `stdin`. – chux - Reinstate Monica Jul 28 '19 at 19:43
  • 1
    @NewStack Rather than `putchar(a);`, use `printf("%d <%c>\n", a, a);` to see more information. – chux - Reinstate Monica Jul 28 '19 at 19:47
  • I used that code per a comment on my original post, but the information it provided still does not answer the question as to why I am not getting "First Letter [New Line] Second Letter" from putchar() once the buffer is full. That would make sense. I'm only getting "Second Letter". So why am I getting only the second letter, why am I not getting "First Letter [New Line] Second Letter" once the buffer is full. – NewStack Jul 28 '19 at 21:45
  • @NewStack Think of it as 2 buffers: `stdin` and the _keyboard_ buffer. The _keyboard_ buffer gives its line of data to `stdin` typically when a `'\n'` is entered. With input `"X\nY\nZ\n"`, `a = getchar();` waits until `stdin` has something. That first something is `"X\n"` and `'X'` is returned leaving `'\n'` for later. `b = getchar();` then returns `'\n'`. Later `c = getchar();` waits for something. That something is `"Y\n"` and `'Y'` is returned leaving `'\n'` for later. – chux - Reinstate Monica Jul 28 '19 at 22:15
  • Thanks Chux, I'm following you but the question then is what happened to X? – NewStack Jul 28 '19 at 22:34
  • My understanding is that in the code above putchar should be waiting for the buffer to fill before putting anything to the screen. Is this understanding correct? Because if not that may be where I'm missing information. The behavior is: 1) I type a character and hit enter, 2) It returns that character and waits for another 3) I enter the second character and hit enter 4) It returns the second character. I thought the buffer needed to be filled with 3 characters before generating the output, if this isn't correct that may be what's confusing me. – NewStack Jul 28 '19 at 22:39
  • @NewStack A) "Is this understanding correct?" No. `putchar()` does not wait. It _prints_ its character by putting it in `stdio` and then returns. That does not mean you see anything yet. `stdio` has its own _output_ buffer that may not be seen by your screen until it gets a `'\n'` - or a _flush_. Use `fflush(stdout);` after each output. B) realize that "I type a character and hit enter" and "I enter the second character and hit enter " is putting 4 characters into `stdin`. It would take 4 `getchar()` to get them all. – chux - Reinstate Monica Jul 28 '19 at 22:46