How to get a input with prompt using scanf? - c

I am using c and I am a newbie.
I want to get a input (1 or 2 or 3) and I will give the user suggest;
printf("please do it\n");
printf("1. \n");
printf("2. \n");
printf("3. \n");
char opt;
scanf("%c"&opt");
if opt is not 1 or 2 or 3 then
printf("error\n");
printf("please re do it");
and all is in a while(true) loop until user enter the enter(new line charactor) to exit;
and how to do it?
I tried to create a function.
void get_order(char opt){
switch(opt){
case '1':break;
case '2':break;
case '3':break;
default:
printf("error\n");
printf("please re do it"):
char option;
scanf("%c",&option);
get_order(option);
}
}
but it not work.
thank you.

That is not a good approach, your code is using recursion, it will consume memory more and more while the user don't enter the correct input. Use a loop instead. Your code should look like this:
#include <stdio.h>
int main() {
printf("please do it\n");
printf("1. \n");
printf("2. \n");
printf("3. \n");
char opt;
scanf("%c", &opt); //correct scanf
scanf("%*c"); //consume the line break
while(!(opt == '1' || opt == '2' || opt == '3')) {
printf("error\n");
printf("please re do it\n");
scanf("%c", &opt); //correct scanf
scanf("%*c"); //consume the line break
}
return 0;
}

Related

My c program keeps crashing on as it's starting

I'm making a c program for a simple library but for some reason the program keeps crashing right on startup. Like there's a menu that is displayed but it doesn't even appear it just crashes. can any one help me?
struct library
{
char name[50];
int id;
int qty;
}books[50],copy[50],delet[50],sort[50];
int i=0;
FILE *mybooks;
int main()
{
int choice; char ans;
int id;
int qty;
int s,o=0,j=0;
char name[50];
mybooks=fopen("D:\\mybooks.txt","r");
if (mybooks == NULL) printf("Error. File not found.");
else
{
while(!feof(mybooks))
{
fscanf(mybooks,"%[^\n] %d %d",books[i].name,&books[i].id,&books[i].qty);
strcpy(copy[i].name,books[i].name);
copy[i].id=books[i].id;
copy[i].qty=books[i].qty;
i++;
}
fclose(mybooks);
}
printf("Welcome to the Library.\n");
do
{
printf("Please choose an option:\n");
printf("1.Insert a book\n");
printf("2.Delete a book\n");
printf("3.Search a book by ID\n");
printf("4.Search a book by name\n");
printf("5.Display all books (sorted by name)\n");
printf("6.Display all books (unsorted)\n");
scanf("%d",&choice);
switch (choice){
case 1:
printf("You will need to enter a name, ID, and quantity of the book.\n");
printf("please enter book name:");
fflush(stdin);
fgets(name,sizeof name,stdin);
printf("please enter book ID:");
scanf("%d",&id);
printf("please enter book quantity:");
scanf("%d",&qty);
InsertBook(name,id,qty);
printf("your book has been added successfully\n");
break;
case 2:
printf("Please enter book ID:");
scanf("%d",&id);
DeleteBook(id);
printf("book successfully deleted.\n");
break;
case 3:
printf("Please enter ID of Book:");
scanf("%d",&id);
s=LinearSearch(id,j);
if (s>=0)
{
printf("Book Found.\n");
printf("Name:%s",books[s].name);
printf("ID:%d\n",books[s].id);
printf("Quantity:%d\n",books[s].qty);
}
else
printf("Sorry, the book doesn't exist.\n");
break;
case 4:
printf("Please enter name of book:");
fflush(stdin);
gets(name);
sorting();
s=BinarySearch(name,0,i);
printf("Book Found.\n");
printf("ID:%d\n",sort[s].id);
printf("Quantity:%d\n",sort[s].qty);
break;
case 5:
sorting();
while (o<i);
{
printf("%s\n",sort[o].name);
o++;
}
printf("\n");
break;
case 6:
while(o<i)
{
printf("%s",books[o].name);
o++;
}
break;
default:
printf("Invalid Choice. Please try again.\n");
break;
}
printf("do you want to choose another option?(y/n) ");
scanf(" %c",&ans);
}while(ans == 'y');
}
(I'm using functions for the library but I don't think they are causing any problem since i didn't call them yet.)
edited the question to add the structure
You have tested an end of file condition before performing any i/o on the input file. And then, when you perform the i/o with fscanf(), you did not test the result to see if the variables were successfully read.
What is happening is that scanf() is probably failing and you do not reach the end of the loop, i.e., the EOF condition. You get stuck in there until one of your assignments (strcpy(copy[i].name,books[i].name);, copy[i].id=books[i].id; or copy[i].qty=books[i].qty;) will finally cause an overflow.
To verify this, run the code in a debugger.
Using fscanf() is very tricky, always test it thoroughly.

Prompt error when user enters a char instead of an expected int

I'm making a menu that lists options 1-3. The user is expected to enter an integer.
scanf("%d", &select_option)
How do I prompt error when user enters a char (for example "a", or "asd" for long strings, or a mixture like "1a2") instead of an expected int? Thanks.
Note: When the user enters a 'char' like 'a', 'asd', the code goes into an infinite loop for some reason.
Here's my program (minimal example):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("Favourite sports? \n");
printf("1. Tennis\n");
printf("2. Badminton\n");
printf("3. Basketball\n");
printf("4. Exit program.\n");
printf("Enter your choice (1-4): ");
scanf("%d", &select_option);
while(select_option != 4)
{
switch(select_option)
{
case 1:
printf("You like tennis! Nice! \n");
break;
case 2:
printf("You like badminton! Nice!");
break;
case 3:
printf("You like basketball! Nice!");
break;
default:
system("clear");
printf("Invalid option. Please re-enter your choice (1-4).\n");
}//end switch
printf("Favourite sports? \n");
printf("1. Tennis\n");
printf("2. Badminton\n");
printf("3. Basketball\n");
printf("4. Exit program.\n");
printf("Enter your choice (1-4): ");
scanf("%d", &select_option);
}//end while
}//end main
You could do this:
#include <stdio.h>
int main(void) {
int v;
int ret = scanf("%d", &v);
if(ret == 1)
printf("OK, %d\n", v);
else
printf("Something went wrong!\n");
return 0;
}
where I took advantage of the return value of scanf(), and based on that value, I made an assumption. This will fail for the case of "1a2", but will succeed for "12" and "a".
However, this is a broad question and personally the way I would go for it is:
Use fgets() to read input.
Discard newline.
Convert string to integer (with strtol() for example).
Validate input.
I am assuming u are a beginner. You can use Switch Case which is used usually for creating menus and depending on the choice of the user executes the particular case.
I will show u a small example.
#include<stdio.h>
#include<conio.h>
int main()
{
int n;
printf("Select the sports u want to do\n");
printf("1.Tennis\n2.Karate\n3.Football\n");
scanf("%d",&n);
Switch(n)
{
case 1:printf("You chose Tennis\n");
break; //To prevent from all cases being executed we use
//break which helps from coming out of a loop
case 2:printf("You chose Karate\n");
break;
case 3:printf("You chose Football\n");
break;
default:printf("Please enter an appropriate number !");
//Cases which dont match with the input are handled by default !
}
}
Also to make the user enter input until he wants to exit add a while loop with a variable !
I hope this helps!

Having problems with creating menu in C using do..while and if..else statement

I am new in this world of programming. I am learning programming at my school. My teacher recently ask the class to create a menu with limited selection that will end with a sentinel value.
So here's my coding:
#include <stdio.h>
void menu(void);
void choice1();
void choice2();
void choice3();
char choice;
int main() {
do {
menu();
if (choice =='1')
choice1();
else if (choice =='2')
choice2();
else if (choice =='3')
choice3();
else if (choice =='4')
break;
else
printf("Invalid character.");
} while (choice != '4');
return 0;
}
void menu(void) {
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
scanf("%c", &choice);
}
void choice1() {
printf("\nChoice 1\n");
}
void choice2() {
printf("\nChoice 2\n");
}
void choice3() {
printf("\nChoice 3\n");
}
When I try to run it, by putting the number 1, 2, 3, the output came out but after that the function menu() and also the line "Invalid character." came out. As for as the other character, the menu() and the "Invalid character" came out twice. Number 4 does end the program. Is there any improvement that I can make to make sure the menu() and the line "Invalid character." does not come out unnecessarily?
In line-buffered input, the newline character lingers in the buffer after you read a single character for 'choice' and hence you get Invalid character. unintentionally.
You are required clear the buffer after reading the choice
scanf("%c", &choice);
while(getchar()!='\n')
/* Wasting the buffer
* Hence ensuring that the character you enter
* is indeed considered for 'choice'
*/
;; // Do nothing in particular
As a side note, your program looks like a typical use-case for the switch-case command and maybe your teacher expects you to use it.
Considering the scenario mentioned by #chqrlie in [ this ] comment, the workaround is to add after
scanf("%c", &choice);
the below lines
int c;
while ((c = getchar()) != EOF && c != '\n')
;; //Wasting the buffer
The problem is simple: the terminal is line buffered: you must press enter for the input to become available to your program, the first scanf("%c", &choice) retrieves the character typed and the second call retrieves the linefeed ('\n') that was generated by the enter key.
There are multiple ways to avoid this problem. You can add a space in the scanf format before the %c: scanf(" %c", &choice); or you can read characters after the first until you get a '\n'.
Note that you must check the return value of scanf to avoid undefined behavior if the user enters an end of file. It is also advisable to avoid global variables: the function menu() should return the choice specified. Using a switch statement is also more idiomatic for this.
Here is a corrected version:
#include <stdio.h>
int menu(void);
void choice1(void);
void choice2(void);
void choice3(void);
int main(void) {
int ch;
for (;;) {
switch (ch = menu()) {
case '1': choice1(); continue;
case '2': choice2(); continue;
case '3': choice3(); continue;
case '4':
case EOF: break;
default: printf("Invalid character %c\n", ch); continue;
}
break;
}
return 0;
}
int menu(void) {
char choice;
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
if (scanf(" %c", &choice) == 1)
return choice;
else
return EOF;
}
void choice1(void) {
printf("\nChoice 1\n");
}
void choice2(void) {
printf("\nChoice 2\n");
}
void choice3(void) {
printf("\nChoice 3\n");
}
As already mentioned in other answers the problem is the newline character.
When you press 1 followed by enter, you'll get two chars, i.e. 1 and \n. So your loop runs twice and prints Invalid character when \n is processed.
Here is an alternative solution for your problem. Just add a space before %c.
scanf(" %c", &choice);
This works because the space will match any number of white-space characters and thereby match the \n and remove it.
From the man page:
A sequence of white-space characters (space, tab, newline,
etc.......). This directive matches any amount of
white space, including none, in the input.
Additional comments
You should always check the value returned by scanf to make sure you read the correct number of values.
if (scanf(" %c", &choice) != 1)
{
// Add error handling ....
// For instance you could terminate the program like
exit(1);
}
In your program choice is a global variable. In general global variables should be avoid if possible. In your case you could make choice a local variable in main and let menu return a char. Like:
// char choice; Remove global variable
int main() {
char choice; // Add local variable
do {
choice = menu(); // Assign to local variable
.....
}
char menu(void) { // Make the function return a char
char choice; // Add local variable
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
if (scanf("%c", &choice) != 1) exit(1); // Assign to local variable
// On failure -> exit
return choice; // Return value of local variable
}
You can write scanf(" %c",&choice); (with whitespace) instead of scanf("%c",&choice);
When I try to run it, by putting the number 1, 2, 3, the output came
out but after that the function menu() and also the line "Invalid
character." came out.
It's happening because of the new line character you press after each number. It's itself a character and loop is iterated one more time for this. As it is an invalid character, that's why "Invalid character." is showing.
Try using getchar() after scanf().
Edit: fixed my previous while loop which may exit incorrectedly:
#include <stdio.h>
int main() {
int choice;
printf("Menu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("2) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
while (1) {
char c = scanf("%d",&choice);
if (c == EOF || choice == 4) break;
if (choice == 1 || choice == 2 || choice == 3) {
printf("Choice %d.\n", choice);
} else {
printf("Invalid character.\n");
}
}
return 0;
}
You can use function if you want, but not necessary in this case. You need to understand how many times your loop actually runs and compare it to that you expect.
My previous code:
#include <stdio.h>
int main() {
int choice;
printf("Menu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("2) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
while (scanf("%d", &choice) && choice != 4) {
if (choice == 1 || choice == 2 || choice == 3) {
printf("Choice %d.\n", choice);
} else {
printf("Invalid character.\n");
}
}
return 0;
}

Simple Option Menu (C)

I am trying to make a simple option menu that is executed within a do- while loop. The menu has 5 different options. I am currently trying to test the the get initial option but when I choose the case 'b' the function does not even execute and the option menu reappears again
#include "mathprogram.h"
int main (void)
{
char menu_option,initials;
int difficulty;
printf(" EDUCATIONAL MATH PROGRAM!!!\n");
printf("------------------------------------------\n\n");
do{
printf("Main Menu\n");
printf("a. Learn about how to use program.\n");
printf("b. Enter your initials (3 individual letters).\n");
printf("c. Difficulty Selection.\n");
printf("d. Start a new sequence of problems.\n");
printf("e. Save and quit.\n");
printf(" Please enter an option from the main menu: ");
scanf("%c",&menu_option);
switch(menu_option){
case 'a':
//Learn_to_use();
break;
case 'b':
initials=get_intials();
break;
case'c':
printf("case c");
//difficulty = get_difficulty();
break;
case'd':
break;
case'e':
break;
default:
printf("invalid input");
break;
}
}while(menu_option !='e');
}
get initials function:
#include "mathprogram.h"
char get_intials(void){
char initails;
printf("Please Enter Initials: ");
scanf("%c",&initails);
return initails;
}
scanf("%c", &var);
leaves the newline in the buffer or stream.
Try to change it to
scanf(" %c", &var);
and it should work as expected (Note the space before the %; this consumes the whitespace so that the next scanf call should work).
However, the initials as defined in your program consist of only one character, not three. I'll leave that up to you to design, that is a different question.
There's a '\n' between option 'b' and the initials char, the "scanf" must handle it.
Complete code that works:
#include <stdio.h>
char get_intials(void){
char initails;
printf("Please Enter Initials: ");
scanf("\n%c",&initails) ;
return initails;
}
int main (void)
{
char menu_option,initials;
int difficulty;
printf(" EDUCATIONAL MATH PROGRAM!!!\n");
printf("------------------------------------------\n\n");
do{
printf("Main Menu\n");
printf("a. Learn about how to use program.\n");
printf("b. Enter your initials (3 individual letters).\n");
printf("c. Difficulty Selection.\n");
printf("d. Start a new sequence of problems.\n");
printf("e. Save and quit.\n");
printf(" Please enter an option from the main menu: ");
scanf("%c",&menu_option);
switch(menu_option){
case 'a':
//Learn_to_use();
break;
case 'b':
initials=get_intials();
printf( "input initials:%c\n", initials) ;
break;
case'c':
printf("case c");
//difficulty = get_difficulty();
break;
case'd':
break;
case'e':
break;
default:
printf("invalid input");
break;
}
}while(menu_option !='e');
}
output:
Please enter an option from the main menu: b
Please Enter Initials: c
input initials:c
/*
This code includes a stray \n from previous input due to which get_initials method was not working properly,it picked up the remanant \n in the input stream and concluded,
flushing the input stream is the solution to the problem, uncomment the code at line 8 to get proper functionality
*/
#include <stdio.h>
char get_intials(void){
char initails;
//fflush(stdin);
printf("Please Enter Initials: ");
scanf("%c",&initails);
return initails;
}
int main (void)
{
char menu_option,initials;
int difficulty;
printf(" EDUCATIONAL MATH PROGRAM!!!\n");
printf("------------------------------------------\n\n");
do{
printf("Main Menu\n");
printf("a. Learn about how to use program.\n");
printf("b. Enter your initials (3 individual letters).\n");
printf("c. Difficulty Selection.\n");
printf("d. Start a new sequence of problems.\n");
printf("e. Save and quit.\n");
printf(" Please enter an option from the main menu: ");
fflush(stdin);
scanf("%c",&menu_option);
switch(menu_option){
case 'a':
//Learn_to_use();
break;
case 'b':
initials=get_intials();
if(initials == '\n')
printf("\n%s\n","I was there in stream as newline");
//printf("\n%c",initials);
break;
case'c':
printf("case c");
//difficulty = get_difficulty();
break;
case'd':
break;
case'e':
break;
default:
printf("invalid input");
break;
}
}while(menu_option !='e');
return 0;
}

Menu not working properly

#include <stdio.h>
#include <stdlib.h> //for the clear screen function
#include <string.h>
struct customer
{
int custID;
char custName[50];
char custAddress[100];
};
typedef struct customer c;
void load_menu(void);
void customers_menu(void);
void createNew(void); //initialize your file
void add_Customer(c c1[30]); //add a new record to the file
FILE *fp;
int main(void)
{
load_menu();
return 0;
}
void load_menu(void)
{
int choice;
do
{
printf("Customer Orders Main Menu. \n\n");
printf("Please enter your choice: \n");
printf("1. Customer's Menu \n");
printf("2. Orders Menu\n");
printf("3. Product Stock Menu\n");
printf("4. Exit\n");
printf("\n");
if (scanf("%d",&choice)==1)
{
switch(choice)
{
case 1: system ("cls");
customers_menu();
printf("\n");
break;
case 2: system ("cls");
orders_menu();
printf("\n");
break;
case 3: system ("cls");
stock_menu();
printf("\n");
break;
case 4: printf("Quitting program!\n");
break;
default: printf("Invalid choice! Please try again\n");
printf("\n");
break;
}
}
else
{
fflush(stdin);
printf("Characters are invalid, please enter a number: \n ");
choice=0;
}
}while((choice !=4));
}
void createNew(void)
{
FILE *fp;
fp=fopen("Customer.dat", "w");
if (fp==NULL)
printf("File creation failed! \n");
else
{
printf("File created! \n");
fclose(fp);
}
}
void add_Customer (c c1[30])
{
int i, n , cc=0;
FILE *fp;
fp=fopen("Customer.dat", "a");
system("cls");
if(fp==NULL)
{
printf("File Creation Failed!");
}
system("cls");
printf("Enter the number of Customers: ");
scanf("%d", &n);
for(i=0;i<n;i++)
{
printf("Customer's ID (numbers only) : ");
scanf("%d", &c1[i].custID);
printf("Customer's Name : ");
gets(c1[i].custName);
printf("Customer's Address : ");
gets(c1[i].custAddress);
fwrite(&c1[i], sizeof(c), 1, fp);
}cc++;
fclose(fp);
}
void recordCount(c c1[30], int *count)
{
add_Customer(c1);
count=0;
count++;
}
void customers_menu(void)
{
int choice;
c c1[30];
int i;
do
{
printf("\n");
printf("Customers Menu \n\n");
printf("Please enter your choice: \n");
printf("1. Add Customer \n");
printf("2.\n");
printf("3.\n");
printf("4. Go back to Main Menu \n");
recordCount (c1, &i);
if (scanf("%d",&choice)==1)
{
switch(choice)
{
case 1: add_Customer(c1);
createNew();
printf("\n");
break;
case 2:
printf("\n");
break;
case 3:
printf("\n");
break;
case 4: printf("Going back to Main Menu\n");
system ("cls");
break;
default: printf("Invalid choice! Please try again\n");
printf("\n");
break;
}
}
else
{
fflush(stdin);
printf("Characters are invalid, please enter a number: \n ");
choice=0;
}
}while((choice !=4));
I have a problem since when I enter the Customers Menu it is staring to execute case 1 immediately (which still doesn't work properly). Can someone help me fix this error please because I tried everything I know and it is still in vain
I think your issue is that in customers_menu() you output the menu, but do not read the selection, instead you call recordCount() which directly calls addCustomer().
After addCustomer() we return the customers_menu() which then calls scanf() for the long gone menu.
A few other notes:
gets() is not good, I suggest you use scanf() (with %s) instead.
Doing a printf() then clearing the screen is a bit pointless.
Error messages should really go to stderr (fprintf(stderr,...)) rather than stdout (printf(...))
You code is a missing trailing }.
cc is added to, but not used.
This problem coming from if (scanf("%d",&choice)==1) because scanf will not return choice. If you enter valid answer (like number), then it returns 1 and switch case work with 1. I think that's the problem.
If you enter char instead of integer, scanf will return 0.

Resources