When searching for everything about getchar() function in this really great site, I found this post: Why doesn't getchar() wait for me to press enter after scanf()?
#include <stdio.h>
int main()
{
int value;
printf("1. option 1.\n2. option 2.\n3. option 3.\n4. Exit\n\nMake an option: ");
scanf("%d", &value);
switch (value)
{
case 1:
printf("you selected the option 1.");
break;
case 2:
printf("you selected the option 2.");
break;
case 3:
printf("you selected the option 3.");
break;
case 4:
printf("goodbye");
break;
default:
printf("thats not an option");
break;
}
getchar();//here is the question,why it's useful ?
return 0;
}
I understand the whole program, and I understand that each time it is called, getchar reads the next input character from a text stream and returns that as its value. That is, after
c = getchar();
the variable c contains the next character of input. The characters normally come from the
keyboard.
But here is the question: why did the programmer call getchar() at the end of the program?
this practice is used especially for console applications, that way you force the program to not stop until you press a key so you can read the output. Usually the console closes when the program execution ends
The last getchar() function is there in order for the application to wait for a keypress before exit.
Generally in console apps, when you work in an IDE and run the code, a terminal window pops up runs the code, and as soon as the main function ends the terminal window also vanishes, and the users cannot see the last output. We need to make some way that the screen waits. One way is to make the program from being terminated by waiting for an input. Some people uses unbuffered input function at the end, so whenever you press a key the function reads it and returns immediately. In this case you use getchar which is a buffered input function, in this case, when you have finished inspecting the screen, press any character and press enter which will return from the function and after that terminate the program. You could have used scanf or other ways to hold the screen too.
It is good for debugging, please remove it from final release.
Related
First off, I just want to say that I hadn't heard of c 2 weeks ago, if that gives you any idea of where I am. Anyway, I was trying to write my first program that allows the user to make choices and continue in the story. Here I will just show you the code:
#include <stdio.h>
//Global variables for entire program
char proceed; //Used to confirm that user wishes to play
int countdwn=5; //Used in do-while loop to count down from red value
char xchoice; //Used in ABC Multiple Choice Selections
int main()
{
//Introduction sequence displays a block of text for user.
puts("\nGreetings,\n");
puts("I am glad that you made it this far!");
puts("Now, you will discover if it was worth your while!");
puts("In this program you will be provided with some information");
puts("which you must use to make wise decisions...");
puts("Whether you survive or not remains to be seen");
puts("But whatever your outcome, you are soley responsible");
puts("as you are the one making the choices... for good or ill!\n\n");
//In order for the user to continue, user must type a '~' followed by enter.
puts("Are you ready to begin!?!?");
puts("If so press \"~\" followed by enter/return---");
proceed=getchar();
if(proceed!='~')
{
puts("\nIt seems that you don't want to continue.");
puts("The program will now close and return you to dos");
puts("Once the program has closed the cursor will begin to");
puts("blink again and then type \"exit\" to exit dos");
sleep(7);
puts("Program Closing in 5...");
do
{
printf("%d\n", countdwn);
sleep(1);
countdwn--;
}
while(countdwn>0);
return 0;
}
/*************************************************************************/
puts("\nYou are living in Japan during a time known as the");
puts("\"Sengoku Jidia,\" or age of the warring states.");
puts("You are a Ninja --- a secret, deadly warrior.");
puts("What kind of missions will you take on?");
puts("What kind of dangers will you face?");
puts("Keep going to find out!\n");
puts("Make a selection by typing the number associated");
puts("with the selection you wish to make, followed by hitting enter.");
puts("Then, the next choice will automatically appear below.\n");
puts("a. To help in the attack on an enemy castle in 1558");
puts("b. To defend your homeland from an enemy attack in 1581");
puts("c. To serve as a bodygard to a powerful ruler in 1600");
puts("Make your selection a, b, or c followed by enter.");
scanf("%c", &xchoice);
if(xchoice=='A' || 'a')
{
puts("\nYou stand alone, looking up at the walls of");
puts("Sawayama Castle near the city of Hikone.");
puts("Activity buzzes all around you. You're a mercenary");
puts("ninja, fighting for whomever pays you the most for your");
puts("services. Today, you're part of an army fighting under");
puts("Rokkaku Yoshita the samurai leader of the Rokkaku clan.");
puts("The dodo clan is supposed be your ally, but some have");
puts("rebelled and taken control of one of your castles.");
puts("You have no choice but to fight to regain your loss.\n");
puts("You are one of 50 ninjas hired to take part in the");
puts("seige. Your leader, Doshun, is already forming plans");
puts("on how to get inside. Doshun is a clever man and a");
puts("respected ninja. But as night approaches, you can't");
puts("help feeling that the time to strike is now.\n\n");
puts("You stare at the castle wall. You know you could get");
puts("inside. Then you could spy on the enemy or set fires");
puts("that would drive the enemy leader, Kuranosuke from");
puts("hiding. But Doshun is your leader. He will have a plan,");
puts("and it might be best to find out what it is.\n\n");
puts("a. To try to get inside the castle walls alone.");
puts("b. To wait for Dashun's plan.");
/*****************************************************************************/
}
return(0);
}
This is all that I have written so far, but I plan to continue it with more options. You can pretty much see where it is going. The program compiles without any warnings or errors. The do-while loop with the countdown and such works fine. However, if I do press the tilde ~ key, followed by enter, instead of waiting for the user input from the
scanf("%c", &xchoice);
the program simply stops running and the terminal just goes back to displaying my current directory. (I am writing on Linux for Windows.) This is obviously not the intended outcome. Also I did try inserting a loop to make getchar work until enter is pressed and that didn't work either. I also tried using getchar to read a single character in the same way as the above scanf statement, but that had the same outcome. I am sure that I am missing something obvious... but I just can't find it. Lastly, I was wondering if there was some better way to display a lot of text on the screen besides a bunch of puts("djfasjlaksdj");
Thanks a bunch!
The getchar function reads a single character for stdin. Unfortunately the terminal will not send any character to the program until you press enter... So this is why you need the user to type ENTER after the ~ for the getchar to return. However the ENTER is not read by getchar but gets read by the input which follows.
The best to do, since we have a line-oriented user interface, is to always read an entire line and then interpret it as a single char, a command or whatever. Best option to read a single line without running the risk to overflow is to use the fgets function.
addendum.
The suggestions to use scanf(" %c"...) is not good in my opinion. Image what happens if the user writes a string like "how are you?" when you ask for a single character...
Your getchar() and scanfs reads a character and stops reading from stdin, but when you enter an option you send at least 2 characters: the option you typed and \n. Your code reads just your option, and leaves the \n for the second call.
In order to avoid reading the end of line, or any other spaces or tabs, you should use scanf(" %c", &xchoice) (notice the space before %c).
And, another thing: your line:
if(xchoice=='A' || 'a')
does not work as expected. You should change it with:
if(xchoice=='A' || xchoice=='a')
After your input and hit the ENTER key or After printing the Input strings, If two characters are placed in the input buffer, they are namely: the entered character and the newline character due to ENTER key. The entered character gets consumed by the getchar() but the newline remains in the input buffer. so the \n is consumed by next scanf(). To avoid that Try with a space before %c-
scanf(" %c", &xchoice); // Fix 1
^ <-Note the space here
and
if(xchoice=='A' || 'a')
evaluates always true. how? You are checking your input with only A. Not with a. so if xchoice=='A' fails means, 'a' remains true always. So try
if(xchoice == 'A' || xchoice == 'a')) // Fix 2.
Just flush the input buffer before scanf
fflush(stdin);
good to go.
I have a simple program, intended simply to excercise my freshly gained knowledge of C.
Please keep in mind I have attempted to solve the problem of the newline leftovers remaining in the stdin buffer using the knowledge I already have. From the problems I was having before I figured out the newline issue, I have made considerable progress in getting this program to act the way I imagine it should. This is all I have left to debug and I am stymied. While my fluency in C is marginal, at best, I believe this program can easily work without a whole lot of modification.
The program asks the user to select a tool, of 2 simple tools I have constructed. The tools themselves work fine, but the cheesy 'pick-a-letter' UI that I've built has a bug I just can't figure out. It runs through the program as expected the first time, but the second time, the variable used for tool selection gets switched to a newline character, and the user input assignment for that variable gets overwritten. Therefore the program enters the switch construct used for the tool selection variable and activates:
case '\n':
which prints an error message indicating a newline got in the way, and breaks out to return to the beginning of the menu loop. On this third time around, the program will again work as expected. It will continue to alternate like this until you exit the program via the exit provided at the end of a normal program run.
This is a direct cut and paste of pertainant code, not included are the D_Time(); and cal(); functions. Feel free to compile and run with substitue functions to see the problem firsthand if need be. Both are void functions, one is a simple 2 argument calculator and the other displays date and time via stdout. And any other suggestions you have that could improve my knowledge of C or this program would be happily accepted and are sought. I am still learning, and although pointers and calculus escape me, i will get the hang of this.
void clrnl(void)
{
while (getc(stdin) != '\n');
} /* This is the fix that kind-of but not-really fixes the '\n' problem. Without it, the error message would pop up every time i used the menu, not including the first run. */
void menu(void)
{
char tool = 1;
int r = 0;
while (r != 1)
{
printf("\n ---Select a tool.---\n\n ------------------\n\n C = Calculator\n\n D = Date/Time\n\n ");
tool = getc(stdin);
clrnl(); /* This seems to be the only line where clrnl(); has a positive effect. */
switch (tool)
{
case 'D':
printf("\n You selected Date/Time ");
D_Time();
r = 1;
break;
case 'C':
printf("\n You selected Calculator ");
cal();
r = 1;
break;
case 'd':
printf("\n You selected Date/Time ");
D_Time();
r = 1;
break;
case 'c':
printf("\n You selected Calculator ");
cal();
r = 1;
break;
case '\n':
printf("\n Error!! -- Newline character detected!! Try again.\n\n");
r = 0;
break;
default:
printf("\n Error!! -- Unknown. Try again.\n\n");
r = 0;
break;
}
}
}
int main()
{
char lx;
do
{
menu();
printf("\n Enter 'x' to exit.\n\n ");
scanf(" %c", &lx);
if (lx != 'x')
{
continue;
}
}
while (lx != 'x');
return 0;
}
Usually a context menu is not waiting for the user to press enter before getting the option while your loop does it.
In order to select the option when pressing the relevant key instead waiting for the "enter" you can call OS specific functions. Under linux reconfigure your terminal using system ("/bin/stty raw") just before entering in your while loop and than leave things as they are. Under windows consider _getch() instead of getc(stdin).
Remember that getchar() and getc() return an integer and not a char.
Doing this you have a more reactive menu and you don't need to handle the extra chars generated.
The problem is when you input your selection, for example D, and you press enter key, various things can happen. If you're on windows, your application will recieve characters: 'D', '\r', '\n'. On linux, it will be 'D','\n'. To eat up any extra input read by scanf use this simple trick:
scanf(" %c*", &lx);
The * in format string will skip your carriage return and newline characters.
This is changed code for tool selection:
printf("\n ---Select a tool.---\n\n ------------------\n\n C = Calculator\n\n D = Date/Time\n\n ");
scanf(" %c*", &tool);
This is the part for the exit input:
printf("\n Enter 'x' to exit.\n\n ");
scanf(" %c*", &lx);
You can further put more switch cases together like this to reduce code duplication:
case 'D':
case 'd':
printf("\n You selected Date/Time ");
D_Time();
r = 1;
break;
This will work, because there's no break statement after case 'D', so if this case happens, the code continues pass the case 'd': line into the corresponding code.
I want to use kbhit() for "Press any key to continue" function.
However, after I used the kbhit() in a loop, the key-pressed is stored in the stdin.
So in the next scanf(), the key-pressed from before, appears in the input.
int x,b=0;
printf("Press any key to continue...")
while (b==0) {
b=kbhit();
}
system("cls");
printf("Enter number:");
scanf("%d",&x);
So, if the user pressed a key, lets say the letter K, the k appears after "Enter number:".
I've tried looking for solutions, but failed to make any of them work.
I tried to put a backspace character in to the input stream.
I also tried using getch(), however, the user has to press "Enter" in order to continue, so it defeats the original purpose.
I also tried clearing the stdin stream, by closing and opening, but I can't get it to open properly.
EDIT: As what janisz said in the comments, all I needed is to use system("pause"). Although I can't edit As what janisz said in the comments, all I needed is to use system("pause"). Although I can't edit the "Press any key to continue", its sufficient for my purpose. I will continue trying other solutions provided here for better results if possible, but for now, system("pause") is want i need.
EDIT2: Ok, some of you suggested using getch(). From what I saw online, getch() function gets the input from the stream without the char actually showing on the screen, which is what I want. However, when I tried using getch(), the program doesn't continue after I press any key, it waits for me to press the enter key. Is there a problem? I'm using C-Free 4 Standard on Windows 7.
kbhit() returns an integer value indicating whether the user has pressed a key or not. Please note that the key pressed still remains in the buffer. All you have to do is to flush the stdin buffer by using fflush(stdin) statement.
However if you want to use the key pressed by the user you will have to use a getch() or scanf statement after you have used kbhit().
You may read a good article on "How to use kbhit in C and C++" here for exact usage instructions.
see http://support.microsoft.com/kb/43993
essentially, insert this code after you read the character you want:
while (kbhit()) getch(); //clear buffer
fflush (stdin) ; // clear stdin's buffer
you need to flush both the bios kb buffer and stdin.
#include <windows.h>`#include <windows.h>
#include <stdio.h>
#include <conio.h> // for kbhit() only
#include <stdbool.h> // for booleans
void cleaningBuffers()
{
fflush(stdout); // always ok & need!
while (kbhit()) getch(); // clear buffer
if ( fflush(stdin) == 0 ) {;} // undefined, not enough
// flush the bios kb buffer:
if ( fflush(__iob_func()) == 0) {;} // now ok
}
and console buffers is clear...
you should consider flushing the input stream after the key was pressed
int x,b=0;
printf("Press any key to continue...")
for(;;){
if(kbhit()){
fflush(stdin);
break;
}
}
system("cls");
printf("Enter number:");
scanf("%d",&x);
Now your x variable is clean and pretty :)
Try this
while(!kbhit());
getch();
kbhit() is in conio.h, it's a console function. It will not be affected by rediction (but fflush will!). Thus to "eat off" the key pressed, you should use getch(), which is also a console function. As an added bonus, it will only eat off one character, not all.
Edit: Only on rereading your question i wonder: why not use getch() just like that? The kbhit() is useless, unless you do something in the loop.
Furthermore, the POSIX compliant function names would be _getch() and _kbhit() (at least on planet Microsoft).
u can use getchar()...it'll scan and also display onscreen
I'm starting to learn C now and i'm trying to figure out how I would go about capturing when the user hits "enter." I'm looking particularly at the scanf and getc functions but I'm not quite sure how to go about it. When the user hits enter I want to perform some operations while waiting/watching for him to hit enter again... Is "enter" a new line character coming in from the console? Any advice would be much appreciated!
You can check the ascii value using fgetc().
while(condition) {
int c = fgetc(stdin);
if (c==10) {//Enter key is pressed
//your action
}
}
If you just need the input when user presses enter as input you can use scanf or getchar. Here is an example from cplusplus.com
/* getchar example : typewriter */
#include <stdio.h>
int main ()
{
char c;
puts ("Enter text. Include a dot ('.') in a sentence to exit:");
do {
c=getchar();
putchar (c);
} while (c != '.');
return 0;
}
This code prints what you entered to stdin (terminal window).
But if you do not want the input ( i know it's really unnecessary and complicated for a new learner) you should use an event handler.
printf("Hit RETURN to exit"\n");
fflush(stdout);
(void)getchar();
Ref: comp.lang.c FAQ list ยท Question 19.4b
The C language is platform-independent and does not come with any keyboard interaction on its own. As you are writing a console program, it is the console that processes the keyboard input, then passes it to your program as a standard input. The console input/output is usually buffered, so you are not able to react to a single keypress, as the console only sends the input to the program after each line.
However! If you do not demand your console application to be platform-independent, there is a non-standard library <conio.h> in some Windows compilers that has a function called getche();, which does exactly what you want - wait for a single keypress from the console, returning the char that was pressed.
I am confused about getchar()'s role in the following code. I mean I know it's helping me see the output window which will only be closed when I press the Enter key.
So getchar() is basically waiting for me to press enter and then reads a single character.
What is that single character this function is reading? I did not press any key from the keyboard for it to read.
Now when it's not reading anything, why does it not give an error saying "hey, you didn't enter anything for me to read"?
#include <stdio.h>
int main()
{
printf( "blah \n" );
getchar();
return 0;
}
That's because getchar() is a blocking function.
You should read about blocking functions, which basically make the process wait for something to happen.
The implementation of this waiting behavior depends on the function, but usually it's a loop that waits for some event to happen.
For the case of the getchar() function, this probably is implemented as a loop that constantly reads a file (stdin for this case) and checks weather the file is modified. If the file is modified, the loop behaves by doing something else.
The getchar() function will simply wait until it receives a character, holding the program up until it does.
A character is sent when you hit the enter key; under a Windows OS, it will send a carriage return (CR) and a line-feed (LF).
See this CodingHorror post for a nicely put explanation.
(...the explanation of the CR+LF part, not the getchar() blocking part)
Try this:
#include <stdio.h>
int main(int argc, char *argv[])
{
char ch;
printf("I'm now going to block until you press something and then return... ");
ch = getchar();
if (ch >= 0)
printf("\nYou pressed %c\n", ch);
else
printf("\nAliens have taken over standard input! Run!\n");
return 0;
}
getchar() will cause your program to go to sleep until a keyboard (or whatever is attached to stdin) interrupt is received. This means it's blocking, no additional code will execute until getchar() returns.
It's very, very helpful to look at the return value of a function in order to understand it.
Any function may block, unless it provides some mechanism to prevent blocking. For instance, open() allows a O_NONBLOCK flag which is helpful for opening slow to respond devices like modems. In short, if it gets input from a terminal or has to wait to get an answer from the kernel or some device, there's a very good chance it might block.
getchar() blocks your program's execution until a key is pressed. So, there's no error if no key is pressed, getchar() will wait for it to happen :)
You can learn more about how getchar behaves here:
http://www.cppreference.com/wiki/c/io/getchar
...this should answer your question:)
I think what confuses you is that the Enter key is needed befor the program continues. By default, the terminal will buffer all information until Enter is pressed, before even sending it to the C program.
see discussion of Enter problem here