tags:

views:

1491

answers:

12

Why is my prof using two getchar(); at the end of our C program tutorials?

And what is the "better way" for this?

+21  A: 

He is waiting for user input so that you can see the output to the program, otherwise it will just complete and the output will not be visible (depending on the OS). Take it out and give it a try.

bleeeah
Also remember this answer as you move through your studies - "Take it out and give it a try" is a very handy tool in what we do. Don't be afraid to tinker sometimes.
shambleh
+1  A: 

getchar(); at the end of the program creates a "Press any key to continue" situation. I'm guessing that he likes hitting any key twice.

entens
I don't think, that he likes to hit keys twice, I think he realized that sometimes it doesn't work when he puts just one getchar(). See my example.
Lucas
+1  A: 

Probably to keep the output window open when you run the program from the IDE.

...why there are two there is beyond me though.

Justin Niessner
+2  A: 

to pause the (probably) commandline program. he is using two, because using only one didn't work and he probably doesn't know why..

find him a better solution to do this (and not std::cin) and you'll be the hero of the day.

MiRAGe
yes i am trying to find this solution :) he said he would cover it later in the semester but i want to find out now.
HollerTrain
well, first of all, he is doing the 'trick' because the buffer (which getchar() uses) might already contain a char, skipping the first getchar() (or at least not pause on it). you could perhaps empty the buffer first? or use a different method for pausing (not System("sleep")!)
MiRAGe
+1  A: 

To fetch a remaining "\n" from the buffer so that the app closes.

Christian
Wouldn't the app also close, if there was still something in the buffer?
Lucas
isn't that why he does it twice?
MiRAGe
+14  A: 

He wants the console to stay open and wait for the user to press a key. I think to remember that depending on what happens in your professors program above the "getchar()". There might still be something in the buffer, so he added a second "getchar()". Not exactly the most elegant way to solve the problem.

Edit: Here is a little example. There is still a remaining "\n" in the buffer from the "scanf()" If you add a second "getchar()", you get the expected result. You have to flush the buffer before the "getchar()".

#include <stdio.h>

main()
{
int input;
scanf("%d", &input);
printf("The input is %d\n", input);
getchar();
return 0;
}

Edit 2: Here is a solution taken from here.

int c;
printf( "Press ENTER to continue... " );
fflush( stdout );
do c = getchar(); while ((c != '\n') && (c != EOF));
Lucas
And I thought everyone else already knows this, you seem the only one here that understands the buffer issue.
abyx
@abyx I thing the buffer issue is pretty known, but shouldn't flushing the buffer be preferable? Or maybe even system("PAUSE");?
Agos
system("PAUSE") is platform depended and works only under windows.
Lucas
I've never seen a program that had to wait for a key at the end of its output that had to be platform independent. It's nearly always some throw away program or something written for academic purposes.
Carson Myers
I didn't mean to imply you shouldn't use system("PAUSE") to test your code. But since we used to pass our programs around in school, I just wanted to point it out so there won't be any surprises when you give it to somebody who doesn't run windows.
Lucas
A: 

Because one hit of the "enter" button generates two characters on Windows, see wikipedia. At least it used too, long time ago in a galaxy far far away ...

Nikolai N Fetissov
No, that’s got nothing to do with it.
Konrad Rudolph
stdin is opened as a "text" (as opposed to binary) stream meaning that you only read '\n' when the enter key is hit.
Artelius
- And even if pressing enter generated two characters, you would only need to wait for the first before terminating the program.
Artelius
Well, the world wasn't always perfect :)
Nikolai N Fetissov
A: 

I know it from my Uni ;> There must be 2 getchar(), because you probably input some text earlier and end it with ENTER. At end probably you have system("pause"); which mean, system check top char from buffor if it is ENTER (\n) end program... so second getchar() "eat" seconde enter. Now you can really pause your console program. :)

EDIT: Of course, if you input some text 2 times you should use getchar() 3 times, etc... not nice solution.

Rin
+5  A: 

The reason a lot of beginners feel it necessary to put two getch calls in their code is that one single call often doesn’t work.

The reason for that is that getch fetches the next keyboard input from the input queue. Unfortunately, this queue gets filled whenever the user presses keys on the keyboard, even if the application isn’t waiting for input at that moment (of if it isn’t reading the whole input – see Lulu’s answer for an example). As a consequence, getch will fetch a character from the input queue without waiting for the next key press – which is really what the programmer wants.

Of course, this “solution” will still fail in a lot of cases, when there’s more than just one character in the keyboard queue. A better solution is to flush that queue and then request the next character. Unfortunately, there’s no platform-independent way to do this in C/C++ to my knowledge. The conventional way to do this in C++ (sorry, my C is limited) looks like this:

std::cin.ignore(std::cin.rdbuf()->in_avail());

This simply ignores all available input, effectively clearing the input queue. Unfortunately, this code doesn’t always work, either (for very arcane reasons).

Konrad Rudolph
What about this here for flushing?void clearStdin() { int c; while ((c=getchar()) != EOF };
Christian
@Christian It’s entirely possible that this works but I guess it could fail for the same reason that the above C++ code sometimes fails.
Konrad Rudolph
+8  A: 

The best better way is not to add any code to try and keep the console window open: start your program right from the console window.

If you must start your program from the IDE and want the program to not terminate before the user presses Enter, one single getchar() should do it.

The second best better way to make the program terminate after the user presses a key, is to always make sure there are no inputs pending and use one single getchar().

The reason your teacher uses 2 getchar(), I guess, is that there is already a character in the input buffer from previous inputs. To consume all characters from the inputs, up to and including the ENTER, this is usual:

int ch;
/* ... */
printf("Press Enter"); fflush(stdout);
while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
pmg
is this syntax for C or C++?
HollerTrain
This is a standard C idiom. I believe it works in C++ too, but may not be idiomatic in that language.
pmg
+2  A: 

Why is my prof using two getchar(); at the end of our C program tutorials?

Assuming you have something like

int main ( void )
{
    int     input;

    scanf ( "%d", &input );

    printf ( "The input is %d.\n", input );

    getchar();
    getchar();

    return 0;
}

Two because scanf won't return until after an enter is pressed, but there will be the '\n' from the enter and any other characters you have entered in the input buffer.

So if you run the above and input 1234Enter, the program will pause after printing The input is 1234. until you then press Enter again. The first getchar reads the '\n' associated with the first Enter. If you input something else, such as 1234SpaceEnter, the program will not pause, as first getchar will read the space. Two getchars might not be enough, and you've interspersed the code for printing the response into the code for handling the input.

And what is the "better way" for this?

There are various standard ways of reading input in C. There are also platform specific ways of ignoring text in the input buffer, but you shouldn't need to do that if you use fgets to read a line of input instead of scanf to read some input from the last line entered.

fgets ( read input until '\n' or end of file ) followed by sscanf ( parse a string for input ) is safe from buffer overruns, and will absorb any extra input and line terminating '\n':

#include <stdio.h>

int main ( void )
{
    int     input;
    char    buf[16] = "";

    fgets ( buf, sizeof buf, stdin );

    sscanf ( buf, "%d", &input );

    printf ( "The input is %d.\n", input );

    fflush ( stdout );

    getchar();

    return 0;
}

Flushing stdout after the printf isn't normally needed for terminal IO, but can be if you're piping it to a disk ( typically when you're logging a crashing program it will lose the most interesting bit just before the crash if you don't flush ).

Because fgets reads up to and including the end of the line, there are no characters left in the buffer so you only need one getchar, and slightly awkward input such as 1234SpaceEnter doesn't cause the program to terminate without pausing.

However, most of the time you don't need to wait after running a console application - on Linux or other Unix systems you typically have a console open and run the program there, after which control returns to the shell. On Windows, IDEs such as Visual Studio typically run the program and pause it using something like:

 "C:\WINDOWS\system32\cmd.exe" /c ""...\ConsoleApplication1.exe"  & pause"

Or you can open cmd.exe and run it from there, or you can run it with a .pif shortcut and set the checkbox it not to close the console on exit, or you can create a batch file which runs it and pauses.

You really only need to make the program pause itself if you're on Windows and you're using a debugger to run it and you haven't set any breakpoints.

Pete Kirkham
A: 

It is a naive solution to the unused buffered input problem. Your prof recognises teh problem, but it seems does not know how to solve it properly.

If you use formatted input, only characters entered that match the format specifier are used. So if for example the last input requested a decimal integer using %d, you might enter at the console:

123

The formatted input will consume the "123", leaving the buffered. An unformatted input such as getchar() will consume that and return immediately. Since this is not what you want, your prof has used the "just add another getchar() kludge". This works only if the user enters the expected input. A hamfisted typist might type:

123w

Not the first getchar() gets the 'w', the second gets the , and your program terminates before you intended it to, and in a GUI environment, if the terminating process owns the window it is running in, then the OS closes it.

A more robust solution is to repeatedly call getchar() until the is found:

while( getchar() != '\n' ) { /*do nothing*/} ;
getchar() ; /* wait */

Of course if the previous input was a character, you need to chack it was not already a :

while( ch != '\n' && getchar() != '\n' ) { /*do nothing*/} ;
getchar() ; /* wait */

Rather than putting the flush loop at the end just before the 'wait' input call, it is better to perform the buffer flush after every input that requires it. This is because that is where you know you need it, and how it should be coded. I tend to write wrapper functions for the input types I need.

Clifford