Check if user input is between 1 and 10 - c

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.

Related

Ignoring scanf value in while loop

I'm learning C and I face a problem running this loop. I've wrote a while loop to prompt the user to key in the package and the quantity of it. I try to validate the input for the quantity to check is it integer or not (when a user key in a character it will prompt the user to key in again)
For the first run, everything is fine.
But when the loop runs a second time and so on, I try to key in a character for the quantity of the package, the message won't pop up to tell the user to key in again.
The value of the scanf is ignored and the value of tempQtty is equal to the previous quantity that the user keyed in.
Is there any way to fix this, or is there another way to validate the user input is integer?
Sorry for my broken English :")[input, expected input and actual input][1]
while(skip != 'x')
{
printf("\n\n%27sPACKAGE A/B/C/D ( x = skip ) : ", "");
rewind(stdin);
package = getchar();
switch (package)
{
case'x':case'X': skip = tolower(package); break;
case'A':case'a':case'B':case'b': case'C':case'c':case'D':case'd':
printf("%27sQUANTITY%21s: ", "", "");
rewind(stdin);
scanf("%d", &tempQtty); //here's the problem
while (tempQtty < 0)
{
printf("%27s(PLEASE KEY IN A CORRECT VALUE!)\n", "");
printf("%27sQUANTITY%21s: ", "", "");
rewind(stdin);
scanf("%d", &tempQtty);
}
switch (package)
{
case 'A':case 'a': qttyA = tempQtty; totalQttyA += tempQtty; break;
case 'B':case 'b': qttyB = tempQtty; totalQttyB += tempQtty; break;
case 'C':case 'c': qttyC = tempQtty; totalQttyC += tempQtty; break;
case 'D':case 'd': qttyD = tempQtty; totalQttyD += tempQtty; break;
}
break;
default:
printf("%27s(NO SUCH PACKAGE! PLEASE KEY IN AGAIN!)\n", "");
}
}
printf("\nA = %d", qttyA);
printf("\nB = %d", qttyB);
[1]: https://i.stack.imgur.com/hBD82.png
First of all, and as I mentioned in a comment, this is a surprisingly complicated problem, and you are not alone in facing it. It's not a problem with you, or with the C language; it's basically just a problem with the scanf function itself.
Partial answer:
(1) Everywhere you have things like
scanf("%d", &tempQtty);
while (tempQtty < 0)
...
that's wrong. If you ask for integer input using %d, and if the user types something non-numeric, what scanf does not do is fill in tempQtty as -1. What it does do is return a value saying it couldn't convert what you (the programmer) asked. So you want to change this to something more like
while (scanf("%d", &tempQtty) != 1)
...
(2) If the user does not type the integer you requested, and if scanf returns 0 to tell you so, there's a problem: the non-numeric input the user typed is probably still sitting on the input stream. It looks like you may have realized this, and that you're trying to get rid of the unread input by calling rewind(stdin). But that won't work; that's not the way to do it.
What you want to do is write a little "helper" function like this:
void flush_unread_input()
{
int c;
do {
c = getchar();
} while(c != EOF && c != '\n');
}
Then, wherever you've detected an error (that is, wherever scanf has returned something other than 1), instead of calling rewind(stdin), just call flush_unread_input().
A few more points:
You may have to experiment where to call flush_unread_input and where not to. You can't just blindly sprinkle it everywhere, because it basically reads and discards the rest of the line, but that it means it can also read and discard an entire line, which might sometimes be a line that you actually wanted.
There are many ways to write a flush_unread_input function. I've shown one way that should be easy to understand, but you'll often see something more compact like while((c = getchar()) != EOF && c != '\n');. (Also I haven't tested the version I've shown here.)
My answer might have suggested that scanf returns 1 if it succeeds and 0 if it fails, but it's more complicated than that. scanf actually returns the number of items successfully converted and stored, which might be more than 1 if you have a format specifier with multiple % signs in it.
There's much more to say on this topic, but I don't have time to write a longer answer this morning.
I try to key in a character for the quantity of the package, the message won't pop up to tell the user to key in again.
The value of the scanf is ignored and the value of tempQtty is equal to the previous quantity that the user keyed in.
Is there any way to fix this, or is there another way to validate the user input is integer?
There is no base for your assumption that tempQtty would receive a negative value if you entered z. In fact, the C standard mandates that tempQtty is not affected if the conversion fails. The way to fix this is to not ignore the scanf return value, which tells whether input was valid.

Are there better ways to clear stdin when looking for a specific kind of input in C?

fairly new programmer here just trying to understand if there is a better way to do this and hoping to get some feedback.
TL;DR: Is there a better way to clear stdin when looking for a specific input?
For some background, I've been learning C for the past 3 weeks and scanf() has been our "go to" function for user input. After looking around for answers to this question, I'm beginning to learn that scanf() is not always preferred.
In this part of the assignment that I'm working on, I created this while loop that is supposed to run while the user input is a nonzero, positive integer. It took a while, but to get to this point I now understand that if a string is inputted instead of an integer when scanf("%d", &variable); is assigned while using leads to an infinite loop as stdin does not get cleared.
I tried to solve this problem by checking to see the return of the scanf() functions, and running the loop while the return is equal or less than 0 (which would mean that the scanf() function broke and did not return anything since it saw a char instead of an int).
The thing is, the code seems to work great until we encounter one scenario, which is where we have characters followed by an integer.
For example:
Input = 1
program runs with no issues
Input = string
program runs loop, asks for new valid input
Input = string string
program runs loop, asks for new valid input
Input = 123string
program proceeds, but then next loop with an int scanf() is infinite. 123 is stored as an int to variable.
My current understanding of the issue is that scanf() reads the integers until we get to the characters and then "string\n" gets stored to stdin, creating an infinite loop in the next part. To solve the issue, I added a fflush(stdin); before the next integer scanf() loop which seems to work.
So my question is: Would somebody be willing to show me some other ways to do this other than adding a fflush(stdin); line before every int scanf() loop? I'm sure there are better ways but I don't rightly know who to ask and the internet seemed like a good resource. Thank you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int squareLen = 0;
int numColors = 0;
int infiniteLoopStop;
// Asks for user input of desired Square Length
printf("Please enter the finished side length (in inches) of one square.\n> ");
while (squareLen < 1) {
infiniteLoopStop = scanf("%d", &squareLen);
if (infiniteLoopStop <= 0 || squareLen < 1) {
printf("\nInvalid input. Enter a nonzero, positive integer.\n> ");
fflush(stdin);
}
}
// Temporary solution to problem
fflush(stdin);
// Asks for int input of colors and loops while number of colors is not 2 or 3
printf("How many colors are you using? Enter 2 or 3.\n> ");
while (numColors < 2 || numColors > 3) {
infiniteLoopStop = scanf("%d", &numColors);
if (infiniteLoopStop <= 0 || numColors < 2 || numColors > 3) {
printf("Invalid, please enter 2 or 3.\n> ");
fflush(stdin);
}
}
printf("\n");
return 0;
}

how to use fgets to get a number AND CLEAN the stdin afterward, nothing else helped

I am trying to get a single digit number from stdin.
Using scanf("%d",&choice); is not good because if something like 3fjios or fjaifdj is entered then it keeps everything after the digit (if there is one), so if later I have scanf("%s",name); it takes the other chars and messing up. And also using scanf is bad (or so it seems from Google).
After a lot of digging I understand that we should use fgets, to read input into a string and then parse through it.
But! Nowhere is explained how to properly clear the buffer afterwards.
So if I do something like:
char choice[3];
do {
fgets(choice, 3, stdin);
scanf("%*[^\n]");
scanf("%*c");//clear upto newline
} while (choice[1] != '\n');
this works only if I enter a string longer than 2 chars.
When I enter a single char for fgets then the scanf actually waits for another input... which is bad.
The other big problem is if I enter more than 2 chars (a digit and '\n') then the first 2 chars go into choice, the rest are stuck in the buffer. All the approaches to clearing it seems like they require one to build a nuclear power plant first...
Also, what happens if the user enters an infinitely (a really long) long string?
Can you please show a simple way that will allow the user to enter some string of some (unknown) length, and then to properly check if it contains exactly a single digit at the start, followed by '\n'?
Any other input should loop back to get a new input from the user again.
please don't use complex solutions, only standard simple C please.
I can't believe I wasted 6 hours on this supposedly simple technical thing, just getting an input from the user. Solving the actual problem was easier...
Do not use scanf. It is making things overly complicated. Just use getchar to read and discard the line. eg:
int read_input(void) {
int n;
n = getchar();
if( getchar() == '\n' || n == EOF)
return n;
else
do n = getchar(); while ( n != '\n' && n != EOF);
fputs("invalid entry: ", stderr);
return read_input();
}
int main(void) {
int input;
input = read_input();
printf("user entered: %c\n", input);
return EXIT_SUCCESS;
}

Issues with using scanf inside a while loop

I’m brand new to programming. I ‘m working on a homework assignment in order to help us understand scanf and arrays. The program is supposed to ask the user to input an unknown set of numbers. Each set of numbers should be separated by a space like below without hitting enter.
14 15 16
The user can also input numbers on a separate line instead using spaces, but again on the last number inputed the user isn’t supposed to hit enter.
12 13
44 55
5
The user should hit ctrl-d to indicate end of input. The program should display the number of elements entered by the user, along with displaying the numbers the user entered. I have been reading around and think I have a basic concept of how scanf works, but I am still having some difficulty. The code kind of works. However, if the user just enters the numbers on one line they need to hit ctrl-d three times in order for it to exit the loop and display the information.
From what I have found online and understand, I think it’s not working because the user hasn’t hit return, so the input hasn’t been flushed into the stdin. So if I'm understanding correctly, the first time I hit ctrl-d it while flush the input. Then the second time I hit ctrl-d it will finally put the EOF into the stream and the third time it will finally read the -1 produced by the EOF and exit the loop.
Is there anyway to force the input stream once ctrl-d is entered.
#include <stdio.h>
int main()
{
int numbers[20];
int i = 0, count, result, n;
int flag = 0;
printf("Please enter a seiries of numbers:\n");
while (flag == 0)
{
result = scanf("%d", &n); //scan user input into n variable along with getting scanf return value and storing in result variable
printf("result =%i \n", result); //Just printing scanf return value to insure it doing what I think it should be doing
if (result == 1)
{
numbers[i] = n; //if scanf return value is 1 places value of n into first element of array
i++; //used to increment my array
flag = 0;//keeps value of flag equal to 0 in order to stay in loop
}
if(result == -1) //checks to see if result = to -1 should be value returned if cntl +d is entered
{
flag = 1; //sets flag to 1 when cntrl +d is entered in order to exit loop.
}
}
for (count = 0 ; count < i ; count++) //loop to print I which is representing number of user inputs and the actual numbers entered by the user.
{
printf("\ni= %i numbers= %i\n", i, numbers[count]);
}
return 0;
}
I won't give you a solution directly, but will try to help you improve coding in C. The more you work with C the more you will find out that one can write pretty compact code, once the language is mastered.
You can omit flag because it depends on result.
And you could omit result because it is just the return value of scanf.
You can omit n and use numbers array directly.
And you could make use of the preprocessor to use a constant number (often for array sizes as in your case).
Have a look at this. Maybe it helps you get an idea:
#include <stdio.h>
#define COUNT 20
main() {
int numbers[COUNT];
int i;
i = 0;
while (scanf("%d", &numbers[i]) == 1 && i < COUNT)
printf("\t%d\n", numbers[i++]);
return 0;
}
P.S.:
I recommend getting acquainted with the different ways of accessing an array and reading about pointers. The have a very close relationship really.
Address of first element in array : numbers
Access ith element of array : numbers[i]
Equivalently : *(numbers + i)
Another equivalence : *(i+numbers)
Surprise, but equivalent again : i[numbers]
Address of ith element of array : &numbers[i]
K&R is a great resource of information and learning.

How to enter a letter to quit a program in C

I am new to C programming. I have been writing this code to add numbers and I just need help with this one thing. When I type the letter 'q', the program should quit and give me the sum. How am I supposed to do that? It is currently the number 0 to close the program.
#include <stdio.h>
int main()
{
printf("Sum Calculator\n");
printf("==============\n");
printf("Enter the numbers you would like to calculate the sum of.\n");
printf("When done, type '0' to output the results and quit.\n");
float sum,num;
do
{
printf("Enter a number:");
scanf("%f",&num);
sum+=num;
}
while (num!=0);
printf("The sum of the numbers is %.6f\n",sum);
return 0;
}
One approach would be to change your scanf line to:
if ( 1 != scanf("%f",&num) )
break;
This will exit the loop if they enter anything which is not recognizable as a number.
Whether or not you take this approach, it is still a good idea to check the return value of scanf and take appropriate action if failed. As you have it now, if they enter some text instead of a number then your program goes into an infinite loop since the scanf continually fails without consuming input.
It's actually not as straightforward as you'd think it would be. One approach is to check the value returned by scanf, which returns the number of arguments correctly read, and if the number wasn't successfully read, try another scanf to look for the quit character:
bool quit = false;
do
{
printf("Enter a number:");
int numArgsRead = scanf("%f",&num);
if(numArgsRead == 1)
{
sum+=num;
}
else // scan for number failed
{
char c;
scanf("%c",&c);
if(c == 'q') quit = true;
}
}
while (!quit);
If you want your program to ignore other inputs (like another letter wouldn't quit) it gets more complicated.
The first solution would be to read the input as a character string, compare it to your character and then convert it to a number later. However, it has many issues such as buffer overflows and the like. So I'm not recommending it.
There is however a better solution for this:
char quit;
do
{
printf("Enter a number:");
quit=getchar();
ungetc(quit, stdin);
if(scanf("%f", &num))
sum+=num;
}
while (quit!='q')
ungetc pushes back the character on the input so it allows you to "peek" at the console input and check for a specific value.
You can replace it with a different character but in this case it is probably the easiest solution that fits exactly what you asked. It won't try to add numbers when the input is incorrect and will quit only with q.
#Shura
scan the user input as a string.
check string[0] for the exit condition. q in your case
If exit condition is met, break
If exit condition is not met, use atof() to convert the string to double
atof() reference http://www.cplusplus.com/reference/cstdlib/atof/

Resources