tags:

views:

806

answers:

6

Hi, this is such a newbie question that I'm almost embarrassed to ask it :$ ... but anyway:

I've started reading "The C Programming Language" (K&R) and I have a doubt about the getchar() function.

For example this code:

#include <stdio.h>

main(){

  int c;

  c = getchar();
  putchar(c);
  printf("\n");

}

given the entry "toomanychars" + CTRL+D (EOF) prints just "t". I think that's expected since it's the first character introduced.

But then this other piece of code:

#include <stdio.h>

main(){

  int c;

  while((c = getchar()) != EOF) 
    putchar(c);

}

given "toomanychars" + CTRL+D (EOF) prints "toomanychars".

My question is, why does this happens if I only have a single char variable? where are the rest of the characters stored?

Thanks.

EDIT:

Thanks to everyone for the answers, I start to get it now... only one catch:

The first program exits when given CTRL+D while the second prints the whole string and then waits for more user input. Why does it waits for another string and does not exit like the first?

+3  A: 

it's treating the input stream like a file. It is as if you opened a file containing the text "toomanychars" and read/outputted it one character at a time.

In the first example, in the absence of a while loop, it's like you opened a file and read the first character, and then outputted it. However the second example will continue to read characters until it gets an end of file signal (ctrl+D in your case) just like if it were reading from a file on disk.


as per your updated question, what operating system are you using? I ran it on my Windows XP laptop and it worked fine. If I hit enter, it would print out what I had so far, make a new line, and then continue (getchar() doesn't return until you press enter when there was nothing in the input buffer when it was called). When I press CTRL+Z (EOF in Windows), the program terminates. Note that in Windows, the EOF must be on a line of its own to count as an EOF in the command prompt. I don't know if this behavior is mimicked in Linux, or whatever you may be running.

Carson Myers
@Carson, exactly! EOF must be in it's own line. THANKS A LOT!
Pablo Fernandez
you're welcome. I struggled with this also but solved it thanks to SO :)
Carson Myers
+7  A: 

getchar gets a single character from the standard input, which in this case is the keyboard buffer.

In the second example, the getchar function is in a while loop which continues until it encounters a EOF, so it will keep looping and retrieve a character (and print the character to screen) until the input becomes empty.

Successive calls to getchar will get successive characters which are coming from the input.

Oh, and don't feel bad for asking this question -- I was puzzled when I first encountered this issue as well.

coobird
+4  A: 

Your first program only reads one character, prints it out, and exits. Your second program has a loop. It keeps reading characters one at a time and printing them out until it reads an EOF character. Only one character is stored at any given time.

Dima
+2  A: 

You're only using the variable c to contain each character one at a time.

Once you've displayed the first char (t) using putchar(c), you forget about the value of c by assigning the next character (o) to the variable c, replacing the previous value (t).

John Weldon
+1  A: 

the code is functionally equivalent to

main(){
  int c;
  c = getchar();
  while(c != EOF) {
    putchar(c);
    c = getchar();
  }
}

you might find this version easier to understand. the only reason to put the assignment in the conditional is to avoid having to type 'c=getchar()' twice.

Jimmy
+1  A: 

Something here is buffered. e.g. the stdout FILE* which putchar writes to might be line.buffered. When the program ends(or encounters a newline) such a FILE* will be fflush()'ed and you'll see the output.

In some cases the actual terminal you're viewing might buffer the output until a newline, or until the terminal itself is instructed to flush it's buffer, which might be the case when the current foreground program exits sincei it wants to present a new prompt.

Now, what's likely to be the actual case here, is that's it's the input that is buffered(in addition to the output :-) ) When you press the keys it'll appear on your terminal window. However the terminal won't send those characters to your application, it will buffer it until you instruct it to be the end-of-input with Ctrl+D, and possibly a newline as well. Here's another version to play around and ponder about:

int main() {
  int c;
   while((c = getchar()) != EOF) {
     if(c != '\n')
        putchar(c);
   }
    return 0;
}

Try feeding your program a sentence, and hit Enter. And do the same if you comment out if(c != '\n') Maybe you can determine if your input, output or both are buffered in some way. THis becomes more interesting if you run the above like: ./mytest | ./mytest

(As sidecomment, note that CTRD+D isn't a character, nor is it EOF. But on some systems it'll result closing the input stream which again will raise EOF to anyone attempting to read from the stream.)

nos