do
{
randomNum = (topBorder + lowBorder)/2;
printf("Your number is: %d?\n",randomNum);
printf("My number is(larger-l/smaller-s/correct-c): ");
scanf("%c", &compare);
printf("\n");
if (compare == 's') {
topBorder = randomNum;
}
else if (compare == 'l') {
lowBorder=randomNum;
}
else if (compare == 'c') {
printf("I like that you take my number.\n");
return 0;
}
} while (compare = 1);
Program work correct but I do not know why write double time *Your number is: (number) My number is(...):
./pcIsUser
Please, guess number between 1 and 100.
Your number is: 50?
My number is(larger-l/smaller-s/correct-c): l
***Your number is: 75? My number is(larger-l/smaller-s/correct-c):***
Your number is: 75?
My number is(larger-l/smaller-s/correct-c): s
***Your number is: 62?
My number is(larger-l/smaller-s/correct-c):***
Your number is: 62?
My number is(larger-l/smaller-s/correct-c): c
I like that you take my number.
Problem
while (compare = 1)
it's assigning 1 to compare.
You need
while (compare == 1)
and you will never get a 1 from scanf() so perhaps just
while (compare)
works, also
scanf("%c", &compare);
is taking the previous '\n' left in the stdin, so this
scanf(" %c", &compare);
would explicitly skip whitespaces and solve the problem.
You should also check the returned value of scanf() to ensure that nothing unexpected happened like someone sending EOF via pressing Ctrl+D on Linux or Ctrl+Z on Windows.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
int valid=0, running=1;
printf("\n1. Generate\n2. Retrieve");
while(!valid){
printf("\n\nEnter choice> ");
scanf("%d", &c);
if(c==1){
valid=1;
generate();
while(running){
printf("\n\nPress Y to generate again. Press N to retrieve> ");
scanf(" %c", retry);
if(retry == 'Y' || retry == 'y'){
idx++;
generate();
}else if(retry == 'N' || retry == 'n')
running = 0;
else
printf("Invalid input. Try again.");
}
retrieve();
}else if(choice==2){
valid = 1;
retrieve();
}else
printf("Invalid input. Try again");
}
Here the user should enter either 1 or 2. If the user enters any other number or character then I want to ask the user to input again. The program works fine if the user enters any other number like 5/6/7 etc. But if the user enters a character the program goes into an infinite loop. I can break the loop with a scanf status check but then the program stops. Instead, I want to prompt the user to input again if he enters anything except 1 or 2.
scanf returns the number of successful input assignments, or EOF on end of file or error. You should get in the habit of checking this return value. In this case of scanf( "%d", &c ), you should expect a return value of 1 on a successful input.
The %d conversion specifier tells scanf to skip over any leading whitespace, then read characters up to the first character that isn't a decimal digit, leaving that character in the input stream.
Example - suppose you enter "12.3" as an input. scanf( "%d", &c ) will read, convert, and assign the "12" portion of the input to c and return 1. The ".3" portion of the input is left in the input stream.
If you call scanf( "%d", &c ) again, the first thing it sees is that '.' character, so it immediately stops reading (you have a matching failure).
Since no input was actually read, nothing gets assigned to c and scanf returns 0. This will keep happening until you remove that '.' character with some other input operation like getchar() or scanf( "%*c" ), etc.
You should always check the result of scanf to make sure you read as many items as you expect:
int r = 0;
do
{
r = scanf( "%d", &c );
if ( r == EOF )
{
// end of file or error signaled on the input stream; in this case we
// just exit the program
exit( 0 );
}
else if ( r == 0 )
{
// matching failure - there's a bad character in the input stream
// remove it with getchar and try again
getchar();
}
} while( r != 1 );
// at this point we either have good input or have already exited the program
Apparently, using scanf with %d, but input characters causes buffer issues. See code below for one way to avoid the problem:
#include <stdio.h>
#include <stdlib.h>
void generate(){
printf("generate\n");
}
void retrieve(){
printf("retrieve\n");
}
int main(){
int valid=0, running=1, idx=0, c=-100;
char retry;
char s[25];
printf("\n1. Generate\n2. Retrieve");
while(!valid){
printf("\n\nEnter choice> ");
scanf("%s", s);
c = atoi(s);
if(c==1){
valid=1;
generate();
while(running){
printf("\n\nPress Y to generate again. Press N to retrieve> ");
while(scanf(" %c", &retry)==0);
if(retry == 'Y' || retry == 'y'){
idx++;
generate();
}else if(retry == 'N' || retry == 'n')
running = 0;
else
printf("Invalid input. Try again.");
}
retrieve();
}else if(c==2){
valid = 1;
retrieve();
}else
printf("Invalid input. Try again");
}
return(0);
}
One possible execution is shown below:
1. Generate
2. Retrieve
Enter choice> Bad
Invalid input. Try again
Enter choice> Worse
Invalid input. Try again
Enter choice> 1
generate
Press Y to generate again. Press N to retrieve> Y
generate
Press Y to generate again. Press N to retrieve> n
retrieve
I'm creating a conversion project for letters/numbers ASCII table. My code is supposed to be 'interactive', so the user would type 'y' or 'n' to answer questions on the screen. However, it doesn't want to do this twice...
I have tried:
Just trying numbers instead of characters, but it's not exactly what I want
The %[\n]*c, and %[\n]c, and %[\n]*s ... technique but it doesn't help ;-;
Testing in a different project, but the only way I am able to do it is for multiple scanf()s to be in a row.
Here is the code:
printf("Would you like to convert a number today? \n");
printf("Please press Y or N \n");
scanf("%c", &input);
if (input == 'y' || input == 'Y') { //compare input if they said 'yes'
printf("\nThank you! \nWhat number?\n");
scanf("%d", &number);
flag = test(number);
if (flag == 0) { //if there is an equivalent letter
letter = conversion(number); //find the equivalent letter
printf("\nYour Number \t ASCII letter\n");
printf("%d\t %c\n", number, letter);
}
}
else if (input == 'n' || input == 'N') {
printf("\nWould you like to convert a letter instead? This time enter 0 or 1\!\n\n"); //problem here!!
printf("I wish I could say it was to \' Spice things up \' ...but it\'s not ;-; \n\n");
scanf("%d", &input2);
if (input2 == 0) { //this needs to be checking whether the user input Y/y
printf("Great choice adventurer!\n");
printf("What letter will it be today?\n\n");
//..I would go to a different funtion here ie: test2(letter)...
scanf("%d", &number); //I showed that it worked with multiple numbers, but I can't get this to work with multiple letters
printf("%d", number);
}
if (input2 == 1) { //this needs to be checking whether the user input N/n
printf("Difficult to please, I see...\n\n");
printf("I suggest you move on with that attitude!\n\n");
printf("Bye bye then\n");
}
}
else { //if they tried to break the code
printf("Sorry I did not recognise your command...please retry\n");
printf("Press Y or N next time!\n");
}
The first check works perfectly, I just want the second check to be like the first!
Some 'solutions' caused a overflow, which I don't want if possible
Even if someone could explain why this isn't working the way I intended would be very helpful!
I'm not sure what confuses you.
Use
char foo;
scanf(" %c", &foo);
for single characters, eg. letters and
int bar;
scanf("%d", &bar);
for numbers, integers. If you type a letter instead, scanf() will fail.
%[...] is for strings.
scanf() returns the number of successful conversions (or EOF), so for
int height;
int width;
scanf("%d %d", &height, &width);
it returns 2 if successful. It might return 1 if only height could be read.
So to check for errors on user input you should do:
int height;
int width;
if (scanf("%d %d", &height, &width) != 2) {
// handle the error, maybe exit the program.
}
Your code could look like that (without error handling):
#define _CRT_SECURE_NO_WARNINGS // you said Visual Studio? Without it you should get
// warnings about some functions being insecure.
#include <ctype.h> // isalpha() returns true if the value is a letter
#include <stdlib.h> // EXIT_SUCCESS
#include <stdio.h> // puts(), printf(), scanf()
int main(void)
{
for(;;) { // for-ever ... endless loop since the user exits by answering
// 'n' or 'N' two times
puts("Would you like to convert a number today?\nPlease press Y or N:");
char input;
if (scanf(" %c", &input) != 1) // We reached EOF ... end of file
break; // that's improbable for stdin,
// but input could be redirected to
// read from a file instead.
if (input == 'y' || input == 'Y') {
puts("\nThank you!\nWhat number?");
int number;
scanf("%d", &number);
if (isalpha((char unsigned)number)) // *)
printf("\nYour Number \t ASCII letter\n%d\t %c\n\n", number, number);
else
puts("Sorry, but that's not the ASCII code of a letter :(\n");
}
else if (input == 'n' || input == 'N') {
puts("\nWould you like to convert a letter instead?\nPlease press Y or N:");
scanf(" %c", &input);
if (input == 'y' || input == 'Y') {
puts("\nGreat choice adventurer!\nWhat letter will it be today?");
char letter;
scanf(" %c", &letter);
if (isalpha(letter))
printf("\nYour letter \t ASCII code\n%d\t %c\n\n", letter, letter);
else
puts("Sorry, but that's not a letter :(\n");
}
else if (input == 'n' || input == 'N') {
puts("\nDifficult to please, I see...\n\nI suggest you move on with that attitude!\n");
puts("Bye bye then.");
return EXIT_SUCCESS;
}
}
else {
puts("Sorry I did not recognize your command... Please retry.");
puts("Press Y or N next time!\n");
}
}
}
*) isalpha() (and the other functions in <ctype.h>) expects a value that fits in a unsigned char or the value EOF. It has undefined behaviour for other values. Since we read user input into an int we cannot be sure that's the case so we have to cast the value to unsigned char before passing it to isalpha() (and friends).
Next time you ask a question please include your full code, including variable declarations, functions like test() and conversion() and #includes. But please, post an example that focuses on your problem at hand. All that dialog you included would not have been necessary.
I am fairly new when it comes down to C programmming. That's why i am working my way up by doing some of the easier exercises. The exercise i'm working on is the "guess the number" game, where the user must guess the number that lies between two numbers (upper and lower bounds). The program is doing what it must, with one exception: when the user enters a character instead of an integer, the program gets stuck in an infinite loop. The only way to break out of this loop is by using a break statement and restarting the program. What i want instead, is to have the program request for the users input again, untill an integer is entered.
Can someone tell me why the programm gets stuck in this infinite loop and why it is not requesting for input again trough scnanf like it did in the first iteration? your help will be appreciated. thank you.
//globals
int secret_nr;
int guess;
int upper_bound = 100;
int lower_bound = 1;
int total_guesses = 1;
void check_input(void) {
if (guess < lower_bound || guess > upper_bound) {
printf("Invalid input! Your guess must be between %d and %d\n", lower_bound, upper_bound);
}
else if (guess < secret_nr) {
printf("Higher\n");
total_guesses++;
}
else if (guess > secret_nr) {
printf("Lower\n");
total_guesses++;
}
else if (guess == secret_nr) {
printf("correct! You guessed the number after guessing %d times!\n", total_guesses);
}
}
int main(int argc, char* argv[]) {
srand(time(NULL));
secret_nr = (rand() % upper_bound) + 1;
printf("Guess the number between %d and %d:\n", lower_bound, upper_bound);
do {
if (scanf("%d", &guess)) {
check_input();
}
else {
printf("Invalid input! Only integer values are allowed!\n");
//break;
}
} while (guess != secret_nr);
return 0;
}
If scanf fails to parse its input according to the specified format, then the input will be left in the input buffer for the next call to scanf which will read the very same input and again fail. And so on and on and on...
The simple solution is to first of all read the whole line of input, using e.g. fgets. Then you can use sscanf in that (now extracted) input to attempt to parse it.
Further complicating your current code is the fact that if scanf fails in some other way, it will return EOF which is the integer -1, which is "true". That will of course lead to problems with your logic and looping as well.
I see this reply in another post: https://stackoverflow.com/a/1716066/5687321
scanf consumes only the input that matches the format string, returning the number of characters consumed. Any character that doesn't match the format string causes it to stop scanning and leaves the invalid character still in the buffer. As others said, you still need to flush the invalid character out of the buffer before you proceed. This is a pretty dirty fix, but it will remove the offending characters from the output.
char c = '0';
if (scanf("%d", &number) == 0) {
printf("Err. . .\n");
do {
c = getchar();
}
while (!isdigit(c));
ungetc(c, stdin);
//consume non-numeric chars from buffer
}
This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 6 years ago.
I'm writing a C program that reads an undefined amount of integers from the keyboard. No limits. The program has a loop that reads integers with scanf and stores the lowest and highest value to display. If the user enters a negative number or non integer, the loop ends and displays info (lowest and highest value).
NOTE: I DO NOT WANT USE BUILT IN FUNCTIONS LIKE "ISDIGIT" OR "FGET". No idea what they are and I don't want to "cheat".
I found out that my EOF value is -1. I tried putting "while(scanf("%d", &num) > -1)" in my loop. This just does nothing if you enter a char(keeps reading and never ends loop). It sometimes breaks the loop if you enter a double negative such a "--2". It doesn't work, anyways.
My problem is with my programs confusing behavior with my current code. Sometimes it does not keep or read a zero. Sometimes it only stores and displays the second highest value. Sometimes it display the second to highest or lowest value after I enter an character or symbol to trigger an end to the loop. Other times it works just fine. I tried some more logical statements to force the min to be zero if it's not equal to 1 and less than 1, but that didn't work either.
An example of the weird behavior...
Enter some integer values, EOF to quit...
0
1
2
3
4
e
not an int
The minimum value is 0
and the maximum value is 3
Can anyone explain why this is happening and offer a solution and/or hint? I've been searching and googling for hours now.
Thank You!
Here is my code...
int min;
int max;
int num;
printf(" Enter some integer values, EOF to quit...\n");
scanf("%d\n", &num);
min = max = num;
while(scanf("%d", &num) == 1)
{
if(num > max)
{
max = num;
}
else if(num < min)
{
min = num;
}
scanf("%d\n", &num);
}//while(scanf("%d", &num) == 1);
printf(" not an int \n");
printf(" The minimum value is %d\n", min);
printf(" and the maximum value is %d\n", max);
You can make this "work" with scanf, but it won't really work. scanf is ill advised for a large number of reasons.
For example, let's say we did this:
printf("Enter some integers, or ctrl-D to quit.\n");
while(scanf("%d", &input) != EOF) {
if(input > max) {
max = input;
}
else if(input < min) {
min = input;
}
}
Seems sensible, scanf returns EOF if it doesn't have any input. And it seems to work.
$ ./test
Enter some integers, or ctrl-D to quit.
230
-238
5
max: 230, min: -238
But what if we give it something that isn't a number?
$ ./test
Enter some integers, or ctrl-D to quit.
230
-238
5
ldsfkj
^D
^D
^D
^C
Why won't it stop? If it fails to read what's required, it leaves it on the stdin buffer. It tries to read ldsfkj, fails because it's not an integer, returns 0 (not EOF) because it didn't match anything. But ldsfkj is still in the buffer, so when it loops again it reads it again and fails again. This is the big flaw in scanf.
Ok, what if we check that it scanned something?
while(scanf("%d", &input) == 1) {
...
}
Again, seems to work great... until we enter something that isn't an integer. Then it just stops because scanf failed. This isn't the behavior we want.
$ ./test
Enter some integers, or ctrl-D to quit.
2039
-203
23.4
max: 2039, min: -203
The safe thing to do is to read input line by line and process it with sscanf. This separates reading the line from parsing the line. We don't have to worry about things getting stuck in the buffer, and we can do more with the parsing, like giving the user an error message.
printf("Enter some integers, or ctrl-D to quit.\n");
char line[256];
while(fgets(line, 256, stdin) != NULL) {
if( sscanf(line, "%d", &input) != 1 ) {
puts("Sorry, I don't understand that");
continue;
}
if(input > max) {
max = input;
}
if(input < min) {
min = input;
}
}
Note that we always check both min and max because it's now possible for the input to be both.
Note that we're using fgets instead of gets because gets will not limit its input to the size of the string, it can easily overflow its buffer.
The second part is making min/max code simpler. Instead of making the first number a special case that's both min and max, assign the largest possible integer to min, and the smallest possible integer to max. Then the first input is guaranteed to be both the min and max. These limits can be found in limits.h.
Here it is all together.
#include <stdio.h>
#include <limits.h>
int main() {
int min = INT_MAX;
int max = INT_MIN;
int input;
printf("Enter some integers, or ctrl-D to quit.\n");
char line[256];
while(fgets(line, 256, stdin) != NULL) {
if( sscanf(line, "%d", &input) != 1 ) {
puts("Sorry, I don't understand that");
continue;
}
if(input > max) {
max = input;
}
if(input < min) {
min = input;
}
}
printf("max: %d, min: %d\n", max, min);
}
There is a small glitch in that program. I leave it as an exercise for you to find it and fix it.
I am trying to get some user input, and I want to make sure that they enter integers, and if they don't I will just ask them to type again (loop until they get it right).
I have found a lot of different approaches to do this; some more complicated then others. But I found this approach which seems to work.
But I just don't really get why this is tested in the code:
scanf("%d%c", &num, &term) != 2
I can understand that scanf outputs the number of items successfully matched and assigned, but I don't get why it outputs 2 if it is an integer.
The code in C is:
int main(void)
{
int num;
char term;
if (scanf("%d%c", &num, &term) != 2 || term != '\n')
printf("failure\n");
else
printf("valid integer followed by enter key\n");
}
Trying to put it in loop:
int main(void){
int m, n, dis;
char m_check, n_check, dis_check;
do{
m = 0; n = 0; dis = 0;
m_check = ' '; n_check = ' '; dis_check = ' ';
printf("Please enter number of rows m in the matrix (integer): ");
if(scanf("%d%c", &m, &m_check) !=2 || m_check != '\n')
m_check = 'F';
printf("Please enter number of columns n in the matrix (integer): ");
if(scanf("%d%c", &n, &n_check) !=2 || n_check != '\n')
n_check = 'F';
printf("Should the random numbers come from a uniform or normal distribution?...
Please press 1 for uniform or 2 for normal: ");
if(scanf("%d%c", &dis, &dis_check) !=2 || dis_check != '\n' || dis != 1 || dis !=2)
dis_check = 'F';
}while(m_check == 'F' || n_check == 'F' || dis_check == 'F');
I've tried just inputting m = 3, n = 3, dis = 2, and then the loop just starts over and asks me to input number of rows. And if I when asked for this press f or something it just start looping like crazy over the printf-statements :)
scanf returns the number of fields it converted. You have the format string %d%c; it has:
%d - first field
%c - second field
so scanf returns 2.
If the user enters a number e.g. 123 and presses Enter, your num will be equal to 123, and term will be \n.
If the user enters a number with garbage at the end, e.g. 123garbage and presses Enter, your num will be equal to 123, the term will be g, and arbage\n will remain in the input buffer.
In both cases, scanf read an int and a char, so it returns 2.
A different example: the user enters garbage123. In this case, scanf will fail to read an integer, and return 0.
So your code checks for two different forms of incorrect output.
Entering an integer will match to the formatter %d and will assign the value to the variable num. The %c formatter will take the newline character ('\n') and store it in the variable term. scanf returns 2 cause 2 elements where correctly assigned (num and term)
If you don't enter an integer the formatter %d won't match correctly, and scanf won't return 2, producing a failure
Edit: Your do-while loop goes crazy cause your conditions in the last scanf are wrong (dis != 1 || dis !=2). It should be
if(scanf("%d%c", &dis, &dis_check) !=2 || dis_check != '\n' || (dis != 1 && dis !=2))
scanf("%d%c", &num, &term) != 2
This checks the return value of scanf . It will return number of arguments correctly matched . So , if a integer and a character is entered , they are store in vairables num and term and scanf returns 2 .
scanf will not return 2 if both the arguments are not correctly matched , in that case failure will be displayed as output.
Oops - now see OP wants to know why approached failed and was not necessarily looking for a how-to do it. Leaving this up as a reference as it does assert the fundamental problem: scanf(). Do not use it for user input.
If code truly needs to "get some user input, and wants to make sure that they enter integers", then use fgets() to get the line and then process the input.
Mixing user input with scanning/parse invariably results in some user input defeating the check, extra user input in stdin or improperly waiting for more input.
// true implies success
bool Read_int(int *value) {
char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) == NULL) return false; // EOF or error
// Now parse the input
char *endptr;
errno = 0;
long number = strtol(buffer, &endptr, 10);
if (errno) return false; // long overflow
if (number < INT_MIN || number > INT_MAX) return false; // int overflow
if (endptr == buffer) return false; // No conversion
while (isspace((unsigned char) *endptr)) endptr++;
if (*endptr) return false; // non-white-space after number
*value = (int) number;
return true;
}