In my C program which is using switch I have problem with my int variable.
My code is:
while(1) {
printf("0. END\n1. TRANSLATE\n2. TEST FROM LESSON\n3. RANDOM"
" WORDS TEST\n4. SHOW DICTIONARY\n5. ADD WORD\n"
"6. DELETE WORD\nYOUR CHOICE: ");
scanf("%d",&option);
fflush(stdin);
printf("\n");
switch(option) {
case 0: {
exit(0);
break;
}
case 1: {
system("cls");
translate();
printf("\n");
break;
}
case 2: {
system("cls");
lessons();
printf("\n");
break;
}
case 3: {
randomFromLessons();
printf("\n");
break;
}
case 4: {
system("cls");
allWords();
printf("\n");
break;
}
case 5: {
system("cls");
addWord();
break;
}
case 6: {
system("cls");
deleteWord();
printf("\n");
break;
}
default: {
printf("---------------\n");
printf("WRONG VALUE.\n");
printf("---------------\n\n");
}
}
}
When I type 'd' into option var. it shows default, which is what I want, BUT when I press number 1 which starts method named "translate()" and then get back into main menu and press 'd' again it gets me back into "translate()" instead of showing the default.
When I use char instead of int, there is no problem.
So, what exactly is the problem? What keeps happening? What am I doing wrong? Isn't using char in switch the best option overall then?
If you wish to allow text input, you should read the input as a string with fgets and then convert to integers as needed.
If you only wish to accept numbers, you should check the result of scanf to see if it succeeded - in this case it will return 1 when successful, in case it managed to read 1 parameter. If not successful, it won't overwrite option but keep the previous value - that's why you get the behavior you describe.
Furthermore fflush(stdin); is undefined behavior since fflush was never meant to be used on input streams. To just discard the line feed character from stdin you can add single getchar().
So you could fix the code into something like this:
int result;
while(1)
{
result = scanf("%d",&option);
getchar();
if(result == 1)
break;
else
printf("some error message\n");
}
switch(option)
...
I am trying to show the user a menu and allow them to pick from the options. It's in a while loop because it has to iterate until option "e" is picked to exit the program. I included the "default" option as a fail-safe for if the user inputs a value that is not accepted. The default case always runs no matter what I do and the menu always appears twice after the initial run of the code.
I have tried changing "getchar()" to the scanf and it still produces the same duplicated output. I have also tried doing away with the switch entirely, but I get the same result using if/then statements. I have attached my full code and any help is appreciated thank you!!
#include <stdio.h>
#include <stdlib.h>
// function for the menu
char menu() {
printf("Please select from the following menu: \n");
// setting up the menu from here
printf("a. input the data files location \n");
printf("b. enter the time interval \n");
printf("c. process and display the US Life Expectancy Data \n");
printf("d. process and display the Statistics of All Data \n");
printf("e. exit the program \n");
}
char options(char choice) {
switch (choice) {
case 'a':
printf("choice a\n");
break;
case 'b':
printf("choice b\n");
break;
case 'c':
printf("choice c\n");
break;
case 'd':
printf("choice d\n");
break;
case 'e':
break;
default: // default when none of the cases are matched
printf("Invalid input\n");
break;
}
}
// main function
int main(void) {
char choice;
do {
menu();
while ((choice = getchar()) == "\n") {};
if (choice == EOF) {
exit(1);
}
options(choice);
} while (choice != 'e');
}
The problem is that your code doesn't handle newlines. In other words when you type a followed by ENTER, your code actually receives two characters. The 'a' and a '\n'. Therefore the menu will be printed twice and you get an "invalid input".
A quick fix could be:
choice = getchar(); --> while ((choice = getchar()) == '\n') {};
That said, you should change choice to be an int and also do:
int choice;
....
....
while ((choice = getchar()) == '\n') {};
if (choice == EOF)
{
// Fatal input error
exit(1);
}
Finally, it's a bad idea to have choice as a global. Instead put it in main and pass it as an argument to the function options. But don't pass it to menu. So do:
char options() { --> char options(int choice) {
and
int main(void) {
int choice;
do {
menu();
while ((choice = getchar()) == '\n') {}; // ignore newlines
if (choice == EOF)
{
// Fatal input error
exit(1);
}
options(choice);
} while (choice != 'e');
}
It's my first time asking here, so I'm sorry in advance if my post is a bit messy. I'm a freshman and my finals is to make an atm program.
My program uses switch statements for the options: the first one asks the user for their info, (account number, account name, PIN, initial deposit), while the second one is for the actual transactions: Balance check, Deposit and Withdrawal. Before you could do any one of those options, of course I'll have to check if the info (in this case the account number and PIN) matches the ones in my file.
The file is in binary. My problem is that my code for reading the file works fine if i want to display the contents of my file (all the data entries that I populated the file with are shown), but when i want to use the contents of the file (searching inside the file for a match of the user inputted account number) it only reads the first line of the file, thus only the first data entry works, while the one's after that are not read.
My question is, what am i doing wrong in my code? its confusing because if I change my code to display the contents it shows everything, meaning it reads the whole file. but when i want to search the file using a conditional statement, only the first data entry gets read. Thank you very much for your time
tldr: can't use data in file for conditionals (verify the data inside the file, cuz my code doesn't read it whole apparently, except for the first entry)
but if i print the contents it reads it fully
my outputs
1.My data entries
data entries
2.Entering the Account no. of the 1st one (desired output)
desired output
3.Entering The account no. of the 2nd one (Problem part)
problem
my main code
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<process.h>
struct account
{
int no;
char name[100];
int pin;
float id;
};
main()
{
FILE *fptr;
fptr = fopen("accrec.dat","ab");
if (fptr == NULL)
{
printf("File does not exists \n");
return 0;
}
system("cls");
struct account accrec;
int i,tpin[4];
char step1,ch;
printf("\t\tWelcome to Banking System\n\t");
printf("\nA.Open an Account\n");
printf("\nB.Bank Transaction\n");
printf("\nC.exit\n");
scanf("%c",&step1);
switch (step1)
{
case 'A':
printf("Open a New Account\n");
printf("\nEnter the following information\n");
printf(" \n5-digit Account number:");
scanf("%d",&accrec.no);
getchar();
printf("\nAccount Name:");
scanf("%[^\n]s",&accrec.name);
printf("\n4-digit Account PIN:");
/*for(i=0;i<4;i++)
{
ch = getch();
tpin[4] = ch;
ch = '*' ;
printf("%c",ch);
}mask works but does not allow PIN saving */
scanf("%d",&accrec.pin);
printf("\nInitial deposit:");
scanf("%f",&accrec.id);
fwrite(&accrec,sizeof(struct account),1,fptr);
fclose(fptr);
break;
case 'B':
{
fptr = fopen("accrec.dat","rb");
int choice;
int accno = 0;
printf("Enter Your Account no.");
scanf("%d",&accno);
while (fread(&accrec,sizeof(account),1,fptr)!=NULL)
{
if(accno == accrec.no)
{
printf("\tWelcome to PUPQC Banking System\n");
printf("1.Balance Inquiry\n");
printf("2.Deposit\n");
printf("3.Withdrawal\n");
printf("4.quit\n");
scanf("%d",&choice);
}
else
{
printf("account doesn't exist\n");
exit(1);
}
fclose(fptr);
switch (choice)
{
case 1:
printf("BALANCE INQUIRY\n");
printf("Current Balance:");
fptr = fopen("accrec.dat","rb");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
printf("Account No: %d\n",accrec.no);
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL);
{
printf("Initial Deposit is %0.2f\n",accrec.id);
}
printf("%d\n",&accrec.id);
break;
case 2:
float dv;
printf("DEPOSIT\n");
printf("Current Balance:");
fptr = fopen("accrec.dat","rb");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL);
{
printf("%0.2f\n",accrec.id);
}
printf("Enter amount to deposit:\n");
printf("Deposit Value:");
scanf("%0.2f",&dv);
accrec.id = accrec.id + dv;
fwrite(&accrec,sizeof(struct account),1,fptr);
fclose(fptr);
break;
case 3:
float wv;
printf("WITHDRAWAL\n");
printf("Current Balance:");
fptr = fopen("accrec.dat","rb+");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL);
{
printf("%0.2f\n",accrec.id);
}
printf("Enter amount to withdraw:\n");
printf("Withdrawal Value:");
scanf("%0.2f",wv);
accrec.id = accrec.id - wv;
fwrite(&accrec,sizeof(struct account),1,fptr);
fclose(fptr);
break;
case 4:
printf("thank you for your patronage \n");
return 0;
break;
default:
printf("error 404");
break;
}
}
}
break;
case 'C':
printf("Thank you! Have a good day");
return 0;
break;
case 'D':
fptr = fopen("accrec.dat","rb");
if (fptr == NULL)
{
printf("File Cant be read");
exit(1);
}
printf("Data From file\n");
while(fread(&accrec,sizeof(struct account),1,fptr)!=NULL)
printf("\n acc.no is %d\n acc.name is %s\n PIN %d\n Initial Deposit is %0.2f\n ",accrec.no,accrec.name,accrec.pin,accrec.id);
fclose(fptr);
getch();
break;
default:
printf("invalid input! please select form the options given\n");
}
}
my structure
struct account
{
int no;
char name[100];
int pin;
float id;
};
code for finding a match of account number in my file
(the part i'm having trouble with)
fptr = fopen("accrec.dat","rb");
int choice;
int accno = 0;
printf("Enter Your Account no.");
scanf("%d",&accno);
while (fread(&accrec,sizeof(account),1,fptr)!=NULL)
{
if (accno == accrec.no)
{
printf("\tWelcome to Banking System\n");
printf("1.Balance Inquiry\n");
printf("2.Deposit\n");
printf("3.Withdrawal\n");
printf("4.quit\n");
scanf("%d",&choice);
}
else
{
printf("account doesn't exist\n");
exit(1);
}
}
fclose(fptr);
The expected output is that my conditional statement works properly and reads my whole file for matches.
try to change the exit(1) to continue;, the exit(1) will make your program quit the while loop and exit the program immediately whenever accno != accrec.no.
in fact, you don't need the else statement inside the while loop, you should put it outside the while loop. for example:
scanf("%d",&accno);
boolean found = false;
while (fread(&accrec,sizeof(account),1,fptr)!=NULL)
{
if (accno == accrec.no)
{
found = true;
scanf("%d",&acpin);*/
printf("\tWelcome to Banking System\n");
printf("1.Balance Inquiry\n");
printf("2.Deposit\n");
printf("3.Withdrawal\n");
printf("4.quit\n");
scanf("%d",&choice);
}
}
if (!found) {
printf("account doesn't exist\n");
}
fclose(fptr);
I am kind of a beginner and have a little problem when trying to loop a menu.
Let's take this for example:
int option = 0;
do {
printf("Menu\n");
printf("[1] Insert\n");
printf("[2] List\n");
printf("[0] Exit\n");
printf("\nOption: ");
scanf("%i",&option);
switch(option)
{
case 1: {
// code
break; }
case 2: {
// code
break; }
default: {
// error
}
}
} while(option != 0);
This will work for numbers, yet, as the option is an integer, if the user types a text, such as "a" or "owkefok" or even "ewf432k", the program will just break;
How do I give an error such as if(containstcharacters) then(error) while repeating the menu? Is it possible without changing the option to char?
You can check for return value of scanf(). Like this :
int num;
if(scanf("%d%c", &num) != 1)
printf("failure\n");
else
printf("valid integer followed by enter key\n");
On success, the function 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.
In simple words, if it can read your user input it will return the number of item it could read successfully.
So in your case the code will be :
int option = 0;
do {
printf("Menu\n");
printf("[1] Insert\n");
printf("[2] List\n");
printf("[0] Exit\n");
printf("\nOption: ");
scanf("%i",&option);
int check = scanf("%d%c", &num);
if(check!=1) {
//error
}else{
switch(option)
{
case 1: {
// code
break; }
case 2: {
// code
break; }
default: {
// error
}
}
} while(option != 0);
}
Instead of
scanf("%i",&option);
use e.g.
char str_option[100];
scanf("%s", &str_option);
so you will read into a string instead to an int. Then you may extract the first character of it and convert it to its numerical value (in spite it doesn't need be a digit) by the well-known trick
option = str_option[0] - '0' // Converts '0' to 0, '1' to 1, and so on
Then you need not change the rest of your code except for inserting in your switch statement:
case 0 : break; // To not fall into "default:" for error-handling
(By the way you need not use { } in the individual cases of the switch statement as all commands are executed regardless of them until they meet break; .)
This is my code, please have a look. My menu keeps looping and does not ask for any input. I do not know why fgets does not work as expected.
When I run my code it will keep looping even though when I get rid of the loop:
int main ()
{
char input[3];
char opt1;
int flag=1,n;
/*hrtime_t start, end;*/
dlist_t lst;
list_init (&lst);
list_input (&lst);
bubblesort (&lst);
list_display(&lst);
while(flag == 1)
{
printf("\nMain Menu\n");
printf("-----------\n");
printf("1. Bubble Sort\n");
printf("2. Selection Sort\n");
printf("3. Quick sort\n");
printf("4. Merge Sort\n");
printf("5. Exit\n");
printf("\nEnter your option[1-5]: ");
fgets(input, 3, stdin);
opt1 = input[0];
/* If condition to display the main menu if user inputs enter */
if(opt1 == '\n')
{
flag =1;
continue;
}
n = strlen(input)-1;
if(input[n] == '\n')
{
input[n] = '\0';
} else {
printf("\nInvalid input. ");
printf("Please note that the maximum length of the input is 1.");
readRestOfLine();
flag =1;
continue;
}
switch(opt1)
{
case '1':
/*start = gethrtime();
bubbleSort(list);
end = gethrtime();*/
printf("\nBubble Sorted List\n");
break;
case '2':
/* start = gethrtime();
selectionSort(list);
end = gethrtime(); */
printf("\nSelection Sorted List\n");
break;
case '3':
/*start = gethrtime();
quickSort(list, 0, list->list_len-1);
end = gethrtime(); */
printf("\nQuick Sorted List\n");
break;
case '4':
/*start = gethrtime();
list->head = mergeSort(list->head);
mergeSortReverse(list);
end = gethrtime(); */
printf("\nMerge Sorted List\n");
break;
case '5':
SNExit();
list_free (&lst);
printf("\n\n ********* THANK YOU **********");
return EXIT_SUCCESS;
default :
{
printf("\nPlease enter valid option\n");
break;
}
}
}
return EXIT_SUCCESS;
return 0;
}
/****************************************************************************
* Function readRestOfLine() is used for buffer clearing.
****************************************************************************/
void readRestOfLine()
{
int c;
/* Read until the end of the line or end-of-file. */
while ((c = fgetc(stdin)) != '\n' && c != EOF)
;
fflush(stdin);
/* Clear the error and end-of-file flags. */
clearerr(stdin);
}
I don't know... I ran your code and it worked fine for me, so I don't know how you're missing the input. Did you copy the full code?
Since you're only using the first character why read it into a buffer anyway? Perhaps with simplified input you can avoid your error, just get the char:
...
printf("4. Merge Sort\n");
printf("5. Exit\n");
printf("\nEnter your option[1-5]: ");
fflush(stdout);
opt1=getchar();
getchar(); // Extra "getchar" call to get rid of the newline
...
EDIT:
Let's try simplifying your problem to understand where the failure is. Try running this code instead:
int main()
{
char input = '0';
input = getchar();
getchar();
printf("%c\n", input);
return 0;
}
Does that compile/run/work on your system? If so the problem isn't with how you're getting the string/char but something else with your code.