The concept if very simple. The computer must repeat the question till it recieves a valid response. Here is my current code:
#include <stdio.h>
int main(int argc, const char * argv[]) {
int age;
do{
printf("How old are you?\n");
scanf("%d", &age);
if (age == 32767)
{
printf("Error, retry: \n");
}
else
{
printf("Cool.");
break;
}
}
while(age!=3267);
return (0);
}
The if else statement is to catch the exception incase the user types something that is not an integer.
I tried using a do-while loop but it ended up as an infinite loop
I used the do-while loop because I needed to go through that procedure until I get a valid age value.
My output with the current code is:
How old are you?
g
Error, retry:
How old are you?
Error, retry:
How old are you?
Error, retry:
How old are you?
Error, retry:
It goes like this indefinitely.
It would be great if you could help me out.
The computer must repeat the question till it recieves a valid response.
It (output) goes like this indefinitely.
Reason :
The problem is that you are receiving input only once in your code and then entering into loop to check for the age.
since age value is not re-assigned after every iteration, if the first intput is !=32767 it's always wrong and enters into an infinite loop or also known as the odd loop.
scanf("%d", &age); //scans only once
do //enters loop
{
if (age == 32767)
{
printf("Error, retry: \n");
}
else
{
printf("Cool.");
}
} while(age!=32767);
The if else statement is to catch the exception incase the user types something that is not an integer.
No, if (age == 32767) would only check if the entered response was equal to 32767 or not.
From #davmac 's comment , you can never check for an input value greater than the maximum value of the int variable.
Instead it'd be better if you would assign a range this way
`if (age > 100 || age <0 )`
Solution :
to avoid this scan age for every iteration and also see the changes I've done :
do{
printf("How old are you?\n");
if(scanf("%d", &age)==1) //checking if scanf is successful or not
{
if (age > 100 || age <0 )
{
printf("Error, retry: \n");
}
else
{
printf("Cool.");
break; //break loop when correct value is entered
}
}
else //if scanf is unsuccessful
{
char c;
printf("enter only integers\n");
do
{
scanf("%c",&c);
}while( c !='\n' && c!= EOF ); //consuming characters
}
}while(1); //always true
Some important points:
First, Using scanf to read an int from user input usually allows for whitespace to be entered first:
scanf(" %d", &age);
In particular this skips over previous new line characters that were input previously and are still buffered.
Second, scanf returns a value indicating whether it succeeded or failed, and how many items it matched. You need to check this return value:
int r = scanf(" %d", &age);
if (r == EOF) {
break;
}
if (r == 0) {
printf("Error, retry: \n");
}
Third, if scanf can't match input it is left in the input buffer. If you don't retrieve it from the buffer, it will simply fail to match again the next time you call scanf, ad infinitum. For this reason, scanf is not great for handling user input at all. It is better, if possible, to read a single line of input into a buffer (you can use fgets for this, if you are careful), and then process the buffer. As a weak alternative, you can force some of the input buffer to be consumed by scanning for a string before you try to read the input value again:
int r = scanf(" %d", &age);
if (r == EOF) {
break;
}
if (r == 0) {
printf("Error, retry: \n");
scanf("%*s"); // match string but suppress assignment
}
else {
printf("Cool.\n");
break;
}
This modification gets your code to at least halfway-working state.
Use do while Loop. Like:
Do{
// your code
Age = // asign value
}while(age>100 && age < 1);
So it will repeat until age is entered between 100 and 1. It will stop if it will get age b/w 1 - 100.
Thanks. Hope it will help.
Related
I am making a program that reads input from a user then check the validity,
but for the while statement in the validateInput function I am getting an warning
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int ValidateUser(char *);
int ValidateInput(int);
FILE *database;
struct{
int year;
int unit;
float gpa;
char semester;
char grade;
char name[40];
}student;
int ValidateInput(int x)
{
while (x != 1 || x != 2 || x != 3) // code that causing a warning
return x;
}
int ValidateUser(char *input)
{
int result;
result = strcmp(input, student.name);
if (result == 0)
{
return 1;
}
else
{
while (result != 0)
{
printf("The Username you entered does not exit. Please enter correct name.");
}
}
return 1;
}
int main()
{
printf("\t----------------------------------------------------------\n");
printf("\t|\t\t\t\t Santa Monica College\t\t\t\t\t |\n");
printf("\t----------------------------------------------------------\n\n");
printf("\t\tWelcome to Santa Monica Student Record System.\n\n");
printf("Please Enter Your Option\n");
printf("\t1.View GPA/GRADE\n");
printf("\t2.Add New GPA\n");
printf("\t3.Modify Information\n");
int choice;
scanf("%d", &choice);
char UserName[40];
if(choice == 1)
{
printf("Please enter your name\n");
scanf("%s", UserName);
ValidateUser(UserName);
printf("The GPA of %s is %f , %c ", student.name, student.gpa, student.grade);
}
else if (choice == 2)
{
printf("Please enter your name\n");
scanf("%s", UserName);
ValidateUser(UserName);
}
else if (choice == 3)
{
printf("Please enter your name\n");
scanf("%s", UserName);
ValidateUser(UserName);
}
else
{
ValidateInput(choice);
}
return 0;
}
The ide was suggesting to add parentheses around x-values in the argument of while statement in the ValidateUser to make it silence
I've done some research on this warning and I found that the condition I made is not true so that's why I am getting it, but I am not quite sure what the problem is.
Can someone help me out with this???
In validateUser(), your program will reach the
while (result != 0)
only in the event that the while condition is initially true, so if it reaches the loop, it will enter it. The body of the loop does not modify result, so if it enters the loop, it will loop indefinitely.
Ultimately, if the first branch of the if / else is taken, then the function returns from within that branch, and if the second branch is taken then control never exits that branch. Either way, the
return 1;
at the end of that function cannot be reached. Of course, that's just a symptom. The infinite loop is the main problem.
It's unclear what behavior you actually want here, but what would be most in keeping with the name of the function would be for it to only evaluate whether the specified user name is valid, returning a result that conveys either "yes" or "no". There is no particular reason why such a function would need to loop at all.
You put while (result != 0) inside function ValidateUser(char *input) and never put a way to get out of the loop, resulting in the return value below it never running.
To fix this, you would need to add a break; somewhere in the loop to indicate that you are ready to leave the current loop, or make result = 0;
The difference between the two is that break; will indicate that the rest of the loop doesn't need to run and will jump out of the loop, or use result=0; to run the rest of the code in the loop and then jump out of it
I am totally new to C.
I want to re-prompt when the input value is not a number and when it's a number it should be less than 1. when I give any sort of string it works correctly. But when I give any number it goes to the next line without printing "Number: ".Then in the next line, it prints "Number: "again if the input value is less than 1.
int x;
printf("Number: ");
while (scanf("%d", &x) != 1 || x < 1 )
{
printf("Number: ");
scanf("%*s");
}
and the result it gives me is this
result
It would be wise to use fgets to read the line, then use sscanf to parse the input. That way, you can get the line, then check if sscanf succeeds!
Simple example:
int target_number; // The number you will have at the end of this.
while (1) { // Loop for rechecking number
char line[16]; // See notes on how to read the whole line.
fgets(line, sizeof(line), stdin);
// We use 1 here because sscanf returns the number of format specifiers that are matched. Since you only need one number, we use 1.
if (sscanf(line, "%d", &target_number) != 1) {
fprintf(stderr, "Invalid Input! Please enter in a valid number.");
continue;
}
}
// Do whatever you will with target_number
Notes
You can see how to read the whole line here.
This code is not safe!
It does not protect against buffer overflow attacks and the like. Please see this on the right way to do this. If this is just for learning, you don't need to worry.
/*This is how it will work the way you want.
If I understand your goal correctly, of course?
If your goal was different,
please specify and I will try to solve it.*/
#include<stdio.h>
int main(void)
{
int x;
printf("Number: ");
while (scanf("%d.%*d", &x)!=1 || x<0)
{
if(x<0)
{
printf("Number: ");
continue;
}
else
printf("Number: ");
scanf("%*s");
}
printf("Hello world!");
return 0;
}
i am pretty new to c, i m trying to make the user input a number, but if they input a letter or word it shows a warning and asks for input again, my code works fine if the user puts in a number but it goes into an infinite loop if the user inputs something invalid, here is my code
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
}
printf("%.2f\n", salary);
return 0;
}
i thought that i was something to do with the buffer left over from the first scanf , but adding a space " %f" didnt work, i tried using fflush(stdin) after then scanf also didnt work. i m not sure what else i can try.
thanks in advance for any help.
You need to clear the buffer or it will keep evaluating it and cause the endless loop. Add one line after your invalid input: scanf("%*[^\n]")
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
scanf("%*[^\n]");
}
printf("%.2f\n", salary);
return 0;
}
This will work. You can see a better explanation here: Scanf and loops
The problem is that scanf won't advance the file stream. You ask it to read a floating point value and it isn't able to, so it doesn't consume the input.
For example, let's say your input is "foo", which isn't a number. Your scanf call isn't able to successfully read anything and returns 0. Then, in the next iteration, "foo" is still waiting to be read from stdin.
Try changing your if condition to something like
if (status == 0) {
char foo[256];
fgets(foo, sizeof(foo), stdin);
printf("Invalid input! Expected a nmuber, got: %s", foo);
}
Notice how the entire input is read from stdin by the gets call.
I'm having a problem understanding how to get my while loop to simply output a message saying "Invalid Input" and asking for a new question from the user unless he chooses number 1 or 2 in the list. What happens if you for example input : asdas instead of a integer the program never stops looping.
What I would like to happen is for the program to tell the user to enter a new number from 1-2 instead of simply stopping running which i can achieve by setting the default in the switch to exit(0); or runSystem = false;
For example:
CMD Says enter 1-2 the user enters : asdaf (never stops looping) as in current situation.
What I want is: asdf and then it says "enter a new choice" and waits for a correct answer.
What bothers me is the fact that the program will do as i want it to if you enter an invalid number for example: 12312312 and ask for a new entry but it doesn't work with string input.
Code:
#include <stdio.h>
#include <stdbool.h>
int main(int argc, char **argv) {
int userinput;
int runSystem = true;
void options() {
printf("<========Welcome to the program, please make a choice========> \n\n");
printf("1: Say Hello\n");
printf("2: Say GoodBye\n");
printf("Please enter a choice:");
scanf("%d", &userinput);
}
while (runSystem) {
options();
switch(userinput) {
case 1: printf("Hello!\n");
break;
case 2: printf("GoodBye!\n");
break;
case 3: printf("Invalid, try again\n");
break;
default:
break;
}
}
return 0;
}
scanf("%d", &userinput); expects an int as the input. When you give a non-integer, scanf() won't assign it to userinput.
Check the return value of scanf() to see if it was successful. It returns the number of successful assignments it did.
When you give a string as input, scanf() won't accept it and will leave it in the input buffer unconsumed.
When you do scanf() again, the invalid input is still present in the input buffer and that is what the second scanf() tries to read. The same thing happens and this goes on. This is the reason behind your infinite loop.
To overcome this, you should consume the invalid input from the input buffer after displaying the message in case 3. Do something like
int ch;
while( (ch=getchar())!='\n' && ch!=EOF );
This will consume from the input buffer till a \n is encountered. getchar() return EOF on failure.
Edit: Standard C doesn't allow nested function definitions. The reason why you didn't get an error for that is probably because your compiler allows this as an extension. But it may not work for other compilers.
See this and this.
You could place the definition of options() within the while loop calling it or get the value for userinput as a return value or via a pointer to the variable passed to the function.
Valid C compiler does not allow declaration of the function options inside the main.
Make that function returning your input and pass the returning value to the switch. Also in order to stop the while loop case 2: should change the runSystem to false;
input : asdas instead of a integer the program never stops looping.
This is because when scanf("%d", &userinput); failed it did not updated the variable userinput.
Check the standard 7.21.6.4 The scanf function.
You can read about behaviour of scanf
here.
On success, the scanf returns the number of items successfully read. This count can match the expected number of readings or fewer, even zero, if a matching failure happens. In the case of an input failure before any data could be successfully read, EOF is returned.
Knowing that you can check the return value of scanf and make appropriate decision. Presented solution eats the bad characters.
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
int options(void) {
int c;
int ret;
int x = 0;
int error = 0;
printf("<========Welcome to the program, please make a choice========> \n\n");
printf("1: Say Hello\n");
printf("2: Say GoodBye\n");
printf("Please enter a choice:");
while(1)
{
c = '0';
if(!error)
printf("Input a number:\n");
else
error = 0;
ret = scanf("%d", &x);
if(ret == EOF) {
return 2; // END OF PROGRAM
}
else
{
if (ret == 1){
return x;
}
else // NOT a number
{
printf("No letters! Input a number:\n");
do
{
c = getchar();
if(c == EOF)
return 2; // END OF PROGRAM
}
while (!isdigit(c) && c!='\n');
ungetc(c, stdin);
error = 1;
}
}
}
}
int main(void) {
int userinput;
int runSystem = true;
while (runSystem) {
userinput = options();
switch(userinput) {
case 1: printf("Hello!\n");
break;
case 2: printf("GoodBye!\n");
runSystem = false;
break;
default:
case 3: printf("Invalid, try again\n");
break;
}
}
return 0;
}
Output:
<========Welcome to the program, please make a choice========>
1: Say Hello
2: Say GoodBye
Please enter a choice:Input a number:
X
No letters! Input a number:
a
No letters! Input a number:
1
Hello!
<========Welcome to the program, please make a choice========>
1: Say Hello
2: Say GoodBye
Please enter a choice:Input a number:
7
Invalid, try again
<========Welcome to the program, please make a choice========>
1: Say Hello
2: Say GoodBye
Please enter a choice:Input a number:
2
GoodBye!
My program works well with invalid inputs such as char, number out of range, but a problem happens when a floating point value such as 1.2 is entered. The program prints menu again, and asks user for input before printing error message. What I try to fix is don't print menu again, but still struggle. For example,
Make your selection: 1.1
[Here is menu content]
Make your selection: That selection isn't valid. Please try again.
#include <stdio.h>
#define QUIT 0
int menu();
int main(void)
{
int choice;
char c;
choice = menu();
while(choice != QUIT) //execute so long as choice is not equal to QUIT
{
choice = menu();
}
}
int menu(void)
{
int option;
printf("Text Encoder Service\n\n");
printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
printf("2.\tEnter name of output file (currently not set)\n");
printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
printf("4.\tEncode the text\n\n");
printf("0.\tQuit\n\n");
printf("Make your selection: ");
while( (scanf(" %d", &option) != 1) /* non-numeric input */
|| (option < 0) /* number too small */
|| (option > 4)) /* number too large */
{
fflush(stdin); /* clear bad data from buffer */
printf("That selection isn't valid. Please try again.\n\n");
printf("Your choice? ");
}
return option;
}
I finally could validate floating input. Thanks your advices so much! This is my new code. What else do you think an invalid input?
int menu(void)
{
int option, parsed_inputs;
char overcount_char;
parsed_inputs = 1;
printf("Text Encoder Service\n\n");
printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
printf("2.\tEnter name of output file (currently not set)\n");
printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
printf("4.\tEncode the text\n\n");
printf("0.\tQuit\n\n");
printf("Make your selection: ");
parsed_inputs = scanf_s("%d%c", &option, &overcount_char);
while( parsed_inputs > 1 ) /* number too large */
{
if((overcount_char != '\n') || (option < 0) || (option > 4))
{
fflush(stdin); /* clear bad data from buffer */
printf("That selection isn't valid. Please try again.\n\n");
printf("Your choice? ");
scanf_s("%d%c", &option, &overcount_char);
}
else
break;
}
return option;
}
An input of 1.1 leads to the following:
The string is read into an internal buffer.
It is then matched against the given format string.
On the first non-match, the scanf() call is stopped and it returns the number of successfully scanned values.
Let's test it:
#include <stdio.h>
int main(int argc, char ** argv)
{
while (1) {
int option;
int n = scanf(" %d", &option);
printf("%d %d\n", n, option);
if (n <= 0) break;
}
}
This program reads one line.
Suppose I enter 123 132.
Then the following happens:
* As the format string starts with a space, all leading whitespace is consumed. In this case, there is none.
* Then the 123 is consumed and put into option.
* As the format string is over now, parsing is stopped, n=1 and option=123.
* In the next loop run, the same happens, giving n=1 and option=123.
But: Suppose I enter 123.321 or 123#321.
Then the following happens:
* As the format string starts with a space, all leading whitespace is consumed. In this case, there is none.
* Then the 123 is consumed and put into option.
* As the format string is over now, parsing is stopped, n=1 and option=123.
* In the next loop run, there is no whitespace to skip. .321 resp. #321 is tried to be matched to %d, but these are no valid ints. Thus, we get n=0 and option keeps its old value.
* As no characters are consumed from the input stream (the one used is put back again), the same happens over and over again - that's why I put if (n <= 0) break;.
So you see that the behaviour has nothing to do with floating point, as it doesn't matter if we use . or # to "disturb".
We change our program to
#include <stdio.h>
int main(int argc, char ** argv)
{
while (1) {
int option; char c;
int n = scanf("%d%c", &option, &c);
printf("%d %d %d %c\n", n, option, c, c);
if (n <= 0) break;
}
}
and run it, inputting 4.235#6x7.
Then we get
* n=2, option=4 and c='.' at the first run
* n=2, option=235 and c='#' at the 2nd run
* n=2, option=6 and c='x' at the 3rd run
* n=2, option=7 and c='\n' (newline) at the 3rd run
and are prompted for further input.
This makes you open to the option
(parsed_inputs = scanf("%d%c", &option, &overcount_char)) < 1
and then check what overcount_char contains, whenever parsed_inputs is > 1.
I think you should put scanf() before the while loop and explicitly check "option" variable in the while loop.
What happening is that, here scanf() will always return the value 1, because scanf() returns no. of arguments read successfully. Hence this while loop will run forever. For further information check this link->http://www.cplusplus.com/reference/cstdio/scanf/
Hope this helps!