This question already has answers here:
Skipping over Scanf statement in C
(4 answers)
Closed 8 years ago.
I am writing an objective c program for hangman. I need to replicate another program which has been given to me. I have done most of it, but am having an issue. It has to replicate the other program exactly, so I went into the other one and entered a character into the wordlength. It came up with the "number must be between 3 and 14 (inclusive)" statement, and asked me to enter a number again, but it started to loop infinitely. It works when i enter a number lower than 3 and larger than 14 (comes up with the error and asks for another input) but with a letter it infinitely loops. Also, the loop is meant to loop infinitely until the word length is larger than 3 and less than 14. That is why the while loop will loop infinitelyAny ideas??? Thanks
while (i == 0) {
printf("\n\n > Please enter a word length: ");
scanf("%i", &wordLength);
printf("\n\n");
if (wordLength > 3 && wordLength < 14) {
continue;
}
else printf("number must be between 3 and 14 (inclusive)");
}
The main problem (that you seem to be asking about) here is that you don't check for errors from the scanf call. It will return with the number of successfully scanned items, or zero if none were scanned, or EOF on error.
If scanf fails to extract data from the input, like when you ask for an integer but the user write a letter, then that letter will continue to be in the input buffer, so the next call to scanf will see that letter again. And again and again...
The best way to fix this is to read the whole line, as text, into a buffer, and then try to parse the integer from this buffer (using e.g. sscanf):
char input[16];
if (fgets(input, sizeof(input), stdin) == NULL)
{
printf("Error reading your input\n");
exit(0); /* Do whatever error handling you want */
}
if (sscanf(input, "%d", &wordLength) != 1)
{
printf("Error: Input was not a valid integer\nPlease try again: ");
fflush(stdout);
continue;
}
Problem is with while (i == 0){ you never change i in the loop. You may want to update it to
while (wordLength == 0){
But make sure you do wordLength=0 before the loop.
change the value of i for the loop to terminate. you dint change the value of i anywhere inside loop.
continue;
will not exit the loop, it will just skip the statement after continue statement and start the loop again. To exit the loop use
break;
so use break or change the value of i to some value other than i=0 to exit the loop.
I think you meant break instead of continue:
if (wordLength > 3 && wordLength < 14)
break;
break will take you out of the loop, whereas continue skips to the next iteration of the loop (which , as others have mentioned, never terminates because i is never changed)
Do not forget to break your loop when the condition is met.
while ( 1 ){
printf("\n\n > Please enter a word length: ");
scanf("%i", &wordLength);
printf("\n\n");
if (wordLength > 3 && wordLength < 14) {
break;
}
else printf("number must be between 3 and 14 (inclusive)");
}
Related
I have a loop that is stopped once a flag is set to 1.
scanf("%d", &next);
scanf("%d", &next1);
int done=0,next,next1;
while (done==0) {
printf("%d,%d.",next,next1);
if (getchar()=='\n') {
scanf("%d", &next);
scanf("%d", &next1);
}
//if not, set flag and stop looping
else{
done=1;
}
}
It scans for 2 numbers from every line of input every loop until there are no more lines of the input left. I thought this would work fine but I encountered a problem when I tested out the following input:
1 0
1 1
1 2
1 3
The output should be
1,0.
1,1.
1,2.
1,3.
but instead it prints the last loop twice like this:
1,0.
1,1.
1,2.
1,3.
1,3.
Why does this scan the last line twice before terminating? is there a character I can check for so it ends after it prints the first "1,3."?
I would suggest something like that
int main(){
int next,next1;
scanf("%d", &next);
scanf("%d", &next1);
while (getchar()=='\n') {
printf("%d,%d.\n",next,next1);
scanf("%d", &next);
scanf("%d", &next1);
}
}
by this way you save a little bit of memory, and is more readable. The output should be correct now, try by yourself.
scanf() -
If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.
So, when the no more lines of the input left, the scanf() returns EOF and the while loop iterate because done is not set to 1 yet and printf() prints the value stored in next and next1 one more time. That's why the last entered value printed twice. After this the condition if (getchar()=='\n') fails and done set to 1 and while loop exits.
You can do:
int done=0,next,next1;
while (done==0) {
if (scanf("%d%d", &next, &next1) != EOF)
printf("%d,%d.",next,next1);
else
done=1;
}
Or
while (scanf("%d%d", &next, &next1) != EOF)
printf("%d,%d.",next,next1);
I have a program where I want the input integer to be between 2 and 64 inclusive, so I put scanf inside a do { ... } while loop. Here's the code I initially tested:
int initialBase;
do {
printf("Initial base: ");
scanf("%i", &initialBase);
} while (initialBase < 2 || initialBase > 64);
The problem is whenever the input is not a valid integer, it just outputs the printf statement indefinitely and no longer prompts for user input, instantly flooding the console. Why is that happening and what's a better way of reading input that satisfies the conditions I want?
When scanf() fails, the argument is not automatically initialized, and uninitialized values could be any value, so it might be less than 2 or greater than 64 no one knows.
Try this
int initialBase;
/* some default value would be good. */
initialBase = 2;
do {
printf("Initial base: ");
if (scanf("%i", &initialBase) != 1)
break;
} while ((initialBase < 2) || (initialBase > 64));
the check will break out of the loop if you input something that is not a number, the initialiazation of initialBase is just a good habit which in your case could have prevented the behavior you describe, but in this case it's there to prevent accessing an uninitialized value after the while loop.
The reason the loop didn't stop, was because scanf() leaves some characters in the input stream when they are not matched, and calling scanf() again while those characters are still there will make scanf() keep waiting for valid input, but returning immediatly with the currently invalid input that is in the stream, if you want to keep reading, try reading characters from the stream until a '\n' is found, this way
int initialBase;
initialBase = 0;
do {
printf("Initial base: ");
if (scanf("%i", &initialBase) != 1)
{
while (fgetc(stdin) != '\n');
continue;
}
} while ((initialBase < 2) || (initialBase > 64));
I'm currently trying to get a users input and see if it is valid, i.e whether or not they have entered an integer versus a string, however, my program does work in realizing the user hasn't entered an integer given it goes to the else statement, except it doesn't restart the loop but rather just prints the words "please try again" a million times in a infinite loop. I've tried implementing the continue statement, but it seems to create the same issue, any input would be much appreciated!
Here is a snippet:
int userInput;
int exit;
exit = 0;
while(exit == 0)
{
if(scanf("%d",&userInput) == 1)
function(userInput);
else
printf("Please try again!\n"); //This loops infinite times, doesn't restart the loop and check input again like the first if
continue;
}
Just add
scanf("%*s");
Inside the body of the else to remove the invalid input from the stdin. You might also want to set exit to 1 when scanf is successful in order to prevent an infinite loop. So modify your code to:
int userInput;
int exit;
exit = 0;
while(exit == 0)
{
if(scanf("%d",&userInput) == 1) {
function(userInput);
exit=1;
}
else
{
printf("Please try again!\n");
scanf("%*s");
}
}
See this answer: https://stackoverflow.com/a/3852934/3788
The original code loops indefinitely because the invalid data (the
"gfggdf") is not removed from the input buffer when scanf fails to
convert it to an integer -- it's left in the input buffer, so the next
call to scanf looks at the same data, and (of course) still can't
convert it to an integer, so the loop executes yet again, and the
results still haven't changed.
This question already has answers here:
Check if input is integer type in C
(16 answers)
Closed 8 years ago.
I am working on code for one of my classes and I have hit a wall. I need the user to input a number that will be used as the number of times a for loop will be repeated. The first loop where I ask for this number is a while loop. I need to make sure the value entered is a number and not a letter or special character.
I do not know how to make sure that it is not a letter or special character.
The next problem is making sure that the for loop only runs for the specified number of times that is the number provided in the first loop.
This is what I have written so far.
#include <stdio.h>
int main()
{
int num_of_scores, n;
char enter;
float score=-1, total=0, average;
do
{
printf("\n\nEnter the number of quiz scores between 1 and 13: ");
scanf ("%d, %c", &num_of_scores, &enter);
}
while(num_of_scores<1 || num_of_scores>13/* && enter == '\n'*/);
printf("\nStill Going!");
for(n=0; n<num_of_scores; n++)
{
printf("\nEnter score %i: ", n+1);
scanf ("%f", &score);
while(score>=0 || score<=100)
{
total = total + score;
score = -1;
break;
}
}
average = total / num_of_scores;
printf("\nThe average score is %.0f.\n\n", average);
return 0;
}
So I have edited the code a little bit. There is a part in the first while loop that is in a comment which i removed because it made the program end after that loop. The printf("still going") is just a test to make sure the program gets that far. Any further pointers? I am still not sure how to check make sure a number is not entered. I though adding the && enter == '\n' would do it, but if it hangs the program it is no good. Many of the examples you have suggested are good, but i find them a little confusing. Thanks!
I'd check Check if input is integer type in C for the answer to this...
Check the return value of scanf. Per the man page:
RETURN VALUE
These functions return the number of input items successfully matched and assigned, which can be fewer than provided
for, or even zero in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching
failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see
ferror(3)) is set, and errno is set indicate the error.
do{
char ch = 0;
num_of_scores = 0;
printf("\nEnter the number of quiz scores between 1 and 13: ");
if(scanf("%d%c", &num_of_scores, &ch)!=2 || ch != '\n'){
int ch;
while((ch=getchar())!='\n' && ch !=EOF);
}
} while(num_of_scores<1 || num_of_scores>13);
int main() {
int input = 0;
do {
if(input > 1) {
printf("You entered");
break;
}
printf("Enter an integer (> 1): ");
scanf("%d",&input);
} while(input < 2);
return 0;
}
Hello, I'm new to C. Could anyone explain what break does? In this program, the statement before break "You entered" doesn't show up on the console. I know java but this works totally different.
There is no integer exist between 1 and 2. Change
if(input > 1)
to
if(input > 0)
After that if you enter 1 then program enters the if body then print You entered and on encountering the break statement, immediately terminates the do-while loop.
The "break" statement causes your code to exit the loop immediately.
You're not seeing any output because you only loop while the input is strictly less than 2, but your if statement is looking for input that's strictly greater than 1.
That's not going to work; if you enter 1, the if statement won't execute (because 1 > 1 is false), and if you enter 2, the loop exits immediately (because 2 < 2 is false).
You either need to loop while input <= 2, or you need to test for input >= 1.
Having said all that...
Standard output is usually line-buffered, meaning you won't see anything show up on your console until the buffer is full or you send a newline character. You either need to manually flush the stream or send a newline as part of the format string; either
printf("You entered");
fflush(stdout);
or
printf("You entered\n");
should work.