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");
}
Related
I've attempted to find if the user has inputted a product id value that's a duplicate and if so, it just tells them that it's a duplicate value and then returns to the menu in my switch statement.
The actual result i get, is that after "productsfilled == 0", it won't utilise the For Loops to check for the duplicates and productsfilled will remain at 1. I've looked online and this way of finding duplicates tends to work and i have used it previously in my code, so I don't think that could be the issue.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <conio.h>
int productsfilled;
struct ProductData{
int product_id;
char product_name[120];
int price;
};
int quiz_5(){
char ch;
int size, input = 0;
struct ProductData products[20];
while(1){
printf("\nWelcome To The Super Mall's Product List. Please Select An Option:\n1. Add Product\n2. Display Product\n3. Delete Product\n");
fflush(stdin);
switch(getchar()){
case '1':
printf("\nPlease Enter Product ID:");
scanf("%d",&products[productsfilled].product_id);
printf("\nPlease Enter Product Name:");
scanf("%s",&products[productsfilled].product_name);
printf("\nPlease Enter Product Price:");
scanf("%d",&products[productsfilled].price);
printf("Productsfilled: %d",productsfilled);
if(productsfilled == 0){
productsfilled = 1;
break;
}
for(int i = 0; i < productsfilled;i++){
for (int j = i + 1; j < productsfilled;j++){
if(products[i].product_id == products[j].product_id){
printf("\nPlease Use Different Product ID");
break;
}else{
printf("test");
productsfilled += 1;
break;
}
}
}
break;
case '2':
while(1){
for(int i = 0;i < productsfilled;i++){
printf("Product ID: %d Product Name: %s Product Price: %d\n",products[i].product_id,products[i].product_name,products[i].price);
}
printf("Please Press Enter To Continue");
fflush(stdin);
if(getchar() == '\n'){
break;
}
}
case '3':
break;
case '\n':
break;
default:
printf("Please Select An Option:\n1. Add Product\n2. Display Product\n3. Delete Product: ");
}
}
}
int main() {
int input = 1;
printf("Welcome to my assignment. Which quiz do you want to run (please input the number of the quiz e.g. for quiz 1, type 1): \n-Quiz 1\n-Quiz 2\n-Quiz 3\n-Quiz 4\n-Quiz 5\n-Quiz 6\n-Quiz 7\n");
while(input == 1){
fflush(stdin);
switch(getchar()){
case '5':
quiz_5();
break;
case '\n':
printf("Welcome to my assignment. Which quiz do you want to run (please input the number of the quiz e.g. for quiz 1, type 1): \n-Quiz 1\n-Quiz 2\n-Quiz 3\n-Quiz 4\n-Quiz 5\n-Quiz 6\n-Quiz 7\n");
getchar();
default:
printf("Invalid Input\n");
} }
return 0;
}
The problem is that you don't increment productsfilled before you enter the loop...therefore, productsfilled is always 1 less than the actual length of your array which means that you don't compare all elements in the array.
Try your program on 2 inputs, both with the same ID. You'll see that you don't compare anything.
You are wrong when using scanf for string input:
scanf("%s",&products[productsfilled].product_name);
You should not use &, you should use as below:
scanf("%119s",products[productsfilled].product_name);
OT, in main function:
switch(getchar()){
case '5':
...
Because getchar() will return int value, so if you want to access to quiz_5, you have to type 35 (ANSCI code) instead of type 5 when you run your program.
char a = '5';
similar to:
int a = 35;
In the code below I take the input from the user and then I find the digit that was introduced by comparing it to every other digit.
This my code:
#include <stdio.h>
#include <stdlib.h>
int main(){
int i = 0;
int input;
printf("Input a digit: \n");
scanf("%d", &input);
for(; i < 10; i++)
{
if(i == input)
{
printf("Your input is %d\n", i);
break;
}
}
return 0;
}
How do I check for a letter instead? Say the user inputs letter G, and I take that in a loop to compare it to every other character until I find the one it equals to?
You can use pretty much the same code you already have, just scan for a char:
char input;
scanf("%c", &input);
To check the input, use what fits your expectations best. A switch is probably a solid choice:
switch (input) {
case 'G':
printf("G was received\n");
break;
default:
printf("Uninteresting character %c was received\n", input);
}
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().
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.
I am a beginner in C...
I have made a made a calculator type program which uses four basic functions in C using if-else loop.
I want when the program comes to end(after the user has added, subtracted etc. etc. then there is a option "Y/N" so that the program can be restarted???"
Here is the sample of the code
#include<stdio.h>
int main()
{
int choi;
printf("*****Interactive Calculator*****");
printf("\n\nChoose an option...");
printf("\n\n1. Addition\n");
printf("\n2. Subtraction");
printf("\n\n3. Multiplication");
printf("\n\n4. Division");
printf("\n\nPlease Enter your Choice : ");
scanf("%d",&choi);
if(choi==4)
{
float a=0,b=0,c=0;
printf("\nEnter Divident :");
scanf("%d",&a);
printf("\nEnter the Divisor :");
scanf("%d", &b);
c=a/b;
printf("\nThe Quotient is : %d\n\n",c);
char choice;
printf("Do you want to try it again?(Y/N) ");
scanf("%c", &choice);
// I want a code here so that the program can be restarted
getch();
return 0;
}
else
{
printf("\nErr#404-Invalid Character! Please Enter 1,2 or 3 !\n\n");
}
end:
getch();
return 0;
}
The best way would be to do some sort of a while loop.
int goAgain=1;
while (goAgain==1) {
... //Normal code here
printf("Again?")
scanf("%c",&again)
if (again=='N') {
goAgain=0;
}
}
Or you could use a do-while loop as well
do {
... //Normal code here
printf("Again?")
scanf("%c",&again)
} while (again=='Y')
Basically, this will keep looping over the bit of code over and over until the person types N to end it.
A do-while loop would be most suitable for this purpose.
int main() {
char choice;
do {
// Calculator stuff here...
printf("Do you want to try it again? (Y/N) ");
scanf("%c", &choice);
} while (choice == 'Y');
}
Edit: As it turns out, there is another problem with the program above, which is that scanf() reads a character but leaves a Newline character in the buffer. Therefore, if the user types YEnter, the program will repeat once (choice == 'Y' the first time), then exit (choice == '\n' the second time).
It is therefore necessary to keep reading until the Newline has been consumed.
int main() {
char choice;
do {
// Calculator stuff here...
printf("Do you want to try it again? (Y/N) ");
choice = getchar();
while (choice != '\n' && getchar() != '\n') {};
} while (choice == 'Y' || choice == 'y');
}
char continue = 'Y'
while (continue == 'Y') {
... //Normal code here
printf("Again?")
scanf("%c",&continue)
}
you can try like this, avoid go to
#include<stdio.h>
int main()
{
int choi;
while(true)
{
printf("*****Interactive Calculator*****");
printf("\n\nChoose an option...");
printf("\n\n1. Addition\n");
printf("\n2. Subtraction");
printf("\n\n3. Multiplication");
printf("\n\n4. Division");
printf("\n\n5. Exit");
printf("\n\nPlease Enter your Choice : ");
scanf("%d",&choi);
if(choi==1)
{
}
else if(choi==2)
{
}
else if(choi==3)
{
}
else if(choi==4)
{
}
else if(choi==5)
{
return 0; //exit(0);
}
else
{
printf("\nErr#404-Invalid Character! Please Enter 1,2,3,4 or 5 !\n\n");
}
}
return 0;
}
By using do-while loop, which is generally used for menu-driven programs.
#include<stdio.h>
int main()
{
int choi;
char choice;
do{
printf("*****Interactive Calculator*****");
printf("\n\nChoose an option...");
printf("\n\n1. Addition\n");
printf("\n2. Subtraction");
printf("\n\n3. Multiplication");
printf("\n\n4. Division");
printf("\n\nPlease Enter your Choice : ");
scanf("%d",&choi);
if(choi==4)
{
float a=0,b=0,c=0;
printf("\nEnter Divident :");
scanf("%d",&a);
printf("\nEnter the Divisor :");
scanf("%d", &b);
c=a/b;
printf("\nThe Quotient is : %d\n\n",c);
char choice;
printf("Do you want to try it again?(Y/N) ");
scanf("%c", &choice);
// I want a code here so that the program can be restarted
getch();
return 0;
}
else
{
printf("\nErr#404-Invalid Character! Please Enter 1,2 or 3 !\n\n");
}
printf("Want to continue (y/n)?");
scanf("%d", &choice); // Enter the character
}while (choice == 'y' || choice == 'Y');
end:
getch();
return 0;
P.S.: I would suggest you to use switch case, instead of if-else statements to do the job.
You can also use a goto:
int main() {
...
if (c=='y') {
main();
} else {
goto end;
}
end:
...
}