Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Why is my prof using two getchar(); at the end of our C program tutorials?
And what is the "better way" for this?
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.
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));
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 */;
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).
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.
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.
Probably to keep the output window open when you run the program from the IDE.
...why there are two there is beyond me though.
It is a naive solution to the unused buffered input problem. Your prof recognises the 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<newline>
The formatted input will consume the "123", leaving the <newline> 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<newline>
Now the first getchar() gets the 'w', the second gets the <newline>, 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 <newline> is found:
while( getchar() != '\n' ) { /*do nothing*/} ;
getchar() ; /* wait */
Of course if the previous input was a character, you need to check it was not already a <newline>:
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.
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.
To fetch a remaining "\n" from the buffer so that the app closes.
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 ...
Related
I am working on the infamous book "Prentice Hall Software Series" and trying out the Code they write and modifying it to learn more about C.
I am working with VIM on Fedora 25 in the console. The following code is a quote from the book, I know "int" is missing as well as argc and argv etc.
Kernighan and Ritchie - The C Programming Language: Page 20
#include <stdio.h>
/* copy input to output; 1st version */
main(){
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
With this code I couldn't manage to get the "EOF" to work. I am not sure if "ctr + z" really is the real thing to do, since it quits any console program in console.
Well since I was unsure i changed the condition to
...
while (c != 'a') {
...
So normally if I enter 'a' the while condition should break and the programm should terminate. Well it does not when I try to run it and enter 'a'. What is the problem here?
Thank you guys!
There's nothing wrong with the code (except the archaic declaration of main).
Usually, on Unixes end of file is signalled to the program by ctrl-D. If you hit ctrl-D either straight away or after hitting new-line, your program will read EOF.
However, the above short explanation hides a lot of subtleties.
In Unix, terminal input can operate in one of two modes (called IIRC raw and cooked). In cooked mode - the default - the OS will buffer input from the terminal until it either reads a new line or a ctrl-D character. It then sends the buffered input to your program.
Ultimately, your program will use the read system call to read the input. read will return the number of characters read but normally will block until it has some characters to read. getchar then passes them one by one to its caller. So getchar will block until a whole line of text has been received before it processes any of the characters in that line. (This is why it still didn't work when you used a).
By convention, the read system call returns 0 when it gets end of file. This is how getchar knows to return EOF to the caller. ctrl-D has the effect of forcing read to read and empty buffer (if it is sent immediately after a new line) which makes it look to getchar like it's reached EOF even though nobody has closed the input stream. This is why ctrl-D works if it is pressed straight after new line but not if it is pressed after entering some characters.
I just wanted to ask what the importance of using getch() is, especially in this array/for-loop example that our professor showed us:
int i;
char pw[7], ch;
printf ("\npw: ");
for (i=0; i<7; i++) {
ch = getch();
pw[i] = ch;
printf ("%c", ch);
}
I tried removing the ch = getch() line and what happened when I ran the program was that the loop went on forever.
Why does that happen?
I only understand that getch() is used at the end of a program to not show a character on the screen (from online definitions).
getch() reads a character from the keyboard without echoing it.
so your program is reading a character from the keybord (user input). and storing it in ch variable, then saving it in the string array pw[], at the end echoing it using printf("%c");
by removing ch = getch();. your program stops reading from keyboard. and fills the pw[] with the same value of (uninitialized ) ch exactly 7 times, and then exit loop.
according to what you posted, you program hangs elsewhere, where you are testing the validity of the password.
If you comment out getch line it runs and ends, it does not loop forever, you must have removed more to change it into a loop forever. To answer your initial question [getch] gets a char and then the program displays it, that's all.
Getch() - Reads a single character from STDIN, if none exists, waits for it!
In your example, Getch() plays a central role, reading the user input (given 7 characters).
if you remove this statement, not only you leave int ch uninitialized (with no valid value),
but the loop wont wait for anything (as getch() won't wait).
Sometimes, especially when learning c++, running a simple program from Visual Studio (or whatever IDE you use)...
running the program is very short, and you cant see the output!
so one adds getch(); at the end, just to tell the program to wait for any character, or put differently, leave the window open and wait for my key-press.
I am working on a C source code and to get input it does
while(!feof(stdin)){
fscanf(stdin, "%d ...
What I can't understand is how do you get it to stop taking input and process the input? Ctr+Z just kills the whole process and I tried pressing enter a bunch without input and it doesn't work.
EOF (usually a define with value -1) indicator on Linux will match CTRL+D (ASCII code 4) for text files. It's generic enough to be used with both binary and text files and on different environments too (for example it'll match CTRL+Z for text files on DOS/Windows).
In your case loop will exit when user will type CTRL+D as input because input stream will reach its end (then feof() will return non zero).
To see drawbacks (not so obvious behavior) for this method just try yourself to input some text then printf it out (using various inputs, terminating at the beginning or in the middle of a line). See also this post for more details about that.
Better (least astonishment) implementation may avoid fscanf and rely on fgets return value (for example). Compare its behavior with this:
char buffer[80];
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
// ...
}
In section 1.5.2 of the 2nd ed. K&R introduce getchar() and putchar() and give an example of character counting, then line counting, and others throughout the chapter.
Here is the character counting program
#include <stdio.h>
main() {
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n",nc);
}
where should the input come from? typing into the terminal command window and hitting enter worked for the file copying program but not for this. I am using XCode for Mac.
It seems like the easiest way would be to read a text file with pathway "pathway/folder/read.txt" but I am having trouble with that as well.
From the interactive command line, press ctrl-D after a newline, or ctrl-D twice not after newline, to terminate the input. Then the program will see EOF and show you the results.
To pass a file by path, and avoid the interactive part, use the < redirection operator of the shell, ./count_characters < path/to/file.txt.
Standard C input functions only start processing what you type in when you press the Enter key IOW.Every key you press adds a character to the system buffer (shell).Then when the line is complete (ie, you press Enter), these characters are moved to C standard buffer. getchar() reads the first character in the buffer, which also removes it from the buffer.Each successive call to getchar() reads and removes the next char, and so on. If you don't read every character that you had typed into the keyboard buffer, but instead enter another line of text, then the next call to getchar() after that will continue reading the characters left over from the previous line; you will usually witness this as the program blowing past your second input. BTW, the newline from the Enter key is also a character and is also stored in the keyboard buffer, so if you have new input to read in you first need to clear out the keyboard buffer.
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");
}
Typing 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);
}
Typing 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?
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?
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.
It's treating the input stream like a file. It is as if you opened a file containing the text "toomanychars" and read or 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.
In reply to 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. (The getchar() function doesn't return until you press enter, which is when there is nothing in the input buffer when it's 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 system you may be running.
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.)
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.
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).
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.
For your updated question, in the first example, only one character is read. It never reaches the EOF. The program terminates because there is nothing for it to do after completing the printf instruction. It just reads one character. Prints it. Puts in a newline. And then terminates as it has nothing more to do. It doesn't read more than one character.
Whereas, in the second code, the getchar and putchar are present inside a while loop. In this, the program keeps on reading characters one by one (as it is made to do so by the loop) until reaches reaches the EOF character (^D). At that point, it matches c!=EOF and since the conditions is not satisfied, it comes out of the loop. Now there are no more statements to execute. So the program terminates at this point.
Hope this helps.