Switch default is not showing when it should - c

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)
...

Related

Switch case 0: entering 0 and entering a letter

int DisplaySchedule()
{
int nDisplaySchedule_Choice;
system("cls");
printf("----- DISPLAY SCHEDULE -----\n");
printf("Pick departure station\n\t");
printf("[1] San Pedro\n\t");
printf("[2] Santa Rosa\n\t");
printf("[3] Calamba\n\n\t");
printf("[9] Go Back\n\t");
printf("[0] Exit\n\n");
printf("Choice: ");
scanf("%d", &nDisplaySchedule_Choice);
printf("\n");
switch (nDisplaySchedule_Choice) {
case 1: SanPedro(); break;
case 2: SantaRosa(); break;
case 3: Calamba(); break;
case 9: OpeningScreen(); break;
case 0: printf("Summary()"); break;
default:
printf("ERROR. INPUT A VALID RESPONSE.\n\n");
DisplaySchedule();
break;
}
return;
}
I have this code in which when I enter a letter, instead of printing the error message, it prints case 0: instead. Is there any way for me to make it so that case 0: will only function if and only if I enter "0" in the scanf statement?
You have undefined behaviour here.
scanf, when scanning for int (%d), fails because you input a character - due to matching failure. Thus not reading anything into nDisplaySchedule_Choice at all.
Since nDisplaySchedule_Choice is uninitialized to start with, it just happens to have 0 and thus goes to case 0.
The solution is to check the scanf return value before proceeding to use nDisplaySchedule_Choice. scanf returns the number of items successfully scanned.
If scanf fails to read a value (for instance because you told it to read an int and gave it a letter) it won't change your variable. So nDisplaySchedule_Choice won't change in a way that you can check in your switch. At least not if you don't initialize it - you can however set it to a value that is not covered by your switch, and if it didn't change, you know that scanf failed to read a value.
Or you could check the return value of scanf to see if it managed to read a value:
int result = scanf("%d", &nDisplaySchedule_Choice);
if (result == 0) {
int c;
while ((c = getchar()) != '\n' && c != EOF); // flush the invalid input
printf("ERROR. INPUT A VALID RESPONSE.\n\n");
DisplaySchedule();
}
else switch ...

I did a switch case program, where it does not execute switch case when I give the input

void booking() { //globally declared function
printf("please select the seats");
printf("1A 2A 3A G");
}
int main() { //Main function
int n;
clrscr();
printf("\t\t\t Railway reservation system");
printf("1.Booking");
printf("2.Availability checking");
printf("3.Cancellation");
printf("4.Prpare chart");
scanf("%d",&n);
switch(n) //when I give input as 1 switch case is not being executed
{
case 1:
booking(); //after the input it should execute this global function.
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
return n;
}
My Aim is when we give the input n it should execute the globally declared functions.After the input it is not getting in to the switch statement.
In fact switch-case is executed, but you're probably not able to see it as your program finishes quickly. Try executing it from command line or put something like this at the end:
do {
printf("Press q to quit: ");
user_in = getchar();
} while (user_in != 'q');
One more thing: put new line character ('\n') at the end of every line in your menu.
Place
printf("Press any key to exit...");
while (!kbhit()) ;
Before return statement, and you will see console screen before it closes.

How to loop a menu which the option variable is int when the user inserts a text?

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; .)

Why does this invalid input still works? (switch case) char error

UPDATED CODE
Why does the input 12 works? It interprets 12 as option 1 and takes 2 for the first scanf of case'1'? I do not want to use int opcao as if I enter a leter it will run indefinitly.
I want that the user can only exit the program when he chooses option exit (one of the cases) thus the do... while.If the user enters an invalid character or leter or whatever the menu shows again and shows the default message. I also want that after the chosen case is executed, it presents the menu again for a new choice thus i am using an always valid condition of 1=1 on the while. I can't use integers as if you enter a leter the program goes bonkers a.k.a never stops running. just try it.
char opcao;
do {
menu();
scanf(" %c",&opcao);
switch(opcao) {
case '1':
printf("Massa do módulo (sem combustível):\n");
scanf("%f",&m_modulo);
printf("Massa de combustível:\n");
scanf("%f",&m_combustivel);
printf("Altitude no início da alunagem em relação a um ponto de referência:\n");
break;
case '2':
break;
case '3':
printf("Funcionalidade nao disponivel.\n");
break;
case '4':
printf("Funcionalidade nao disponivel.\n");
break;
case '5':
printf("Funcionalidade nao disponivel.\n");
break;
case '6':
exit(0);
break;
default:
printf("Opcao invalida, as seguintes opcoes estao disponiveis:\n");
break;
}
}
while(1==1);
That's because you're reading your input with a single %c.
This way, the first character of 12 (1) is used by the switch, while the second is used by the scanf of case '1':.
To avoid this behaviour, you can read the options as integers and use the placeholder %d in your very first scanf.
EDIT:
To avoid your infinte loop problem, you can do like this:
#include <stdio.h>
void clean_stdin();
int main() {
int opcao;
float m_modulo, m_combustivel;
int flag = 0;
do {
printf("Make a choice: ");
if (scanf("%d", &opcao) == 0) {
clean_stdin();
}
else {
switch(opcao) {
case 1:
printf("Massa do módulo (sem combustível): ");
scanf("%f", &m_modulo);
printf("Massa de combustível: ");
scanf("%f", &m_combustivel);
printf("Altitude no início da alunagem em relação a um ponto de referência.\n");
break;
case 2:
break;
case 3:
printf("Funcionalidade nao disponivel.\n");
break;
case 4:
printf("Funcionalidade nao disponivel.\n");
break;
case 5:
printf("Funcionalidade nao disponivel.\n");
break;
case 6:
flag = 1;
break;
default:
printf("Opcao invalida, as seguintes opcoes estao disponiveis:\n");
}
}
} while(flag == 0);
}
void clean_stdin()
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
What I've done is the following:
Check the scanf output if it reads the input correctly (in this specific case, if the input was a number it returned a number different from 0).
Use the function clean_stdin (Credits) to clean characters that scanf read but didn't consumed (it expects a number and you give it a character, so the character stays in stdin and create the infinite loop)
I use a flag to control the loop condition, when the exit option is chosen, flag value is changed to a value that makes the condition fail
I added the main() because I need it to run the program; you can incorporate what's inside in your main. Remember to copy clean_stdin() function.
I suggest you to read some scanf documentation to understand its return value.
I suggest also to read about scanf alternatives, since it's a boring function: link 1 and link2.
Remember to format your code with the right indentation, it's a best practice.
That's how scanf works.
You asked scanf to read a single character from the input stream. The input stream originally contained 12 sequence (more likely, 12<newline> sequence). So, just like you asked it to, scanf consumed that first 1, leaving the rest in the input stream.
The next scanf continued to consume the input stream where the previous one left off.
scanf with the %c can read one character at once. '12' contains two characters '1' and '2'. So '1' will be consumed firstly by the scanf and hence,case '1': gets executed. The '2' is left in the input buffer(stdin) and it will be consumed by the next scanf with a %c.
To avoid this,you could declare opcao as an integer and use the following code:
while(1)
{
if(scanf("%d",&opcao)==0)
{
printf("Invalid input. Try again:");
scanf("%*s"); //remove the invalid input
continue;
}
if(opcao>0 && opcao<7)
break;
else
printf("invalid integer. Try again:");
}
switch(opcao) {
case 1://your code
break;
case 2://your code
break;
case 3://your code
break;
// etc...
case 6:exit(0);
}
//no need of do...while or a default case

How can I repeat scanf in a switch-case scenario if some invalid input has been given?

I have the following code, where I expect the user to give eiher 's' or 'f' (case insensitive) as input:
/* ... snip ... */
char acc_type;
printf("\n\nENTER HERE\t : ");
scanf("%c",&acc_type);
switch (acc_type)
{
case 's':
case 'S':
printf("\n SAVING ACCOUNT");
break;
case 'f':
case 'F':
printf("\n FIXED ACCOUNT");
break;
default:
printf("\n INVALID INPUT!!! TRY AGAIN");
}
/* ... snip ... */
However, the default action doesn't allow me to repeat the whole switch statement. How can I ask for input in his scenario again if the input wasn't valid?
You need a loop, essentially (in pseudo-code):
good_input = 0;
while(good_input == 0) {
... prompt for input ...
if (input == good) {
good_input = 1;
}
}
Until something valid is entered, good_input stays 0 and the while() loop continues to prompt for input. Once something good is entered, that flag changes and the code continues on to the next section.
Put the part you want to repeat in a loop, like this:
bool inputOK = false;
do {
printf("\n\nType S to SAVING ACCOUNT");
printf("\nType F to FIX ACCOUNT");
printf("\n\nENTER HERE\t : ");
scanf("%c",&acc_type);
switch (acc_type)
{
case 's':
case 'S':
printf("\n SAVING ACCOUNT");
inputOK = true;
break;
case 'f':
case 'F':
printf("\n FIXED ACCOUNT");
inputOK = true;
break;
default:
printf("\n INVALID INPUT!!! TRY AGAIN");
break; // Note: it's wise to use break in EVERY case
}
} while (inputOK == false);

Resources