While / Switch Loop Implementation - c

When I run this code and I hit one of the switch's breaks (excluding case 'x') the first printf statement outputs twice. I'm not sure why this happens. Wondering if anybody can see it right from the code without needing the functions to actually run the program.
int main(void)
{
int key;
char command, word[STRINGMAX];
struct data_node *first=NULL, *ptr, *new_node;
while (command)
{
printf("Enter a list command (+-flx): ");
scanf("%c", &command);
switch(command)
{
case '+' :
printf("'+' detected\n");
printf("Enter key data: ");
scanf("%d", &key);
printf("What string to store?: ");
scanf("%s", &word);
first = ptr = insert(&first, key, word);
break;
case '-' :
printf("'-' detected\n");
printf("Enter key data: ");
scanf("%d", &key);
delete(&first, key);
break;
case 'f' :
printf("'f' detected\n");
printf("Enter a key data: ");
scanf("%d", &key);
find_node(first, key);
break;
case 'l' :
printf("'l' detected\n");
dump_list(first);
break;
case 'x' :
printf("Goodbye.\n");
exit(0);
default :
break;
}
}
return (0);
}
Any help appreciated. Thanks.

Add a getchar() after reading a number and a string as scanf leaves the new line character in the input stream. It is preferable to use fgets().
Vivek

Related

Switch Case is getting triggered by itself in C

I have a file student.txt and it has a content like
Name RollNo Address ...\n
Name RollNo Address ...\n
And I have written a function to search a Name in the file
it's menu driven and goes like
std student;
FILE *file = NULL;
int choice;
char name[20];
while (1)
{
printf("Enter the choice\n1.Insert\t2.Append\t3.Search\t4.Display: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
//insertion
break;
case 2:
// append
break;
case 3:
printf("Enter the student name to be searched: ");
scanf("%d", &name);
search(name, &file);
break;
case 4:
// display
break;
default:
exit(0);
break;
}
}
return 0;
search function is
void search(char ele[], FILE **fileptr)
{
*fileptr = freopen("student.txt", "r", *fileptr);
char line[100];
while (fgets(line, 100, *fileptr) != NULL)
{
if (strstr(line, ele) != NULL)
{
getchar();
printf("Congrats !!\n");
return;
}
}
printf("not found\n");
fclose(*fileptr);
}
But when i run this though has a filename matching filename it goes to an infinite loop and executes display function and triggers search function itself infinitely
It happens when the data is not taken in correctly using a correct format specifier.
In case 3, in the scanf function, use the format specifier
%s
instead of
%d
That will stop the infinite loop.

switch case not working with character value if i input char value the switch doesn't encounter default and starts linfinite loop

---------- > ## Heading ## > when i input a character as an input default case of switch doesn't encounter and loop started > infinite times > > > enter code here
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void create();
void display();
void search();
struct node {
int data;
struct node* link;
};
struct node* head;
int main()
{
int value;
while (1) {
printf("Enter Correct Choice :- \n");
printf("Enter 1 to Create Linklist :- \n");
printf("Enter 2 to Display Linklist :- \n");
printf("Enter 3 to Search Linklist :- \n");
printf("Enter Your Choice Here _________ ");
scanf(" %d", &value);
switch (value) {
case 1:
create();
break;
case 2:
display();
break;
case 3:
search();
break;
default:
printf("Error !! Wrong Choice :- \n");
break;
}
}
return 0;
}
TL;DR- Always check the return value of scanf() for success.
In case of a non-numeric character input, the format specifier %d does not find a match, and no input is consumed (i.e., the invalid input remains in the input buffer). Thus, the switch body executes, most likely it does not find a match with any existing case statement, so the default case statement(s) get executed, and control goes back to while loop.
Then, due to the presence of the invalid input in the buffer (and not getting consumed), the above phenomena keeps on repeating.
The major problem is, in case of scanf() failure, the value of variable value remains uninitialized and indeterminate. It does not construct a well-defined program.
Couple of things:
Always initialize local variables.
Always check for success of scanf() before using the returned value, if you have to use scanf(). For better use fgets() to take user input.
In case of failure of input using scanf(), clean up the input buffer before trying to read next input.
The break causes the program to exit the switch case but not the while. To wxit the while as well you should do something like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int value;
int done = 0;
while (!done) {
printf("Enter Correct Choice :- \n");
printf("Enter 1 to Create Linklist :- \n");
printf("Enter 2 to Display Linklist :- \n");
printf("Enter 3 to Search Linklist :- \n");
printf("Enter Your Choice Here _________ ");
scanf(" %d", &value);
switch (value) {
case 1:
printf("do stuff\n");
break;
case 2:
printf("do stuff\n");
break;
case 3:
printf("do stuff\n");
break;
default:
printf("Error !! Wrong Choice :- \n");
done = 1;
break;
}
}
return 0;
}
Here I used a variable initialized to 0 which indicates that the operation is not completed yet. When it's time to exit, the variable is set to 1, which causes the program to exit the while loop
Also, always remember to check the return value of printf(), to avoid possible errors
There is no break condition for while().
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void create();
void display();
void search();
struct node {
int data;
struct node* link;
};
struct node* head;
int main()
{
int value = 1;
while (value) {
printf("Enter Correct Choice :- \n");
printf("Enter 1 to Create Linklist :- \n");
printf("Enter 2 to Display Linklist :- \n");
printf("Enter 3 to Search Linklist :- \n");
printf("Enter 0 to exit :- \n");
printf("Enter Your Choice Here _________ ");
scanf(" %d", &value);
switch (value) {
case 1:
create();
break;
case 2:
display();
break;
case 3:
search();
break;
default:
printf("Error !! Wrong Choice :- \n");
break;
}
}
return 0;
}
if a non valid integer is enter for scanf(" %d", &value); value is not set and the invalid input is not flush => scanf will never block nor update value
you need to check scanf returns 1 (you read 1 value) and if not to flush the invalid input for instance reading all the line
so you can replace
scanf(" %d", &value);
switch (value) {
...
}
by
if (scanf("%d", &value) != 1) {
puts("invalid input");
while ((value = getchar()) != '\n') {
if (value == EOF) {
puts("EOF, exit");
exit(-1);
}
}
}
else {
switch(value) {
...
}
}
of course you can also manage the invalid input in your default case forcing an invalid value :
if (scanf("%d", &value) != 1) {
while ((value = getchar()) != '\n') {
if (value == EOF) {
puts("EOF, exit");
exit(-1);
}
}
value = -1; /* any value except 1,2 or 3 */
}
switch(value) {
...
}
Out of that you have no option to stop the execution, you can do :
...
puts("Enter 4 to exit :-);
...
switch (value) {
...
case 4:
exit(0);
...
}
I belive your intention is to run the program as long as "0" is not entered, but ter is no case for "0". also when we have scanf for %d and entering a "char" instead scanf will not read the char from buff. data on value will not get changed and it will keep printing existing data. (garbage if we enter invalid data first time itself, or any entered data.)
used fgets to read the input data, and do a scanf from buf, even when data is incorrect we are clearing the std input. so program will not get in to a infinite loop with scanf failure.
initilised "value = 0"
added case for "0".
scanf is replaced with fget +sscanf
#include <stdio.h>
#include <stdlib.h>
int main()
{
int value = 0;
char buff[256] = {0};
while (1) {
value = -1;
printf("Enter Correct Choice :- \n");
printf("Enter 1 to Create Linklist :- \n");
printf("Enter 2 to Display Linklist :- \n");
printf("Enter 3 to Search Linklist :- \n");
printf("Enter Your Choice Here _________ ");
fgets(buff, 255, stdin);
sscanf(buff, "%d", &value);
switch (value) {
case 1:
//create();
printf("case : 1\n");
break;
case 2:
//display();
printf("case : 2\n");
break;
case 3:
//search();
printf("case : 3\n");
break;
case 0 :
printf("case : 0 : Exiting program\n");
return 0;
default:
printf("Error !! Wrong Choice :- %d\n", value);
break;
}
}
return 0;
}

Why does getchar() not pause after a switch case and inside a while loop?

#include <stdio.h>
#include <stdlib.h>
main()
{
int Q = 1;
while(Q==1)
{
system("clear");
printf("MAIN MENU\n");
printf("--------------------------------------\n");
printf("1 - See all files\n");
printf("2 - See all files with permission\n");
printf("3 - VIM Editor\n");
printf("4 - EXIT\n");
fputs("Enter Choice : ",stdout);
char ch = getchar();
switch(ch)
{
case '1' : system("ls"); break;
case '2' : system("ls -l"); break;
case '3' : system("vi"); break;
case '4' : Q=0; break;
default : puts("Wrong Choice.."); break;
}
fflush(stdin);
fputs("PRESS ENTER TO CONTINUE...",stdout);
getchar();
}
}
The getchar() does not pause rather it just clears the screen and starts the menu again.
What is the cause of such problems?
I am using tutorialspoint codingground online compiler.
You could identify the problem yourself if you displayed what the unexpected character is:
default: printf ("Unrecognized choice: '%c' (%d)", ch, ch); break;
That is not a bad technique to use in any similar situation. If the code somehow gets unexpected input, say so and show what is known.
This happens because fflush() doesn't always flush the stdin and it's not the safest method to clear the buffer. Try using scanf(" %c", &yourcharvariable) instead or else you should use another getchar() to consume the '\n' left by your first input.
Try this code instead:
#include <stdio.h>
#include <stdlib.h>
main()
{
int Q = 1;
while(Q==1)
{
system("clear");
printf("MAIN MENU\n");
printf("--------------------------------------\n");
printf("1 - See all files\n");
printf("2 - See all files with permission\n");
printf("3 - VIM Editor\n");
printf("4 - EXIT\n");
fputs("Enter Choice : ",stdout);
char ch = getchar();
switch(ch)
{
case '1' : system("ls"); break;
case '2' : system("ls -l"); break;
case '3' : system("vi"); break;
case '4' : Q=0; break;
default : puts("Wrong Choice.."); break;
}
fflush(stdin); // This doesn't always work.
getchar(); // It consumes the '\n' left by your first getchar().
fputs("PRESS ENTER TO CONTINUE...",stdout);
getchar();
}
}

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;
}

Basic Linked List operations in C

I am creating a program to perform basic linked list operations. Right now i have wrote the code only for inserting the node at the front. I ran my program to see its working or not but the program is terminating after accepting the input for the node, then it prints the message after switch. It doesn't even pause for accepting my input for continuing the operations (just before end of main())
here is the code :
#include <stdio.h>
#include <stdlib.h>
struct linkedlist
{
int num;
struct linkedlist *next;
};
struct linkedlist *head = NULL;
void display();
void insertBeginning()
{
struct linkedlist *obj;
int no;
obj = (struct linkedlist *)malloc(sizeof(struct linkedlist));
if(obj == NULL)
{
printf("\n Overflow ");
}
else
{
printf("\n Enter the number = ");
scanf("%d", &no);
obj->num = no;
if(head == NULL)
{
head = obj;
obj->next = NULL;
}
else
{
obj->next = head;
head = obj;
}
}
}
void display ()
{
struct linkedlist *head2 = head;
while(head2 != NULL)
{
printf("%d ->",head2->num);
head2=head->next;
}
printf("NULL \n");
}
int main()
{
int choice;
char wish;
printf("\n 1. Insert at beginning");
printf("\n 2. Insert at end");
printf("\n 3. Insert in between");
printf("\n 4. Delete from front");
printf("\n 5. Delete from end");
printf("\n 6. Delete from in between");
printf("\n 7. Reverse");
printf("\n 8. Sort ascending");
printf("\n 9. Sort descending");
printf("\n 10.Swap alternate elements");
printf("\n 11.Display\n\n");
do
{
printf("\n Enter the option = ");
scanf("%d", &choice);
switch(choice)
{
case 1:
insertBeginning();
break;
case 2:
// insertEnd();
break;
case 3:
// insertInbetween();
break;
case 4:
// deleteFront();
break;
case 5:
// deleteEnd();
break;
case 6:
// deleteInbetween();
break;
case 7:
// Reverse();
break;
case 8:
// sortAsc();
break;
case 9:
// sortDesc();
break;
case 10:
// swap();
break;
case 11:
display();
break;
default:
printf("\n Wrong choice ");
}
printf("\n Do you wish to continue (y/n) = ");
scanf ("%c",&wish);
}while(wish == 'y' || wish =='Y');
return 0;
}
In your case, you have to change
scanf ("%c",&wish);
to
scanf (" %c",&wish);
because, if you don't include the leading white-space before the format specifier, it will consider the remaining \n (newline) which got generated and stored into the input buffer by pressing ENTER key after the first input. So, the second scanf() won't wait for the user input.
when calling scanf()
1) with a '%d' format specifier, the trailing newline, from where the user entered the number, will not be consume.
2) with a '%c' format specifier, leading white space, like a newline, will cause the scanf() to fail, leaving the parameter (wish) unchanged.
3) in the posted code, when the 'wish' does not contain a valid 'Y' or 'y' then the program exits.
I agree with the other poster, that adding a choice '0' for exiting would be a much better way than the separate call to scanf()
there is a new line after giving the input 'choice' which scan by the variable 'wish'. So we need to remove that newline ('\n').
So if you want the user to continue just use a getchar() before take the input wish. Its easy and simple.
printf("\n Do you wish to continue (y/n) = ");
getchar();
scanf ("%c",&wish);

Resources