In this code I have several querys for user input. If there is an invalid input like 'r' instead of 4, I want my programm to say "invalid input" and ask for another user input. I tried a lot but I couldn't get it to work.
I commented the problematic locations in the code. Thanks for help.
#include <stdio.h>
int main()
{
double Operand1;
double Operand2;
int Menuchoice;
int Input;
char Dummy;
double Result;
do
{
printf("Simple Calculator\n");
printf("========================\n");
printf("\n");
printf("1. Addition\n");
printf("2. Subraction\n");
printf("3. Multiplication\n");
printf("4. Division\n");
printf("9. Quit\n");
Input = scanf("%i", &Menuchoice); // At this point I want to check if there is a valid input and
do scanf("%c", &Dummy); // if not the programm should ask again
while (Dummy != '\n');
if(Input)
{
switch(Menuchoice)
{
case 1: printf("Type in the first operand:\n");
scanf("%lf", &Operand1) // Here I want to validate the input
printf("Type in the second operand:\n"); // again and the programm should also ask
scanf("%lf", &Operand2) // again if it was invalid
printf("%lf + %lf = %lf\n", Operand1, Operand2, Result);
break;
case 2:
case 3:
case 4:
default: printf("No valid input!\n");
break;
}
}
}while (Menuchoice != 9);
return 0;
}
Manual page of scanf:
On success, these functions return the number of input items successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
So here is a sample which could lead you to solve your problem:
#include <stdio.h>
int main (int argc, char* argv)
{
double o;
int res;
// To illustrate, I chose to set up an infinite loop.
// If the input is correct, we'll "break" it
while(1)
{
printf("Enter a double: ");
res = scanf("%lf",&o);
// Success = 1 read input
if (res == 1)
{
printf("Yahoo, got it right: %f\n",o);
break; // We exit the loop
}
// Ah, we failed
printf("Please retry.\n");
// popping the CR character to avoid it to be got by the next scanf()
getchar();
// Here we go for another loop.
}
// Good, we got our double.
printf("Hey, sounds like we got outside this infinite loop.\n");
}
Example:
user#so:~$ ./a.out
Enter a double: r
Please retry.
Enter a double: f
Please retry.
Enter a double: 6.543
Yahoo, got it right: 6.543000
Keep in mind this check is not perfect. For example, "frg6sgg" will success and be displayed as 6.0000000 by printf().
Related
How do I make my if statement ask the user to try again if the input is a negative number or a letter?
struct foodstuff {
float amount;
};
void add(struct foodstuff *tmpAdd) {
printf("Write amount: ");
scanf("%f", &tmpAdd->amount);
while (tmpAdd->amount != 0) {
if (tmpAdd->amount < -1 || isalpha(tmpAdd->amount)) {
printf("Type in a valid number!\n");
printf("Write amount: ");
getchar();
scanf("%f", &tmpAdd->amount);
getchar();
}
else {
scanf("%f", &tmpAdd->amount);
getchar();
}
}
};
I think you can rephrase your code to use a do loop instead:
do {
printf("Enter a positive number with no characters:\n");
int result = scanf("%f", &tmpAdd->amount);
while (tmpAdd->amount <= 0 || result != 1);
Note that I have removed the call to isalpha(), which acts only a single character at a time. Instead, I propose just checking that the entered number is a valid float and that it is greater than zero. If scanf does not succeed to read in a valid float, then its return value would be not be 1 and the loop would repeat. And the same is the case for entering a valid float which is a negative number.
As chux said, you could first read the input with fgets() and then parse it.
Like
char buff[100], *ptr;
float f;
while(fgets(buff, sizeof(buff), stdin)!=NULL)
{
buff[strlen(buff)-1]='\0';
f=strtof(buff, &ptr);
if(errno==ERANGE)
{
printf("\nPossible overflow.");
errno=0;
continue;
}
if(f<0 || *ptr!='\0')
{
printf("Type in a valid number!\n");
continue;
}
tmpAdd->amount=f;
printf("\n%f", f);
}
Here, fgets() is used to read the input on each iteration. fgets() will return NULL upon error.
The
buff[strlen(buff)-1]='\0';
is done because fgets() will read in the trailing \n into buff as well. We modify that \n to be the \0 character denoting the end of string with buff[strlen(buff)-1]='\0';.
strtof() is used to extract the value from buff.
It is in stdlib.h.
In case buff has something other than numbers, the number part would be converted and returned by strtof() and the ptr pointer would be made to point to the first non-numeric part of buff.
So if the first character in the string pointed to by ptr is the \0 character, there were no non-numeric parts in buff.
If the input value was too large or too small to be accommodated in a float, errno would be set to ERANGE. You need to include errno.h for that.
If overflow (or underflow) occurred, we set errno to 0 and continue.
And (tmpAdd->amount<-1) would be false even if tmpAdd->amount were -1 and -1 is negative. You need (tmpAdd->amount<0) instead.
Also, your loop would exit only when tmpAdd->amount becomes 0. You could simply do
tmpAdd->amount=0;
if that would do.
Otherwise, you can add a
if(f==0)
{
break;
}
at the end of the while loop.
I did some changes to my code, it looks like this now:
printf("Write amount: ");
scanf("%f", &(tmpAdd + index)->amount);
getchar();
do {
if (tmpAdd->amount <= -1 || isalpha(tmpAdd->amount != 0)) {
printf("Type in a valid number!\n");
printf("Write amount: ");
scanf("%f", &(tmpAdd + index)->amount);
getchar();
}
else if (isdigit(tmpAdd->amount >= 0)) {
scanf("%f", &(tmpAdd + index)->amount);
//getchar();
}
} while (tmpAdd->amount <= -1 || isalpha(tmpAdd->amount != 0));
};
Main looks like this:
int main (void) {
int input, noFood = 0;
int flag = 1;
printf("Welcome to the shopping list manager. \n\n");
struct foodstuff food1;
while (flag == 1) {
printf("1 - add food\n");
printf("2 - print shopping list\n");
printf("3 - end\n\n");
printf("What do you want to do? ");
scanf("%d", &input);
clear();
switch (input) {
case 1: add(&food1, noFood); noFood++; break;
case 2: print(&food1, noFood); break;
case 3: printf("\nExiting program\n"); flag = 0; break;
default: printf("Please enter a valid choice\n");
}
}
return 0;
}
And the output like this:
Output
The only problem remaining is that when I want to add another item (add food) for the second time and I type a letter or a negative number, it doesn't run through the if statements.
I am writing a program that can calculate the areas of a square, cube, and circle. The program needs to present an error message and allow the user to enter a new choice if they enter something not included in the menu. My problem is that if they type anything includes my menu options then the program still executes. (i.e. -1, 23, 344) I was wondering how to get it to ignore anything after the first character or to read the whole string. Or if there is something better than getchar(). I'm open to any solutions! Thank you!
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int choice;
int lengthsq;
int areasq;
int lengthcube;
int areacube;
int radius;
double circlearea;
printf("Area Calculation\n");
printf("(1) Square\n");
printf("(2) Cube\n");
printf("(3) Circle\n");
fputs("Please make a selction: ", stdout);
while((choice = getchar()) != '\n')
switch (choice) {
case '1':
printf("\nPlease enter the length: ");
scanf("%d", &lengthsq);
while(lengthsq <= 0){
printf("Error! Please enter a positive number: ");
scanf("%d", &lengthsq);
}
areasq = lengthsq * lengthsq;
printf("The area of the square is %d.", areasq);
return 0;
case '2':
printf("\nPlease enter the length: ");
scanf("%d", &lengthcube);
while (lengthcube <= 0) {
printf("Error! Please enter a positive number: ");
scanf("%d", &lengthcube);
}
areacube = 6 * lengthcube * lengthcube;
printf("The surface area of the cube is %d.\n", areacube);
return 0;
case '3':
printf("\nPlease enter the radius: ");
scanf("%d", &radius);
while(radius <= 0){
printf("Error! Pleae enter a postive number: ");
scanf("%d", &radius);
}
circlearea = 3.14159 * radius * radius;
printf("The area of the circle is %.2f.\n", circlearea);
return 0;
case '\n':
case '\t':
case ' ':
break;
default:
printf("\nInvalid choice entered.\n");
fputs("Enter a new choice: ", stdout);
break;
}
}
You could add another switch case for the dash, which would toggle some kind of negative flag and then read a number as you're already doing. If you do not like introducing such a flag, then the best option would be using fgets, which returns the entire input line. But that has the downside that you need to parse the input. I.e. do some string manipulation, which may be slightly more complex than a simple flag parameter.
On the other hand, from the code you attached, I deduct that the only valid input consists of mere numbers (integers). You could just read an integer then with scanf.
My question is i have been asked to write a menu driven program that will ask the user to 1. enter a 4 digit code 2. Encrypt the code and verify against a set 4 digit code. 3. Exit the program. The program should loop back to the start menu after the user is done with their selected option apart from when they choose to exit. i.e the user will enter their code and return to the menu before encrypting and verifying the code entered against a set 4 digit code.
My code below does not loop back to the menu nor does it run correctly when i choose option 1 it asks me to enter the 4 digit code twice. I have tried tiredlessy to fix this but to no avail. Any help you can give me would be great.
#include <stdio.h>
#include <stdlib.h>
#define CODE 4
//prototypes
int enter_code (int* code_arr);
int encrypt_code (int* pass_code, int* user_code);
int main(void)
{
//declare variables
int password[CODE] = {0};
int passOK[CODE] = {4,5,2,3};
int option;
int exit1;
int code;
//do while loop
do
{
//print the menu on screen
printf("\t \t \t \t Pearse Security \n \n");
printf("\t \t \t1 - Enter the access code\n");
printf("\t \t \t2 - Enter the encrypt code and verify\n");
printf("\t \t \t3 - Exit the program \n");
//scan for user input
scanf("%d",& option);
switch(option)
{
case 1:
{
code =enter_code(password);
break;
}
case 2:
{
if (encrypt_code(passOK, password))
printf("You unlocked the vault\n");
break;
}
case 3:
{
// prompt user to a key to exit
printf("\n You choose to exit the program.\n Press a key to exit\n ");
getchar();
exit(0);
break;
}
default:
{
printf("You must enter a number between 1-5\n");
}
} // end switch()
if (!enter_code(password))
{
printf ("Bad password entry\n");
}
else
{
if (encrypt_code(passOK, password))
{
printf("You unlocked the vault\n");
}
else
printf("You don't know the passcode\n");
}
return 0;
}//end do
while(exit1!=4 & exit1 <5);
}//end main()
//enter code function()
int enter_code (int* code_arr)
{
//declare variables for enter_code()
int i;
//prompt user to enter the 4 digit code
printf("Enter your 4 digit code\n");
for(i=0;i<CODE;i++)
{
if (scanf("%d", &code_arr[i]) != 1)
{
return 0;
}//end if()
}//end for()
return 1;
}//end enter_code()
//encrypt code and verify function
int encrypt_code (int* pass_code, int* user_code)
{
//variables for encrypt_code()
int i;
for(i=0;i<CODE;i++)
{
if (pass_code[i] != user_code[i])
{
return 0;
}//end if()
}//end for()
return 1;
}//end encrypt_code()
The output of this program is
Enter 4 digits
4
5
2
3
Enter 4 digits
4
5
2
3
You have unlocked the vault
And the program ends
Why does it ask me to enter the code twice and why does it not loop back to the menu.
I received two compiler warnings about this line
while(exit1!=4 & exit1 <5);
Firstly it should be
while(exit1!=4 && exit1 <5);
It is also undefined behaviour since exit1 has never been assigned a value.
I suggest you replace the line with
while(1);
since case 3: contains an exit().
Next, you say that enter_code() is being called twice. The reason is because it is being called twice: once within case 1: and again outside the switch() code block.
Here is the amended main() in which I deleted the surplus stuff below the switch() block and added a failure message to case 2:
int main(void)
{
int password[CODE] = {0};
int passOK[CODE] = {4,5,2,3};
int option;
int code;
do
{
printf("\t \t \t \t Pearse Security \n \n");
printf("\t \t \t1 - Enter the access code\n");
printf("\t \t \t2 - Enter the encrypt code and verify\n");
printf("\t \t \t3 - Exit the program \n");
scanf("%d",& option);
switch(option)
{
case 1: {
code =enter_code(password);
break;
}
case 2: {
if (encrypt_code(passOK, password))
printf("You unlocked the vault\n");
else
printf("You don't know the passcode\n");
break;
}
case 3:{
// prompt user to a key to exit
printf("\n You choose to exit the program.\n Press a key to exit\n ");
getchar();
exit(0);
break;
}
default: {
printf("You must enter a number between 1-5\n");
}
}
} while(1);
return 0;
}
hello guys I coded something like kfc menu,and I got it to work(finally),but when I input something other than numbers for "menu",eg:the letter "A", I just can't get it to loop again to normal,instead it finishes the program
#include <stdio.h>
#include <stdlib.h>
int main()
{
char counter='y';
float totalprice=0;
while (counter=='Y' || counter=='y')
{
int menu;
float price=0;
printf("\nplease select from menu:");
scanf (" %i", &menu);
switch(menu)
{
case 1: {
printf("\none hotbox1 =RM10.50");
totalprice=totalprice+10.50;
break;
}
case 2: {
printf ("\none hotbox2=RM10.60");
totalprice=totalprice+10.60;
break;
}
case 3:{
printf ("\none hotbox3=RM10.70");
totalprice=totalprice+10.70;
break;
}
default : {
printf ("\nplease enter proper number please:");
scanf("%2f", &menu);
break;
}
}
printf("\n\nadd order?(Y/N):");
scanf (" %c", &counter);
}
printf("\n\nThe total price is: %f", totalprice);
return 0;
}
You should use fgets() (reference here) first and then sscanf() (reference here), checking it's return value to see if it's a number.
char inputBuffer[MAX_BUFFER];
do
{
fgets(inputBuffer, MAX_BUFFER, stdin);
}
while(sscanf(inputBuffer, "%d", &menu) != 1)
You scanf with %f in the default case, I am fairly certain that is for floats. Use %d.
Remove scanf("%2f", &menu);
Switch in C does not support char in switch-case. Before you start switch-case validate the user input. If it is a number go into switch case otherwise display a user message to enter only numeric value
I recommend that you debug this by printing out the value of "counter" at various points in the loop (i.e. after you read it in, at the bottom of the loop, etc.). This will give you visibility into what your code is doing.
You can try something like this
#include <stdio.h>
int main()
{
char counter;
float totalprice=0;
int menu=0;
do
{
printf("\n1. one hotbox1=RM10.50");
printf("\n2. one hotbox2=RM10.60");
printf("\n3. one hotbox3=RM10.70");
printf("\nplease select from menu:");
scanf ("%d", &menu);
switch(menu)
{
case 1:
printf("\none hotbox1 =RM10.50");
totalprice=totalprice+10.50;
break;
case 2:
printf ("\none hotbox2=RM10.60");
totalprice=totalprice+10.60;
break;
case 3:
printf ("\none hotbox3=RM10.70");
totalprice=totalprice+10.70;
break;
default :
printf ("\nplease enter proper number please:");
scanf("%d", &menu);
}
printf("\n\nadd more order?(Y/N):");
fflush(stdin); //to empty the input stream.
scanf("%c",&counter);
}while(tolower(counter) != 'n'); //tolower returns the lowercase character.
printf("\n\nThe total price is: %.2f", totalprice);
return 0;
}
When scanf("%i", &menu) tries to read an integer from the input, it finds A, which it cannot interpret as a number, so it does not read it(*). Then the next scanf continues reading the input from when the other left off and happily reads the letter 'A'. Since you loop as long as the read letter is either 'y' or 'Y' (which A is neither), it exits the loop.
(*) read up on the documentation of scanf to see how to tell if it encountered an error.
Note: scanf("%i", &menu) should be scanf("%d", &menu) as%d` is the formatting symbol for integers.
One solution would be to change the loop condition to:
while (counter!='N' && counter!='n')
{
...
}
This way you end the loop only if an explicit 'N' or 'n' is inputted.
Note: it won't help if you accidentally type 'n' for the menu item, so see the comment about the error handling above.
I'm writing a program in C. In the program, the user has to choose a number, either 1, 2 or 3. I would like to construct the code so that when the user enters in a number that isn't 1, 2 or 3, he/she will be told "Invalid selection - choose again" and then they will be brought back to the start of the program:
int main() {
int choice;
char response, Y, N;
printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n");
scanf("%d",&choice);
if(choice==1||choice==2||choice==3) {
printf("Enter the radius, r\n");
} else
printf("Invalid selection, choose again.\n");
}
What I would like is that after "Invalid selection, choose again" appears, the user is brought back to the start of the program, so they can input their choice again. How would I do this?
Here is what you do:
int choice;
char response, Y, N;
for (;;) {
printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n");
scanf("%d",&choice);
if(choice==1||choice==2||choice==3) {
break;
}
printf("Invalid selection, choose again.\n");
}
Once this loop is over, prompt for the radius. You will nearly certainly need another loop to prevent the input of negative values for the radius, so do not prompt for it in the same loop.
Use a while loop for this
int main()
{
int choice;
char response, Y, N;
printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n");
while(1)
{
scanf("%d",&choice);
if(choice==1||choice==2||choice==3)
{
printf("Enter the radius, r\n");
//Maybe read the radius here
scanf("%d",&radius);
break;
}
else
printf("Invalid selection, choose again.\n");
}
}
use do-while loop, loops until correct input
do like this,add choice 4 for exit:
do {
scanf("%d",&choice);
int flag=0;
if(choice==1||choice==2||choice==3) {
printf("Enter the radius, r\n");
} else {
printf("Invalid selection, choose again.\n");
flag=1;
}
} while(flag==1&& choice!=4);
Some people will object to this, but I think in these situations a plain old goto is a very clean and readable way of doing things, because it emphasizes the linearity of the "normal" control path:
int main(int arg, char *argv[])
{
int choice;
choose_shape:
printf("Choose a shape from the following:\n"
" 1.Sphere\n 2.Cone\n 3.Cylinder\n");
scanf("%d", &choice);
if (choice < 1 || choice > 3) {
printf("Invalid selection, please choose again.\n");
goto choose_shape;
}
printf("Enter the radius, r:\n");
...
}
Yes, people have complained about goto so let me justify it some more.
Here is a more sophisticated version that allows you to select a shape by letter:
char c;
shape_t shape;
choose_shape:
printf("Choose a shape: [s]phere, [c]one, c[y]linder:\n");
scanf("%c", &c);
switch (c) {
cases 's':
shape = SHAPE_SPHERE;
break;
case 'c':
shape = SHAPE_CONE;
break;
case 'y':
shape = SHAPE_CYLINDER;
break;
default:
printf("Not a valid shape: %c\n", c);
goto choose_shape;
}
And here is the version with goto. Note that this introduces another variable, flag, whose only purpose is to get rid of the goto statement. You cannot simply use break here (which is an unlabeled goto to begin with) because of the switch statement. I consider this harder to read due to the additional state. It's five lines longer.
char c;
shape_t shape;
int flag;
for (flag = 0; !flag; ) {
printf("Choose a shape: [s]phere, [c]one, c[y]linder:\n");
scanf("%c", &c);
switch (c) {
cases 's':
shape = SHAPE_SPHERE;
flag = 1;
break;
case 'c':
shape = SHAPE_CONE;
flag = 1;
break;
case 'y':
shape = SHAPE_CYLINDER;
flag = 1;
break;
default:
printf("Not a valid shape: %c\n", c);
break;
}
}
Here is an alternative for you to consider. Notice that the getting of user input is separated into a function and the main() just calls that function and loops on error. Readers of main() probably don't care about how you get the input choice, so why make them read it?
Also notice that I used fgets, not scanf. If you run your version with scanf and enter a non-digit, that character will remain in the input buffer indefinitely; scanf will never remove it as it is looking for digits to satisfy the %d format string - hence an infinite loop. You could try flushing stdin before the scanf (using fpurge) but the function would still not correctly handle the closing of stdin (eg with ctrl-d on the shell UNIX based systems).
#include <stdio.h>
#include <stdlib.h>
static int get_shape(int *shape)
{
char buf[10] = "";
printf("Choose a shape from the following:\n"
" 1.Sphere\n 2.Cone\n 3.Cylinder\n");
if (!fgets(buf, sizeof buf, stdin)) { /* Note: fgets, not scanf */
exit(1); /* ctrl-d */
}
*shape = strtol(buf, NULL, 0);
if (*shape==1 || *shape==2 || *shape==3) {
return 1;
}
printf("Invalid selection\n");
return 0;
}
int main(int argc, char ** argv)
{
int shape = 0;
while (!get_shape(&shape)) {
/* loop */
}
printf("Choice: %d\n", shape);
return 0;
}
here is a simple validation using the while loop, I just copied your code and made a few adjustments, here the code will scan the integer from the user and will proceed to print "Enter the radius, r" only and only if the user types in the integers 1, 2 or 3, otherwise the program will keep on asking him to type in the correct input.
int main() {
int choice;
char response, Y, N;
printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n");
scanf(" %d",&choice);
while((choice<=1)||(choice>=3)){
printf("Invalid selection, choose again.\n");
scanf(" %d",&choice);
}
printf("Enter the radius, r\n");
}