Entering while loop repeatedly before stopping at getchar() - c

I'm writing a simple C program in which I want to validate my user's input for integers from 1-9.
The logic for my code seems fine but for some reason if I type "lll" for my input (or any other random input not between 1-9), it will show the error message inside the while loop a couple of times before actually stopping at the getchar() once again.
/**
* Validate user input and reprompt if invalid
* #return input - Users valid input
*/
int validateUserInput() {
int firstInput = getchar() - 48;
int secondInput = getchar();
while(secondInput != 10 || firstInput >= 10 || firstInput <= 0 ){
printf("Invalid Input. Please try again. \nEnter a number between (1-9): ");
firstInput = getchar() - 48;
secondInput = getchar();
}
return firstInput;
}
The logic is that:
Invalid Input - If the second input != 10 which means that the second char is something other than the enter key.
Invalid Input - If the first char subtracted 48 is higher than 9 or less than 1 then it's too high.
The logic seems fine to me but here's some output when I enter random characters:
Enter a number between 1-9: lllll
Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9:
Why does it repeat that message so many times before actually letting me enter input again? This is all that's wrong with my program.

Your logic is fine. But the invalid characters you input still remain in the input buffer. So, the subsequent calls to getchar() read them.
Whenever you hit an invalid input, you want to ignore them all. You can read them out using a loop like this:
while(secondInput != 10 || firstInput >= 10 || firstInput <= 0 ){
printf("Invalid Input. Please try again. \nEnter a number between (1-9): ");
int i;
while((i=getchar()) != '\n' && i != EOF);
...
Having said that it's generally hard to use getchar() and scanf() family functions to correctly read interactive input and do error checking. A better way would be to read lines (such as fgets()) and parse/error check them.

Because you entered 5 chars. 5x L. You are checking only one char, but by what did you wrote I guess you want to check whole input charr array. So then you cant use getChar().

Related

Check if user input is between 1 and 10

part of the program that i am working on is to get a number from the user , but the condition is that it has to be any number between 1 and 10 nothing else, so how could i force the user to only input one of these specific numbers , so that if he wrote any other number or a character , an error message to pop out and repeat the process till he choses correctly
here is the code
// getting a number from the user
int number;
printf("Please pick a number from 1 to 10 : ");
scanf("%d",&number);
printf("Oh ! You have chosen %d\n", number);
// what should i do here ?
C allows for very nice input control, but it is not free... Said differently you cannot rely on the language nor on the standard library but have to code everything by hand.
What you want:
control that the input is numeric
control that the number lies between 1 and 10
How to:
control the return value of the input function
if you got a number control its value
if you got an incorrect input (optionaly) give a message and loop asking
Possible code:
int number;
for (;;) { // C idiomatic infinite loop
printf("Please pick a number from 1 to 10 : ");
if (scanf("%d", &number) != 1) {
// non numeric input: clear up to end of line
int c; // c must be int to compare to EOF...
while ((c = fgetc(stdin)) != EOF && (c != '\n'));
}
else if (number > 0 && number <= 10) break; // correct input: exit loop
// error message
printf("last input was incorrect\n");
}
printf("Oh ! You have chosen %d\n", number);
If you want a more user friendly way, you could use different messages for non numeric input and incorrect values, but it is left as an exercise for you... (I am afraid I am too lazy ;-) )
What you likely envision is a fine-grained control over the character-by-character input of the user; for example, anything but digits should be impossible; or when they type a 2 and try to type another digit, that should be impossible, too.
That's something we know from graphic user interfaces. It requires that your program is "informed" about every key stroke at once.
For historical reasons, this capability is not part of the C standard library. The reason is that historically all kinds of input devices were used, for example punch cards or paper-based teletypes. The communication was line by line: Input was local until the user hit the aptly named "enter" key. Any stupid device can do that, a lowest common denominator which is why all languages which do not define GUI elements adhere to it.
Obviously, character-by-character input is entirely possible on modern terminals and computers; but it is system specific and has never been standardized in the language. It is also likely more complicated than meets the eye if you want to give the user the opportunity to edit their input, a phase during which it may be "illegal". In the end you'll need to catch the point when they submit the entire value and validate it, which is something you can do even with the crude facilities that C provides.
Hints for an implementation:
Let the user complete a line of input. Validate it, and if the validation fails, prompt for another attempt. Do that in a loop until the input is valid.
Use scanf because it is convenient and error free (compared to home-grown input parsing).
This is something often overlooked by beginners: Check the return value of scanf which will indicate whether the input could be parsed (read the scanf manual!).
int main()
{
int number = 0;
while (number < 1 || number > 10)
{
printf("please enter number between 1 - 10\n");
scanf("%d", &number);
if (number < 1 || number > 10)
{
printf("you entered invalid number!\n");
}
}
return 0;
}
while(1)
{
//input ....
if(number<0 || number>10)
{
// print error
continue;
} else {
while (getchar() != '\n') ;
break;
}
}
I think I made a mistake at the beginning.A character can be checked by if but scanf can't. If scanf can't get the input in the specified format, the illegal input in the input buffer will be kept all the time.
After looking at another question, I thought that when the input is wrong, we should use getchar() to clear the buffer before the next input.

While using scanf("%i",var) if the user enters a letter or just presses enter i get a problem

I want for my program to just ask again if the user entered a letter or just pressed enter.
I know that if the input is not a number scanf() will return 0, so i have been doing this:
int variable;
printf("Please write an integer and then press enter: \n");
if (scanf("%i",&variable)!= 1) { /* ERROR CODE */; return 1;}
return 0;
But i dont want for my program just to stop if the input is not correct. So i tried this:
int variable;
do
{
printf("Please write an integer and then press enter: \n");
} while (scanf("%i",&variable) != 1);
But the program will just start printing "Please write an integer and then press enter:" without stoping. Is there a way of doing this?
edit: Forgot the &
edit2: Thanks to everybody.
edit3: I have been looking into the functions. Will this code be correct?
char variable[10]; int var;
do
{
printf("Please write an integer: ");
fgets(variable,sizeof(variable),stdint);
} while( sscanf(variable,"%i",&var) != 1 );
I have tried it and it works but i post it here because i know im probably missing something.
int variable;
do {
printf("Please write an integer and then press enter: \n");
} while (scanf("%i", &variable) != 1 && scanf("%*[^\n]") == 0);
The second scanf discards characters till the '\n' character. The '\n' character remains, though it will be skipped by the first scanf on the next iteration of the loop.
The code has some defects but it will work in most cases. One defect is that, if scanf returns EOF without reading a character then the loop will exit but the value of variable will be indeterminate, which can cause undefined behaviour when used. This one is not difficult to cure. Another one is that, the behaviour is undefined if the user enter a number outside of range for int. So a way better approach, is to use fgets and strtol library functions.

Input Restriction in C

I'm having a bit of a problem restricting the user input. I only want the integers 1,2 or 3 to be the input. Do.. while loop does the job for invalid integer inputs, but how do I disregard string/character inputs? I also need to ask the user repetitively if ever the input is invalid.
Update:
int problem;
printf("Please select the problem that you want to solve:\n");
printf("\t 1-Problem 1\n");
printf("\t 2-Problem 2\n");
printf("\t 3-Problem 3\n");
while( scanf("%d", &problem)==0 && (problem!=1 || problem !=3 || problem !=2))
{int c;
while((c=getchar())!='\n' && c!=EOF);
printf("Please select the problem that you want to solve:\n");
printf("\t 1-Problem 1\n");
printf("\t 2-Problem 2\n");
printf("\t 3-Problem 3\n");
}
It kinda looks messy because of the multiple printfs. I just don't want lengthy codes in one row. Anyway, I wanted only 1,2, or 3 as inputs. If the entered input is invalid, the program asks the user again until the user inputs a valid input.
The code works for invalid inputs such as words, letters, characters, etc. However, if the user inputs 1.2 , it proceeds with 1 which should not be the case. 0 isn't accepted either. What can I do to my code to restrict them?
scanf with a %d will fail and return 0 in case of invalid inputs(like character(s)). So, just check if the scanf failed by checking the return value of it.
while(scanf("%d",&num)==0 && (num<=1 || num >=3)) //Invalid input if this is true
{
int c;
while((c=getchar())!='\n' && c!=EOF); //Clear the stdin
printf("Invalid input. Try again\n");
}
The line
while((c=getchar())!='\n' && c!=EOF);
clears the standard input stream so that scanf does not read the invalid input again and again resulting in an infinite loop.
Note that scanf can return EOF. This will cause the program to think that the user has entered valid input. You can add a check to see if the return value from scanf isn't EOF. Also, you should initialize num to a number that is not 1,2 or 3 to avoid invoking Undefined Behavior.

why does my int while loop keeps going when i scan for a number?

I'm having a problem with a while loop. I have to enter a number which is bigger than 0 and below 81. when I use numbers like -1,0,1,2,82 it is going good and I get the expected result, but when I use a letter it keeps going through my while loop. I've used the debugger in eclipse and when I'm at the while loop amount is automatically set to '0' because of the failed scanf. Why does it keep looping when I insert a letter?
#include <stdio.h>
#include <stdlib.h>
int main(){
int amount = 0;
printf("Give a number:\n");
fflush(stdout);
scanf("%d",&amount);
while(amount <= 0 || amount >= 81){
printf("Wrong input try again.\n");
printf("Give a number:\n");
fflush(stdout);
scanf("%d",&amount);
}
return EXIT_SUCCESS;
}
You need to make sure the scanf() worked. Use the returned value to do that
if (scanf("%d", &amount) != 1) /* error */;
When it doesn't work (because eg a letter was found in input) you probably want to get rid of the cause of the error.
A better option to get input from users is to use fgets()
See this related question: scanf() is not waiting for user input
The reason is that when you press enter with a char, scanf failed and didn't eat up the char in the input feed. As a result, the next block begins having whatever you entered before.
You can check that by adding a getchar() before the scanf() inside the while loop. You'll notice that it'll repeat the while loop as many times as your line has invalid characters, then stop and wait for input. The getchar() ate one of the invalid chars in the input each time the loop ran.
It would be better not to use scanf like that, though. Take a look a this resource:
Reading a line using scanf() not good?

C: Using scanf to accept a predefined input length char[]

I'm writing a C program that needs to accept user input of up to 100 characters, but the user is allowed to input less than that limit. I'm trying to implement this idea with a while loop that continues to accept char input until the user presses enter (ascii value of 13), at which point the loop should break. This is what I've written:
char userText[100]; //pointer to the first char of the 100
int count = 0; //used to make sure the user doens't input more than 100 characters
while(count<100 && userText[count]!=13){ //13 is the ascii value of the return key
scanf("%c", &userText[count]);
count++;
}
Launching from the command line, if I enter a few characters and then press enter, the prompt simply goes to a new line and continues to accept input. I think the problem lies with my lack of understanding how scanf receives input, but I'm unsure of how to change it. What can I do to make to loop break when the user presses enter?
Because you read into &userText[count] and then do count++, so you loop condition userText[count]!=13 is using the new value of count. You can fix it with:
scanf("%c", &userText[count]);
while(count<100 && userText[count]!='\n'){
count++;
scanf("%c", &userText[count]);
}
And as Juri Robl and BLUEPIXY are pointing out, '\n' is 10. 13 is '\r', which isn't what you want (most likely).
while(count<100 && scanf("%c", &userText[count]) == 1 && userText[count]!='\n'){
count++;
}
You should probably check against \n (=10) not 13. Also you check against the wrong count, it is already one to high.
int check;
do {
check = scanf("%c", &userText[count]);
count++;
} while(count<100 && userText[count-1]!='\n' && check == 1);
userText[count] = 0; // So it's a terminated string
On the other hand you could use scanf("%99s", userText); which allows up to 99 chars input (and one at the end for the 0).
The check for check == 1 looks for an error in reading, for example an EOF.

Resources