Reputation:
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?
Upvotes: 3
Views: 29610
Reputation: 1
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");
}
Upvotes: 0
Reputation: 3684
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;
}
Upvotes: 2
Reputation: 213258
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;
}
}
Upvotes: 0
Reputation: 17655
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);
Upvotes: -1
Reputation: 726479
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.
Upvotes: 2
Reputation: 4600
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");
}
}
Upvotes: 1