Wait for user input in while(1) loop - c

I'm trying to make a loop in C where the program calculates the avarage of 2 numbers and then waits for user input. If the user input is 'G' then the loop will break. However this is not working currently because it's (in a strange way) a infite loop.
My code is:
while(1){
pogingen++;
gem = (minimum+maximum)/2;
printf("%i",gem);
scanf("%c",&invoer);
if(invoer=='L'){
maximum = gem;
}
if(invoer=='H'){
minimum = gem;
}
if(invoer=='G'){
printf("%i",pogingen);
break;
}
}
I tested it with these values: minimum = 1, maximum = 10. The result will be an infite loop of 5's. It doesn't even wait for the user input (which it's supposed to do.)
Thanks in advance for looking at this!

It doesn't even wait for the user input (which it's supposed to do.).
The program is not waiting to get the input means there is some character left in input buffer. possibly \n from previous input. So clear the input buffer before reading input.
you can put,
getchar();
scanf("%c",&invoer);
before scanf() inside loop;

The reason it doesn't wait for user input in some instances, is because when scanf reads a character, you press the Enter key at the end of the of input, and that key is also stored in the input buffer. So the next iteration it will read that enter key.
This is easily solved by telling scanf to discard trailing whitespace (which the newline character is):
scanf("%c ",&invoer);
/* ^ */
/* | */
/* Notice extra space here */
You might also want to print some error message if the user doesn't give valid input. Also, consider using toupper, because the chances are the user will not give you an upper-case letter.
It might also be better to to use e.g. if ... else if ... else ... instead. Or possibly use a switch statement.

simple and sweet solution invoer=getchar(); that will wait for a character as well as store in to the variable.
no need to write scanf

invoer=getchar();
is a solution if you flush stdin before using it for the next iteration like so:
fflush(stdin);
invoer=getchar();

Related

Do..While loop doesn't stop to wait for uinput [duplicate]

This question already has an answer here:
How to read / parse input in C? The FAQ
(1 answer)
Closed 2 years ago.
I am implementing a super simple menu selection procedure with a basic input validity check mechanism. The legal inputs are {1,2,3} so the possible issues would be either a number that is out of this range, or a non integer. My code is shown below. This works fine for the former issue (i.e. when i input "4") but for the latter (when i try to input a char), it prints the invalidity message over and over again rather than waiting for a new input, it's like it skips the scanf line entirely on every iteration except the first.. what am I missing here ?
do{
try = scanf("%d", &selection);
if(try!=1 || selection < 1 || selection > 3){
printf("\nInvalid input. Dear guest, please enter '1', '2', or '3'.\n\nInput:");
}
}while(try!=1 || selection < 1 || selection > 3);
After entering a character which cannot be part of the text representation of a decimal number, say 'A', the input available to the program is the byte sequence 'A' '\n' (the latter being a newline), or perhaps 'A' '\r' '\n' on Windows (carriage return followed by a newline).
When scanf tries to parse a number from these characters it balks already at the 'A' and puts it back in the input stream. Input streams in C guarantee that you can perform at least one ungetc(), that is, put at least one character back into the stream so that it will be the first character read by the next input operation. This simple but ingenious facility makes it a lot easier to process variable-format input: Imagine you parse an expression in some C source code, and both integer literal or a variable name are syntactically allowed as the next token: You can try the number first, and if that fails, the input still contains all of the variable name to process. The work of keeping the first failing character "in mind" and making it available to other parts of the program is encapsulated in the FILE implementation.
This is what happens here. The first failing scanf() puts the 'A' back so that it will be encountered again by the next attempt, ad infinitum. The 'A' must be removed from the input. More specifically, the next "word" should be removed from the input altogether: The user may have entered "kkjkllkjlk", and you don't want 10 error messages for that. You can decide whether you would accept "lklkj2" (and read the 2) but it is simpler to discard the whole word.
You can also decide whether you would accept "1 2 3 2" as 4 valid successive inputs or whether you demand newlines between the numbers; for generality (for example, if the input does not come from a terminal) I would accept all number sequences separated by whitespace of any kind. In this case you simply want to read to the next whitespace:
#include <ctype.h>
// ...
while(!isspace(getchar())) { /* ignore */ }
This should do the trick. It is possible that more whitespace is following this one, including newlines etc., but that's OK: The symbolic input conversions of scanf (like %d) skip leading whitespace.
I think it is neat to let the user exit the program by ending the input (inserting end-of-file by pressing Ctrl-z in a Windows Console, or Ctrl-d on a Posix terminal), so I would test for the special case of scanf() returning EOF. If the input is from a pipe that may actually be essential. The fringe case that a bad input is immediately followed by EOF needs a check for EOF even in the code discarding wrong input (Posix: echo -n "a" | myprog would hang; -n suppresses the usual newline which echo usually appends). Putting it all together, my take on the input loop is this:
while(1) { // break on good input
printf("Please enter your choice of 1, 2 or 3:\n");
try = scanf("%d", &selection);
if(try!=1 || selection < 1 || selection > 3){
if(try == EOF)
{
return 0;
}
printf("\nThe input was not 1,2 or 3. Please try again.\n");
int discard;
{
do{
discard = getchar();
if(discard == EOF) { return 0;} // catches EOF after bad char
}while(!isspace(discard));
}
}
else break;
}

Program ends before I type A or D for bubble sorting [duplicate]

I'm trying to develop a simple text-based hangman game, and the main game loop starts with a prompt to enter a guess at each letter, then goes on to check if the letter is in the word and takes a life off if it isn't. However, when I run the game the prompt comes up twice each time, and the program doesn't wait for the user's input. It also takes off a life (one life if it was the right input, two if it wasn't), so whatever it's taking in isn't the same as the previous input. Here's my game loop, simplified a bit:
while (!finished)
{
printf("Guess the word '%s'\n",covered);
scanf("%c", &currentGuess);
i=0;
while (i<=wordLength)
{
if (i == wordLength)
{
--numLives;
printf("Number of lives: %i\n", numLives);
break;
} else if (currentGuess == secretWord[i]) {
covered[i] = secretWord[i];
secretWord[i] = '*';
break;
}
++i;
}
j=0;
while (j<=wordLength)
{
if (j == (wordLength)) {
finished = 1;
printf("Congratulations! You guessed the word!\n");
break;
} else {
if (covered[j] == '-') {
break;
}
}
++j;
if (numLives == 0) {
finished = 1;
}
}
}
I assume the problem is scanf thinking it's taken something in when it hasn't, but I have no idea why. Does anyone have any idea? I'm using gcc 4.0.1 on Mac OS X 10.5.
When you read keyboard input with scanf(), the input is read after enter is pressed but the newline generated by the enter key is not consumed by the call to scanf(). That means the next time you read from standard input there will be a newline waiting for you (which will make the next scanf() call return instantly with no data).
To avoid this, you can modify your code to something like:
scanf("%c%*c", &currentGuess);
The %*c matches a single character, but the asterisk indicates that the character will not be stored anywhere. This has the effect of consuming the newline character generated by the enter key so that the next time you call scanf() you are starting with an empty input buffer.
Caveat: If the user presses two keys and then presses enter, scanf() will return the first keystroke, eat the second, and leave the newline for the next input call. Quirks like this are one reason why scanf() and friends are avoided by many programmers.
Newlines.
The first time through the loop, scanf() reads the character.
Then it reads the newline.
Then it reads the next character; repeat.
How to fix?
I seldom use scanf(), but if you use a format string "%.1s", it should skip white space (including newlines) and then read a non-white space character. However, it will be expecting a character array rather than a single character:
char ibuff[2];
while ((scanf("%.1s", ibuff) == 1)
{
...
}
Break the problem up into smaller parts:
int main(void) {
char val;
while (1) {
printf("enter val: ");
scanf("%c", &val);
printf("got: %d\n", val);
}
}
The output here is:
enter val: g
got: 103
enter val: got: 10
Why would scanf give you another '10' in there?
Since we printed the ASCII number for our value, '10' in ASCII is "enter" so scanf must also grab the "enter" key as a character.
Sure enough, looking at your scanf string, you are asking for a single character each time through your loop. Control characters are also considered characters, and will be picked up. For example, you can press "esc" then "enter" in the above loop and get:
enter val: ^[
got: 27
enter val: got: 10
Just a guess, but you are inputting a single character with scanf, but the user must type the guess plus a newline, which is being consumed as a separate guess character.
scanf(" %c", &fooBar);
Notice the space before the %c. This is important, because it matches all preceding whitespace.
Jim and Jonathan have it right.
To get your scanf line to do what you want (consume the newline character w/o putting it in the buffer) I'd change it to
scanf("%c\n", &currentGuess);
(note the \n)
The error handling on this is atrocious though. At the least you should check the return value from scanf against 1, and ignore the input (with a warning) if it doesn't return that.
A couple points I noticed:
scanf("%c") will read 1 character and keep the ENTER in the input buffer for next time through the loop
you're incrementing i even when the character read from the user doesn't match the character in secretWord
when does covered[j] ever get to be '-'?
I'll guess: your code is treating a newline as one of the guesses when you enter data. I've always avoided the *scanf() family due to uncontrollable error handling. Try using fgets() instead, then pulling out the first char/byte.
I see a couple of things in your code:
scanf returns the number of items it read. You will probably want to handle the cases where it returns 0 or EOF.
My guess would be that the user is hitting letter + Enter and you're getting the newline as the second character. An easy way to check would be to add a debugging printf statement to show what character was entered.
Your code will only match the first occurrence of a match letter, i.e. if the word was "test" and the user entered 't', your code would only match the first 't', not both. You need to adjust your first loop to handle this.
When you enter the character, you have to enter a whitespace character to move on. This whitespace character is present in the input buffer, stdin file, and is read by the scanf() function.
This problem can be solved by consuming this extra character. This can be done by usnig a getchar() function.
scanf("%c",&currentGuess);
getchar(); // To consume the whitespace character.
I would rather suggest you to avoid using scanf() and instead use getchar(). The scanf()requires a lot of memory space. getchar() is a light function. So you can also use-
char currentGuess;
currentGuess=getchar();
getchar(); // To consume the whitespace character.

unexpected output with getchar()

char c = ' ';
while(c != 'x')
{
c = getchar();
printf("threadFuncParam = %u\n", threadFuncParam);
}
In the above code snippet the print is printing threadFuncParam value twice every time I enter a character where as I expect it to print only once.
As per my understanding very first time it enters while as condition is true and and then wait for user input at getchar call on entering a character it shall print the value and then if input character is not x it shall wait for another input at getchar call, but whenever i enter a character i see 2 prints ion screen for each input. I am not able to understand why?
What i'm trying to do here is that in main thread i am taking single char input from user and in worker thread i am incrementing a counter which gets incremented every second, i print the value everytime user input a char input until user enters 'x' character.
The simple issue here is that the console (input) sends the text to the stdin only when it encounters a enter key or ctr+d.
As a result an extra \n goes into your input stream. This causes your program to read that character in the next iteration.
A simple solution would be to read all white space characters in the stream.
This can be done in multiple ways -
If you need to discard any whitespace characters (including space, tabs, vtabs, newline), you can add
scanf(" ");
before the getchar();
If you need to discard only the newlines which come as a result of pressing enter, you can add
scanf("%*[\n]")
before the getchar();
This will eat up all the \n that come before the next character. But will not eat spaces.
Finally if you want to discard only 1 \n
You can do
scanf("%*1[\n]");
Remember though, in all the cases the scanf should be immediately before the getchar() because scanf would wait till it finds the next non white space character.
All cases figured out with the help of comments from #chux.
If you tried to debug your program (its best way to learn to code), you would spot that the second value is everytime 10. In ASCII table you would find that is code for new line. Which you are pressing after the every character. Then by fast & simple searching you would find this THREAD. Where is the problem described and you would easily solve it.
char c = ' ';
while(c != 'x')
{
printf("threadFuncParam = %u\n", (char)c);
fflush(stdout);
if (scanf(" %c",&c) != 1)
{
// failed
}
}
I think the problem is in the way logic is applied. You print before you check the condition. See this for explanation:
loop 1: getchar() executed say for value 'a'.
printf() executed.
loop 2: Because c='a', condition is true. Now, getchar() is executed with 'x' value.
printf() is again executed.
loop 3: Condition is evaluated false. Loop is terminated.
So basically you should change your logic a little bit.

C Ending a loop with user input

I'm trying to write a program that lets the user insert integer values into an array until they enter a specific key to stop, say ENTER, or X.
int array_numb[100];
char quit = 'x';
printf("Enter as many values into the array as you want, pressing x will end the loop\n");
while(1==1){
int i = 0;
scanf("%i",&array_numb[i]);
i++;
array_numb[i] = quit;
}
I know it's wrong but this is my thought process. Any ideas? thanks for the help
Enter as many values into the array as you want while having int array_numb[100];, at some point you will be in trouble. What if the user enters more than 100 numbers before entring the sentinel value? You'll be overruning the allocated memory, isn't it?
You should check the return value of scanf() to ensure proper input. A mismatch in the supplied format specifier and the type of input will cause scanf() to fail. Check the man page for details.
You need to have a break statement inside while(1) loop to break out. Otherwise, you need to have a conditional statement in the controlling expression for while() loop to terminate the loop.
Note: IMHO, the best way to stop scanning user input is to comapre the return value of scanf() against EOF, which can be produced by pressing CTRL+D on linux and CTRL+Z in windows.
You can check this answer for your reference.
The same thing can be achieved as shown below:
scanf() can fail and check the return value. When a character is scanned scanf() fails
int i=0;
printf("Enter as many values into the array as you want, pressing x will end the loop\n");
while(i<100 && scanf("%d",&array_numb[i])==1)
{
i++;
}
scanf, with %i, will fail to scan a number when invalid data, such as a character is inserted and will return 0(in your case) if it fails.
Just check the return value of scanf. If it is zero, use
if(getchar()=='x') //or if(getchar()==quit)
break;
Note: Clear/flush the standard input stream(stdin) using
int c;
while((c=getchar())!='\n' && c!=EOF);
after the loop as well as after the break; .
You could learn something and use signals:
http://man7.org/linux/man-pages/man7/signal.7.html
Register SIGINT, override it, let it check which key was pressed, then let it change a variable. In your loop check if this variable is 0 or 1.
Signals have top priority, signal code will be executed no matter the loop.
Example: http://www.thegeekstuff.com/2012/03/catch-signals-sample-c-code/
It's overkill for this case but a fun thing to know. Signals are the way how an OS is managing events, like process kills, keyboard input etc. Be warned, how to use this is OS specific and has not much to do with C itself.

scanf() is getting skipped

Hi
Just started learning c for uni (usually use objective c) and have run into a strange issue with scanf, i have the following code
while(stringCheck == 0){
scanf("%c",&computerType);
computerType = toupper(computerType);
if ( computerType == 'L') {
/*set stringCheck to 1 so the scanf while loop breaks*/
stringCheck = 1;
counter = 0;
} else {
printf("ERROR\n");
}
}
This i printing out "ERROR" then asking for input (so it is skipping the scanf statment the first time). If i change the it to another variable that is a string it works fine, it stops on the first time.
The rest of the code works fine, its just the fact that it print an error as soon as it enters the loop that is annoying.
I have tried getChar() and it does the same thing.
Thank you for any help you have to offer.
If it's printing an error the first time you enter the loop, then there's already something in the input buffer. I'll guarantee (assuming your compiler is not brain-dead) that it is not skipping the scanf. You should check what it's actually receiving by changing:
printf("ERROR\n");
to:
printf("ERROR, code = %02x\n", computerType);
I would suggest that it's the newline from the last time your program ran that code (you say it's the first time but it's unclear as to whether you mean the first time into that loop ever (since program started) or first time entering that loop but you've been through it before on this program run.
When you enter LENTER the first time, your code will pull out the L but not the ENTER. If you then call that code again, it will get the ENTER key.
You should either understand and allow for what's actually entered or use a safe and sound input function like this one.
You should always check the return value from scanf(); it tells you how many of the conversions succeeded. In this context, if you don't get back 1, you have a problem. The first time around the loop, scanf() reads a character - but not an ell (l or L) because you say you get an error message. The next iteration attempts to read the newline or whatever else follows the previous erroneous character, and the newline is certainly not an ell, and the other characters quite likely aren't an ell either, thus producing at least one more error message. You would get an error printed for each non-ell character.
Generally, if you use scanf(), it is fairly hard to recover from errors. You're likely to be better off reading a line into a buffer (character array) and use sscanf() to parse it.
You should just need to add a space before %c. I am unsure why it works, but it does. This also happens with other data types.
Replace your scanf statement with scanf(" %c",&computerType);

Resources