Program ends suddenly, with switch case inside while loop in C - c

I have this program show, which allows me to display a menu with 3 choices. If you choose anything except exit (0) then the program continues to loop.
However, when I try to call a function from inside the switch statement, once the function is finished, the loop exists completely. I want to go back to the menu and continue unless I select exit.
The program works, without the function call.
It also works if I select 2, triangle, it then stays in the loop.
Why is this happening, and how can I fix it,
many thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int rows;
void xmasTree(void)
{
printf("Enter Rows:\n>");
scanf("%d",&rows);
}
int main (int argc, char ** argv)
{
int flag = 1;
while (flag)
{
//Print menu
printf("1: Create xmas tree\n");
printf("2: Create triangle\n");
printf("0: exit\n");
printf("Enter choice :");
//read input
char buffer[10];
fgets(buffer, 10, stdin);
//convert to number
int number = atoi (buffer);
//work on input
switch (number)
{
case 1:
printf("Building your xmas tree\n");
xmasTree();
break;
case 2:
printf("creating your triangle\n");
break;
case 0:
printf("Exiting...\n");
flag = 0;
break;
default:
printf("INVAID INPUT\n");
break;
}
}
return 0;
}

The problem is, that here
scanf("%d",&rows);
you read a number from stdin, but you leave the trailing newline inside the stream!
Then, in the next loop iteration
fgets(buffer, 10, stdin);
reads the (empty) line and
int number = atoi (buffer);
sets number to 0, causing your program to exit.
One possible fix would be to read in rows with fgets() and atoi() as you do it with number.

The problem is this call in the function xmasTree
scanf("%d",&rows);
After it there is stored the new line character '\n' in the buffer. So the next call of the function fgets reads an empty string. You should remove this new line character as for example
scanf("%d",&rows);
scanf( "%*[^\n]" );
scanf( "%*c" );

Related

The result box is a problem due to a gap?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct person {
char name[SIZE];
char address[SIZE];
char mobilephone[SIZE];
char desc[SIZE];
} PERSON;
void menu();
PERSON get_record();
void print_record(PERSON data);
void add_record(FILE* fp);
void search_record(FILE* fp);
void update_record(FILE* fp);
void delete_record(FILE* fp);
int main(void)
{
FILE* fp;
int select;
printf("Enter an integer value: ");
if ((fp = fopen("address.dat", "a+")) == NULL) {
fprintf(stderr, "I can't open the file for input.");
exit(1);
}
while (1) {
menu();
printf("Enter an integer value: ");
scanf_s("%d", &select);
switch (select) {
case 1: add_record(fp); break;
case 2: update_record(fp); break;
case 3: search_record(fp); break;
case 4: delete_record(fp); break;
case 5: return 0;
}
}
fclose(fp);
return 0;
}
void menu()
{
printf("====================\n");
printf(" 1. Additional\n 2. correct\n 3. Search\n 4. elimination\n 5. Termination\n");
printf("====================\n");
}
void search_record(FILE* fp)
{
char name[SIZE];
PERSON data;
fseek(fp, 0, SEEK_SET);
fflush(stdin);
printf("The name of the person you want to explore");
gets_s(name, SIZE);
while (!feof(fp)) {
fread(&data, sizeof(data), 1, fp);
if (strcmp(data.name, name) == 0) {
print_record(data);
break;
}
}
}
As shown in the picture above, entering an integer ignores entering the name and returns to the menu.
Why does this phenomenon appear?
If you press 3 and press the enter, the direction of the function for 3 cannot proceed, and there is a problem of returning to the menu as if it were entered twice in a row.
If this problem is solved, how should we solve it?
enter image description here
Scanf only consumes what you tell it to, leaving the rest in stdin. Gets stops at the first instance of newline or a terminating character.
Your input is "3\n" (newline happens when you press enter). Your scanf pattern consumes the first integer and stops at the first non-numerical character (roughly). In this case that is '\n'. So when you call gets, it immediately consumes the newline left on stdin by scanf and seems to "skip" that input.
fflush(stdin) before taking an input (either scanf or gets) to drop leftover stuff.
Something to think about in the future would be: is the input "3foo\n" still valid? As I mentioned, scanf only reads what you tell it to. So the "foo\n" is ignored by the scanf pattern "%d". Further, the l33t input of "0n3\n" is interpreted as zero despite the user's intention.

Program not asking for new entry if you enter invalid choice in String format

I'm having a problem understanding how to get my while loop to simply output a message saying "Invalid Input" and asking for a new question from the user unless he chooses number 1 or 2 in the list. What happens if you for example input : asdas instead of a integer the program never stops looping.
What I would like to happen is for the program to tell the user to enter a new number from 1-2 instead of simply stopping running which i can achieve by setting the default in the switch to exit(0); or runSystem = false;
For example:
CMD Says enter 1-2 the user enters : asdaf (never stops looping) as in current situation.
What I want is: asdf and then it says "enter a new choice" and waits for a correct answer.
What bothers me is the fact that the program will do as i want it to if you enter an invalid number for example: 12312312 and ask for a new entry but it doesn't work with string input.
Code:
#include <stdio.h>
#include <stdbool.h>
int main(int argc, char **argv) {
int userinput;
int runSystem = true;
void options() {
printf("<========Welcome to the program, please make a choice========> \n\n");
printf("1: Say Hello\n");
printf("2: Say GoodBye\n");
printf("Please enter a choice:");
scanf("%d", &userinput);
}
while (runSystem) {
options();
switch(userinput) {
case 1: printf("Hello!\n");
break;
case 2: printf("GoodBye!\n");
break;
case 3: printf("Invalid, try again\n");
break;
default:
break;
}
}
return 0;
}
scanf("%d", &userinput); expects an int as the input. When you give a non-integer, scanf() won't assign it to userinput.
Check the return value of scanf() to see if it was successful. It returns the number of successful assignments it did.
When you give a string as input, scanf() won't accept it and will leave it in the input buffer unconsumed.
When you do scanf() again, the invalid input is still present in the input buffer and that is what the second scanf() tries to read. The same thing happens and this goes on. This is the reason behind your infinite loop.
To overcome this, you should consume the invalid input from the input buffer after displaying the message in case 3. Do something like
int ch;
while( (ch=getchar())!='\n' && ch!=EOF );
This will consume from the input buffer till a \n is encountered. getchar() return EOF on failure.
Edit: Standard C doesn't allow nested function definitions. The reason why you didn't get an error for that is probably because your compiler allows this as an extension. But it may not work for other compilers.
See this and this.
You could place the definition of options() within the while loop calling it or get the value for userinput as a return value or via a pointer to the variable passed to the function.
Valid C compiler does not allow declaration of the function options inside the main.
Make that function returning your input and pass the returning value to the switch. Also in order to stop the while loop case 2: should change the runSystem to false;
input : asdas instead of a integer the program never stops looping.
This is because when scanf("%d", &userinput); failed it did not updated the variable userinput.
Check the standard 7.21.6.4 The scanf function.
You can read about behaviour of scanf
here.
On success, the scanf 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.
Knowing that you can check the return value of scanf and make appropriate decision. Presented solution eats the bad characters.
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
int options(void) {
int c;
int ret;
int x = 0;
int error = 0;
printf("<========Welcome to the program, please make a choice========> \n\n");
printf("1: Say Hello\n");
printf("2: Say GoodBye\n");
printf("Please enter a choice:");
while(1)
{
c = '0';
if(!error)
printf("Input a number:\n");
else
error = 0;
ret = scanf("%d", &x);
if(ret == EOF) {
return 2; // END OF PROGRAM
}
else
{
if (ret == 1){
return x;
}
else // NOT a number
{
printf("No letters! Input a number:\n");
do
{
c = getchar();
if(c == EOF)
return 2; // END OF PROGRAM
}
while (!isdigit(c) && c!='\n');
ungetc(c, stdin);
error = 1;
}
}
}
}
int main(void) {
int userinput;
int runSystem = true;
while (runSystem) {
userinput = options();
switch(userinput) {
case 1: printf("Hello!\n");
break;
case 2: printf("GoodBye!\n");
runSystem = false;
break;
default:
case 3: printf("Invalid, try again\n");
break;
}
}
return 0;
}
Output:
<========Welcome to the program, please make a choice========>
1: Say Hello
2: Say GoodBye
Please enter a choice:Input a number:
X
No letters! Input a number:
a
No letters! Input a number:
1
Hello!
<========Welcome to the program, please make a choice========>
1: Say Hello
2: Say GoodBye
Please enter a choice:Input a number:
7
Invalid, try again
<========Welcome to the program, please make a choice========>
1: Say Hello
2: Say GoodBye
Please enter a choice:Input a number:
2
GoodBye!

scanf validation sits and waits for another input. Why?

I was working on this sample exercise, and everything works as I would like it to, but there is one behavior I don't understand.
When providing input: if I make consecutive invalid entries everything seems to work great. But if I enter a number different from 1,2,3 in the case of the first question, or 1,2 in the case of the second question, the program just sits there until a new input is given. If another invalid entry is made, it goes back to the error "invalid entry" message, and if an appropriate number is entered, everything moves along fine.
I do not understand why it stops to wait for a second input...anyone?
Thanks guys.
#include <stdio.h>
static int getInt(const char *prompt)
{
int value;
printf("%s",prompt);
while (scanf("%d", &value) !=1)
{
printf("Your entry is invalid.\nGive it another try: %s", prompt);
getchar();
scanf("%d", &value);
}
return value;
}
int main() {
int wood_type, table_size, table_price;
printf("Please enter " );
wood_type = getInt("1 for Pine, 2 for Oak, and 3 for Mahogany: ");
printf("Please enter ");
table_size = getInt("1 for large, 2 for small: ");
printf("\n");
switch (wood_type) {
case 1:
table_price = (table_size == 1)? 135:100;
printf("The cost of for your new table is: $%i", table_price);
break;
case 2:
table_price = (table_size == 1)? 260:225;
printf("The cost of for your new table is: $%i", table_price);
break;
case 3:
table_price = (table_size == 1)? 345:310;
printf("The cost of for your new table is: $%i", table_price);
break;
default:
table_price = 0;
printf("The cost of for your new table is: $%i", table_price);
break;
}
}
You most likely need to flush your input buffer (especially with multiple scanf calls in a function). After scanf, a newline '\n' remains in the input buffer. fflush does NOT do this, so you need to do it manually. A simple do...while loop works. Give it a try:
edit:
static int getInt(const char *prompt)
{
int value;
int c;
while (printf (prompt) && scanf("%d", &value) != 1)
{
do { c = getchar(); } while ( c != '\n' && c != EOF ); // flush input
printf ("Invalid Entry, Try Again...");
}
return value;
}
The blank line you get if you enter nothing is the normal behavior of scanf. It is waiting for input (some input). If you want your routine to immediately prompt again in the case the [Enter] key is pressed, then you need to use another routine to read stdin like (getline or fgets). getline is preferred as it returns the number of characters read (which you can test). You can then use atoi (in <stdlib.h>) to convert the string value to an integer. This will give you the flexibility you need.
example:
int newgetInt (char *prompt)
{
char *line = NULL; /* pointer to use with getline () */
ssize_t read = 0; /* number of characters read */
size_t n = 0; /* numer of chars to read, 0 no limit */
static int num = 0; /* number result */
while (printf ("\n %s ", prompt) && (read = getline (&line, &n, stdin)) != -1)
{
if ((num = atoi (line)))
break;
else
printf ("Invalid Input, Try Again...\n");
}
return num;
}
If some invalid input is entered, it stays in the input buffer.
The invalid input must be extracted before the scanf function is completed.
A better method is to get the whole line of input then work on that line.
First, put that input line into a temporary array using fgets(),
then use sscanf() (safer than scanf because it guards against overflow).
#include <stdio.h>
int main(int argc, const char * argv[]) {
char tempbuff[50];
int result, d , value;
do
{
printf("Give me a number: ");
fgets( tempbuff, sizeof(tempbuff), stdin ); //gets string, puts it into tempbuff via stdin
result = sscanf(tempbuff, "%d", &value); //result of taking buffer scanning it into value
if (result < 1){ //scanf can return 0, # of matched conversions,
//(1 in this case), or EOF.
printf("You didn't type a number!\n");
}
}while (result < 1);
//some code
return 0;
}
Knowledge from: http://www.giannistsakiris.com/2008/02/07/scanf-and-why-you-should-avoid-using-it/

scanf reads previous line instead of getting new one

I have the following code:
#include <stdio.h>
int opt;
scanf("%d",&opt);
while(opt!=0)
{
switch(opt)
{
case 1:func1();
break;
case 2:func2();
break;
case 3:return 0;
}
printf("\n");
scanf("%d",&opt);
}
I want to computer to get from user everytime different digit (1 or 2 or 3) and in every time the computer will run on seperate function. but when I press 2, func2 gets 3 ints and prints chars on the screen in a new line. the computer reads them instead of reading next input (1 or 2 or 3). how can I fix it?
EDIT: The problem rises only after specific inputs (I build a program converts bases).
Input:
2
10
26
1z2
OUTPUT:
ERROR
INPUT:
2
38762
10
UNWANTED OUTPUT:
201222
I'm not sure from where the computer scans the second num it uses to print the last unwanted output.
your second scanf is supposed to block but it isn't because the input buffer is not empty after the first call! This is why it is always returning the previous value and looping infinitely.
Use a combination of fgets and sscanf instead.
Also check this : http://c-faq.com/stdio/scanfprobs.html
If your functions use scanf() inside them to ask for characters or you are using fgets() to read a while line, you might find that scanf() / fgets() does run without user input. This is because the newline character you entered at scanf("%d",&opt); is still there and is used as new input for the next scanf()/fgets(). You have to erase it by issuing
fflush (stdin);
Just prior to call scanf() or fgets()
you may need something like this..
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int opt;
do{
printf("Enter the option\n");
scanf("%d",&opt);
switch(opt){
case 1: func1();
break;
case 2: func2();
break;
case 3:
return 0;
}
}while(opt != 3);
return 0;
}
One problem that is pointed out by hhachem in comment that you are not exiting from your while loop.
You can solve this problem by doing (as you want to exit only after pressing 3):
while(1)
{
switch(1)
{
case 1:func1();
break;
case 2:func2();
break;
case 3: exit(0);
}
printf("\n");
scanf("%d",&opt);
}
Test program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int opt;
scanf("%d",&opt);
while(1)
{
switch(opt)
{
case 1:printf("1");
break;
case 2:printf("2");
break;
case 3:exit(0);
}
printf("\n");
scanf("%d",&opt);
}
return 0;
}
See the output.

how to create an interactive menu in C that moves from one function into another without redrawing the menu

My goal is to produce a program that will take a file as input and "encode" the text within by shifting the characters ahead 3 (so 'a' would be come 'd'). It should produce an output file with the encoded text. The menu is to take user input and execute the function that is assigned to the number selected.
I'm early on at creating this program, but running short on time and am struggling with how to structure it. Currently, I have the menu displaying, but when a sub function is called, it displays but then the menu overwrites it and I can't figure out why. Any help would be appreciated. Here is the code I have so far...
#include <stdio.h>
#define INPUT_FILE 1 //define statements
#define OUTPUT_FILE 2
#define NUM_TO_SHIFT 3
#define ENCODE 4
#define QUIT 0
int menu(); //function prototypes
int input();
int output();
int shift();
int encode();
void quit();
int main()
{
int choice; // main variables
char user_filename[100];
choice = menu(); // get user's first selection
while(choice != QUIT) //execute so long as choice is not equal to QUIT
{
switch(choice)
{
case INPUT_FILE:
printf("Enter the filename of the file to encode:\n");
printf("(hit the Enter key when done)\n");
gets(user_filename);
break;
case OUTPUT_FILE: output();
break;
case NUM_TO_SHIFT: shift();
break;
case ENCODE: encode();
break;
case QUIT: quit();
break;
default: printf("Oops! An invalid choice slipped through. ");
printf("Please try again.\n");
}
choice = menu(); /* get user's subsequent selections */
}
printf("Bye bye!\n");
return 0;
}
int menu(void)
{
int option;
printf("Text Encoder Service\n\n");
printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
printf("2.\tEnter name of output file (currently not set)\n");
printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
printf("4.\tEncode the text\n\n");
printf("0.\tQuit\n\n");
printf("Make your selection: ");
while( (scanf(" %d", &option) != 1) /* non-numeric input */
|| (option < 0) /* number too small */
|| (option > 4)) /* number too large */
{
fflush(stdin); /* clear bad data from buffer */
printf("That selection isn't valid. Please try again.\n\n");
printf("Your choice? ");
}
return option;
}
int input()
{
}
int output()
{
return 2;
}
int shift()
{
return 3;
}
int encode()
{
return 4;
}
void quit()
{
printf("Quiting...Bye!");
exit(0);
}
You shouldn't use gets(user_filename) to get the file name since gets() reads up to a \n and stops reading. Your scanf for the menu option does not read the \n at the end of the line when the user types in the menu option. Essentially, you're making gets read a string without words in it. The line you want to read is actually the next line. Using scanf instead of gets will fix it.
Otherwise, your program is working as expected - it's just that your functions don't do anything yet that your menu is "overwriting" the submenus. See http://ideone.com/F2pEs for an implementation with scanf instead of gets.
use getchar(); soon after the gets(user_filename); it will wait to get the character
gets(user_filename);
getchar();
break;
As in this question which Stackoverflow has highlighted as a match, you need to clear out the buffer to remove the newline that's waiting in there.
Add this code after reading a valid menu option:
do
{
c = getchar();
} while (c != EOF && c != '\n');
where c is a char declared up by option. This loops over remaining characters in the input stream until EOF (End Of File) or a newline character is reached, meaning they don't affect your call to gets(). Note that gets() is considered insecure because it doesn't protect against buffer overflow, a user could easily enter more than 100 characters (inc. newline) and start writing into memory that shouldn't be touched by their input. You would do well to lookup the secure equivalent when you see compiler warnings around function calls like this, typically they take a second parameter which is the maximum size of the buffer being read into.
Well, this answer is way late but having come across it, I can't help but write something.
Let's get straight to it. You will have an array of menus, with the array elements being the options you want in your menu. Then while in a truthy condition, loop through the elements of the array, selecting the option you want.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//function prototypes
int input();
int output();
int shift();
int encode();
void quit();
int main(){
int menus_on = 1;
const char *menus[5] = {"Input","Output","Shift","Encode","Quit"};
while(menus_on){
int menu,*temp;
for(int i =0;i<6;i++){
printf("%d: %s\n",i,menus[i]);
}
printf("Select menu\n");
scanf("%d",temp);
menu = *temp;
printf("Selected menu::%d\n",menu);
switch(menu){
case 0:
input();
break;
case 1:
output();
break;
case 2:
shift();
break;
case 3:
encode();
break;
case 4:
quit();
break;
default:
printf("Invalid selection\n");
break;
}
}
return 0;
}
int input() {
return 0;
}
int encode () {
return 0;
}

Resources