Break statement doesn't work in loop (gcc) - c

I'm sorta having a problem with my code. The function will not terminate and it keeps looping forever. I'm kinda new when it comes to compiling C in Linux (I came from Dev-C++..)
Here's the code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
struct student{
char lname[20];
char fname[20];
int idnum[8];
int year;
};
struct course{
char cname[4];
struct student stud[MAX];
};
int main()
{
struct course c[0];
userSelect(&c);
return 0;
}
int userSelect(struct course *p_course)
{
int z=0, x;
printf("1 - Create course\n2 - Edit course\n3 - Add student(s)\n4 - Edit student data\n5 - Delete\n6 - Quit");
scanf("\n%d", &x);
while(z==0){
switch(x){
ccase 1: userCreateCourse(p_course);
break;
//case 2: userEditCourse(&c);
//break;
//case 3: userCreateStudents(&c);
//break;
//case 4: userEditStudents(&c);
//break;
case 6: printf("bye");
z++;
break;
default: printf("Invalid input");
break;
}
}
}
int userCreateCourse(struct course *p_course)
{
int *cnum=0, i;
cnum=(int *)malloc(sizeof(int));
cnum++;
printf("Enter course (ex: BSCS): ");
fgets(p_course[*cnum-1].cname, sizeof(p_course[*cnum-1]), stdin);
puts(p_course[*cnum-1].cname);
}
If I select 1, this is the output:
1 - Create course
2 - Edit course
3 - Add student(s)
4 - Edit student data
5 - Delete
6 - Quit1
Enter course (ex: BSCS): H��4k
Enter course (ex: BSCS): AAAA
AAAA
Enter course (ex: BSCS): AAAA
AAAA
Enter course (ex: BSCS):
and it keeps doing that endlessly until I close the terminal. I really don't know what's wrong.. Someone help :(

You need to read x inside the loop. What happens is that x remains the same value that you inputted the very first time. So case 1: is always executed.
You can use a do-while loop like:
do{
printf("1 - Create course\n2 - Edit course\n3 - Add student(s)\n4 - Edit student data\n5 - Delete\n6 - Quit\n");
scanf("\n%d", &x);
switch(x){
case 1: userCreateCourse(p_course);break;
//case 2: userEditCourse(&c);break;
//case 3: userCreateStudents(&c);break;
//case 4: userEditStudents(&c);break;
case 6: printf("bye");z++;break;
default: printf("Invalid input");break;
}
} while( z==0);
But remember there are a number of issues with the scanf() + fgets() approach.
The scanf() that reads x will leave a newline in the input buffer and fgets() will return immediately without reading input (due to \n).
You can handle this by discarding any input chars left in the input with:
.
int c;
while((c=getchar()) != '\n' && c!=EOF);
(just before fgets() call).
If you input non-numbers input for x, then you'll end up with an infinite loop since scanf() doesn't ignore invalid input(s). You should check the scanf() return value and discard (using getchar() as above) all input chars if it failed.

You should ask for a new x inside the while loop if you want to be able to input a new one. Otherwise the first x will be used time and again since you never exit the loop.

Well it does breaks but it comes back again in your loop since z == 0 remains true. It breaks out of your switch case, not out of your loop. At the end of the switch you should change the value of z for something different than 0 like :
while(z==0){
switch(x){
case 1: userCreateCourse(p_course);break;
//case 2: userEditCourse(&c);break;
//case 3: userCreateStudents(&c);break;
//case 4: userEditStudents(&c);break;
case 6: printf("bye");z++;break;
default: printf("Invalid input");break;
}
z = 1;
}
It'd be best for you to use a boolean like
boolean done = false;
while(!done){
switch(smth){
// do smth
}
done = true
}

Related

Can't get my code to continue when I enter 'y', it just exits out

It's my first time using switch case statements in my code so I could just be using it wrong in this scenario. I am attempting to make a simple dice roller that lets you roll the dice again.
My code for the dice roll works, but at the end when it asks you if you would like to roll again (y/n)
When I enter y
it just exits out.
`
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define WON 0
#define LOSE 1
int rollDice();
int playGame();
int rollAgain();
int rollDice()
{
return rand() % 6+ 1;
}
int playGame()
{
srand(time(NULL));
int dice_1 = 0;
int dice_2 = 0;
int sum = 0;
int result;
printf("--------------\n");
printf("- HOW TO WIN -\n");
printf("--------------\n");
printf("Your dice roll must equal 7 or 11 or else you lose.\n");
printf("\n");
printf("Want to test your luck? ");
printf("Press ENTER to roll the die\n");
fgetc(stdin);
dice_1 = rollDice();
dice_2 = rollDice();
sum = dice_1 + dice_2;
printf("Dice 1:%2d\nDice 2:%2d\nSum:%2d\n", dice_1, dice_2, sum);
switch ( sum )
{
case 7:
case 11:
result = WON;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 8:
case 9:
case 10:
case 12:
result = LOSE;
break;
}
return result;
}
int rollAgain()
{
srand(time(NULL));
int dice_1 = 0;
int dice_2 = 0;
int sum = 0;
int result;
printf("Press ENTER to roll the die\n");
fgetc(stdin);
dice_1 = rollDice();
dice_2 = rollDice();
sum = dice_1 + dice_2;
printf("Dice 1:%2d\nDice 2:%2d\nSum:%2d\n", dice_1, dice_2, sum);
switch ( sum )
{
case 7:
case 11:
result = WON;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 8:
case 9:
case 10:
case 12:
result = LOSE;
break;
}
}
int main()
{
char answer;
int result = playGame();
switch ( result )
{
case WON:
printf("You won the game.\n");
printf("Do you wish to play again? (y/n)");
scanf("%c", &answer);
if(answer == 'y' || answer == 'Y');
{
int rollAgain();
}
break;
case LOSE:
printf("You lost the game.\n");
printf("Do you wish to play again?");
scanf("%c", &answer);
if(answer == 'y' || answer == 'Y');
{
int rollAgain();
}
break;
}
return 0;
}
`
How do I get my code to 'roll the dice again'?
Why isn't the if statement working?
is it because I am using a scanf instead of something like fgets?
Like how I used the fgetc for the enter ?
The following code contains two errors:
if(answer == 'y' || answer == 'Y');
{
int rollAgain();
}
The line
if(answer == 'y' || answer == 'Y');
is wrong. The ; at the end of the line is an empty statement, so you are effectively telling the program to "do nothing" when the if condition is true. If you instead want the code block after the if statement to be associated with the if statement, you must remove the empty statement, by removing the ; in the line quoted above.
My gcc compiler warns me of this, when I enable all warnings. You may want to read this question: Why should I always enable compiler warnings?
Also, the line
int rollAgain();
is wrong. That line is a function declaration. If you want it to be a function call instead, you must remove the int from that line.
After fixing these two bugs, which both occur in two places in your program, the function rollAgain is now successfully being called:
--------------
- HOW TO WIN -
--------------
Your dice roll must equal 7 or 11 or else you lose.
Want to test your luck? Press ENTER to roll the die
Dice 1: 4
Dice 2: 6
Sum:10
You lost the game.
Do you wish to play again?y
Press ENTER to roll the die
Dice 1: 6
Dice 2: 5
Sum:11
However, it does not make much sense that you only allow the user to repeat once. It also does not make sense that you inform the user whether they won the first round, but not whether they won the second round.
It also does not make much sense that you have two functions playGame and rollAgain that are nearly identical. The main difference between these functions seems to be that the first function prints additional instructions to the user, which are only intended to be printed before the first round. Therefore, it would make sense to combine these two functions into one function, so that you don't have any unnecessary code duplication. The printing of the additional instructions could be handled in another function, which is called in main at the start of the program.
Another issue is that the line
scanf("%c", &answer);
in the function main will consume the y character from the input stream, but leave the newline character on the input stream. This means that when the function rollAgain is called, it will prompt the user like this:
Press ENTER to roll the die
However, afterwards, the line
fgetc(stdin);
will not wait for the user to press ENTER, but will instead immediately read the \n newline character that was left over by the function main.
In order to prevent such leftover characters, I recommend that you always read exactly one line of input at once, including the newline character, for example by using the function fgets instead of scanf or fgetc.
Another issue in your program is that you are calling srand several times in your program, which will cause the same sequence of random numbers to be generated if srand is called in the same second. See the following question for further information: srand() — why call it only once?
Here is a fixed version of your code, in which all the issues mentioned above have been addressed and some minor improvements have been added:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
enum result
{
RESULT_WON = 0,
RESULT_LOST = 1
};
int rollDice();
enum result playGame();
int rollDice( void )
{
return rand() % 6 + 1;
}
void printInstructions( void )
{
printf("--------------\n");
printf("- HOW TO WIN -\n");
printf("--------------\n");
printf("Your dice roll must equal 7 or 11 or else you lose.\n");
printf("\n");
printf("Want to test your luck? ");
}
enum result playGame( void )
{
int dice_1;
int dice_2;
int sum;
int c;
printf("Press ENTER to roll the die\n");
//read characters from input stream until newline character
//is found
do
{
c = getchar();
} while ( c != EOF && c != '\n' );
dice_1 = rollDice();
dice_2 = rollDice();
sum = dice_1 + dice_2;
printf( "Dice 1:%2d\nDice 2:%2d\nSum:%2d\n", dice_1, dice_2, sum );
switch ( sum )
{
case 7:
case 11:
return RESULT_WON;
default:
return RESULT_LOST;
}
}
int main( void )
{
char line[200];
//seed the random number generator only once, at the
//start of the program
srand(time(NULL));
printInstructions();
do
{
switch ( playGame() )
{
case RESULT_WON:
printf( "You won the game.\n" );
break;
case RESULT_LOST:
printf("You lost the game.\n");
break;
}
printf( "Do you wish to play again? (y/n)" );
//read exactly one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
fprintf( stderr, "Input error!\n" );
exit( EXIT_FAILURE );
}
} while ( toupper( (unsigned char)line[0] ) == 'Y' );
return EXIT_SUCCESS;
}
This program has the following behavior:
--------------
- HOW TO WIN -
--------------
Your dice roll must equal 7 or 11 or else you lose.
Want to test your luck? Press ENTER to roll the die
Dice 1: 3
Dice 2: 6
Sum: 9
You lost the game.
Do you wish to play again? (y/n)y
Press ENTER to roll the die
Dice 1: 4
Dice 2: 1
Sum: 5
You lost the game.
Do you wish to play again? (y/n)y
Press ENTER to roll the die
Dice 1: 3
Dice 2: 4
Sum: 7
You won the game.
Do you wish to play again? (y/n)n

Exit case in switch in C

I am trying this code with exit case, the exit case doesn't work it still asks me for the two numbers and then it exits. I have provided the output. What is the alternative to the switch case that I can use for menu driven programs?
Sample input/output:
::::::Menu:::::
1. Addition:
2. Subtraction
3. Multiplication
4. Division
5. Mod
6. Exit
Enter your choice:6
Enter the values of a and b:3 4
#include<stdio.h>
#include<stdlib.h>
int main(){
int a,b,c;
int no;
do{
printf("\n::::::Menu:::::\n");
printf(" 1. Addition:\n 2. Subtraction \n 3. Multiplication \n 4. Division \n 5. Mod \n 6. Exit");
printf("\nEnter your choice:");
scanf("%d",&no);
printf("\nEnter the values of a and b:");
scanf("%d%d",&a,&b);
switch(no){
case 1:
c = a + b;
printf("\nAddition is:%d",c);
break;
case 2:
c = a - b;
printf("\nSubtraction is:%d",c);
break;
case 3:
c = a * b;
printf("\nMultiplication is:%d",c);
break;
case 4:
c = a / b;
printf("\nDivision is:%f",c);
break;
case 5:
c = a % b;
printf("\nMod is:%d",c);
break;
case 6:
exit(1);
default:
printf("\nInvalid choice\n");
break;
}
}while(no!=6);
return 0;
}
Your program asks for two numbers because you are checking for the exit code after the second scanf statement. If you wish the program to exit when 6 is entered, then you have to add an if statement in between the first and second scanf. You should additionally removed the exit case from your switch statement. Below is an example:
printf("\nEnter your choice:");
scanf("%d",&no);
if (no == 6)
exit(0);
printf("\nEnter the values of a and b:");
scanf("%d%d",&a,&b);
You're reading the user's menu option, then asking for the next two numbers before you get to the switch statement, so of course it will always ask for those two numbers.
You need to either check specifically for 6 right after reading the menu input, or you need to move the second prompts to only where they're needed, i.e. inside each case.
It keeps asking for the two numbers because the switch statement is positioned right AFTER you ask for the user input. I restructured your code, this should work:
#include<stdio.h>
#include<stdlib.h>
int main(){
int a,b,c;
int no;
while(1){
printf("\n::::::Menu:::::\n");
printf(" 1. Addition:\n 2. Subtraction \n 3. Multiplication \n 4. Division \n 5. Mod \n 6. Exit");
printf("\nEnter your choice:");
scanf("%d",&no);
if (no == 6)
break;
printf("\nEnter the values of a and b:");
scanf("%d%d",&a,&b);
switch(no){
case 1:
c = a + b;
printf("\nAddition is:%d",c);
break;
case 2:
c = a - b;
printf("\nSubtraction is:%d",c);
break;
case 3:
c = a * b;
printf("\nMultiplication is:%d",c);
break;
case 4:
c = a / b;
printf("\nDivision is:%f",c);
break;
case 5:
c = a % b;
printf("\nMod is:%d",c);
break;
default:
printf("\nInvalid choice\n");
break;
}
}
return 0;
}
Note how I changed the do-while to a while-true and explicitly check for no == 6 PRIOR to asking for user input.
The statements in C are meant to be executed sequentially unless you disrupt the normal flow of action using jumps. In your case
printf("\nEnter your choice:");
scanf("%d",&no);
printf("\nEnter the values of a and b:");
scanf("%d%d",&a,&b);
// Only now does the switch start.
You ask for the choice first and then for the two numbers. That is why you always end up in entering the two values. One way is to take the exit out of the switch-case which perhaps is the simplest solution I guess. Something like
printf("\nEnter your choice:");
scanf("%d",&no);
if ( 6 == no )
exit(1);
What is the alternative to the switch case that I can use for menu
driven programs
Well, switch-case is exactly made for that. Why think of an alternative?
#include<stdlib.h>
#include<conio.h>
#include<stdio.h>
int main()
{
char ch;
while(1)
{
printf("l.print l c.print c q. exit \n");
printf("enter choice ");
scanf("%c",&ch);
switch(ch)
{
case 'l':
printf("You have typed l \n");
break;
case 'c':
printf("yoh have typed c \n");
break;
case 'q':
exit(0);
}
}
return 0;
}

Switch in C with while loop

I am new to C programming. I wrote a simple switch case but it is not executing as expected . Can some one tell me what is wrong here??
#include <stdio.h>
int main() {
int i;
char yes;
bool flag = true;
while(flag) {
printf("Enter the value");
scanf("%d",&i);
switch(i) {
case 1:
printf("Hi");
break;
case 2:
printf("Hello");
break;
}
printf("Enter Y or N to continue");
scanf("%c",&yes);
if (yes == 'N') {
flag = false;
}
}
return 0;
}
The result I am expecting is:
Enter the Value
1
Hi
Enter Y or N to continue
Y
Enter the Value
2
Hello
Enter Y or N to continue
N
But the result I am getting is :
Enter the value 1
HiEnter Y or N to continueEnter the value N
HiEnter Y or N to continue
When you hit Enter after typing in the first number, scanf read all numeric characters from the input stream except the newline character produced by that Enter hit. The newline character is not a part of the number. It is left in the input stream, unread, waiting for someone else to read it.
The next scanf("%c",&yes); discovered that pending newline charcter and it read it without waiting. The %c format specifier does not skip whitespace in the input, it just reads the first character it sees.
Replace your scanf with
scanf(" %c",&yes);
to make it skip whitespace. That way it will ignore that pending newline and actually wait for you to enter something.
In all your printf you need to add \n at the end.
For example on usage, see here: printf
This should work for you:
(You forgot all '\n' in your printf statements and add a space in your char scanf statements)
#include <stdio.h>
int main() {
int i;
char yes;
int flag = 1;
while(flag) {
printf("Enter the value\n");
scanf("%d",&i);
switch(i){
case 1:
printf("Hi\n");
break;
case 2:
printf("Hello\n");
break;
}
printf("Enter Y or N to continue\n");
scanf(" %c", &yes);
if (yes == 'N')
flag = 0;
}
return 0;
}
Output:
Enter the Value
1
Hi
Enter Y or N to continue
Y
Enter the Value
2
Hello
Enter Y or N to continue
N
It's not a problem with the switch statement. It's a problem with your output - there aren't line breaks ('\n'). For example, instead of printf("Hi"); you might want to have printf("Hi\n");, which adds a line space at the end.

do while loop in C

I am implementing a polynomial using array. This is the Problem Statement:
Write a menu-driven program to represent Polynomials as a data structure using arrays. and write functions to add, subtract and multiply two polynomials; multiply a polynomial with a constant, find whether a polynomial is a "zero- polynomial, return the degree of the polynomial. Assume that a new polynomial is created after each operation. How would you input and output polynomials?
I have created the input and output functions. But my do while loop is running twice.. Help me finding out why.
The do-while loop
do{
print_menu();
scanf("%c",&ch);
printf("\nch = %c\n",ch);
switch(ch){
case '1':
create_poly(poly,termpool,&next_poly);
break;
case '2':
print_poly(poly,termpool,&next_poly);
break;
case 'q':
break;
default:
printf("Invalid choice.");
}
}while(ch != 'q');
return 0;
}
The print_menu() function
void print_menu()
{
printf("\n1. Create a new polynomial.");
printf("\n2. Print polynomial.");
printf("\nq. Exit");
printf("\nEnter Choice:");
}
The create_poly() function
void create_poly(int poly[][2], int termpool[][2], int *next_poly)
{
int beg = poly[*next_poly][0];
int end, size, i, j;
printf("Enter size of the polynomial:");
scanf("%d",&size);
poly[*next_poly][1] = beg + size - 1;
end = poly[*next_poly][1];
printf("Enter terms of the polynomial(coeff then exponent):\n");
for(i=beg; i<=end; i++){
for(j=0; j<2; j++){
scanf("%d ",&termpool[i][j]);
}
}
poly[++(*next_poly)][0] = end + 1;
}
The print_poly() function
void print_poly(int poly[][2],int termpool[][2],int *next_poly)
{
int pos,beg,end;
int i;
printf("Enter position of the polynomial:");
scanf("%d",&pos);
if(pos-1 > *next_poly){
printf("Invalid position.");
return;
}
beg = poly[pos-1][0];
end = poly[pos-1][1];
for(i=beg; i<=end; i++){
printf(" %dx^%d +",termpool[i][0],termpool[i][1]);
}
printf("\b = 0");
}
Here is a sample output:
1. Create a new polynomial.
2. Print polynomial.
q. Exit
Enter Choice:1
ch = 1
Enter size of the polynomial:2
Enter terms of the polynomial(coeff then exponent):
2 4
6 7
1. Create a new polynomial.
2. Print polynomial.
q. Exit
Enter Choice:
ch =
Invalid choice.
1. Create a new polynomial.
2. Print polynomial.
q. Exit
Enter Choice:q
ch = q
Tried flushing the stdin… The problem stays. Printing the value of ch in each step, I think it is a whitespace. Where does the white space comes?
The answer to abnormal behavior of scanf answers this question also.
If you test the next code you will note the same problem
int main() {
char c;
do {
scanf_s("%c", &c);
if (c != 'q')
printf("test scanf() function\n");
} while (c);
}
the scanf() function works when the enter key is pressed, but this insert another char in the buffer input, the char of new line '\n', it is taken again by scanf() because the loop block. Try to change the previous code by this code:`
do {
scanf_s("%c", &c); // or c = getchar();
switch (c){
case '\n':
break;
default:
printf("test scanf() function\n");
}
} while (c);`
and will work fine. In your code only add a new case in the switch block:
switch(ch) {
case '1':
create_poly(poly,termpool,&next_poly);
break;
case '2':
print_poly(poly,termpool,&next_poly);
break;
case '\n':
break;
case 'q':
break;
default:
printf("Invalid choice.");
}
sorry, English is not my native language
There's an extra character waiting to be consumed after you make your initial choice, that's why the loop is executing twice.
See this question on the comp.lang.c FAQ

getchar() function not reading the correct value

When I enter 0 the program ends. But there is getchar() in if statement and it doesn't work, can you help me?
On case 0 I want it to get char from user. If 'N' or 'n' is entered the program will end but if not the program will start over again. (from sec1).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
sec1:
printf("Select a number between 4 and 0: ");
scanf("%d[\n]", &n);
switch(n)
{
case 0:
puts("Are you sure?");
puts("Yes(Y) or No(N)");
if(getchar() == 'N') goto sec1;
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
puts("Only numbers between 4 and 1 are accepted!");
goto sec1;
break;
}
system("pause");
return 0;
}
working one
int main()
{
int n, c;
sec1:
printf("Select a number between 4 and 0: ");
scanf("%d/n", &n);
switch(n)
{
case 0:
puts("Are you sure?");
puts("Yes(Y) or No(N)");
fflush(stdin);
if (getchar() == 'N') goto sec1;
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
puts("Only numbers between 4 and 1 are accepted!");
goto sec1;
break;
}
system("pause");
return 0;
}
Change
scanf("%d[\n]",&n);
to
scanf("%d\n",&n);
The reason that your original code does not work is because scanf wants to read an integer, a "[", a "\n" and a "]". So when you input an integer followed by a "\n", scanf only takes the integer(because it expects to see a "["). Then the getchar will simply take the remaining "\n". That's why your getchar() seems not working.
Hope it is helpful to you!
Probably you have some symbols in the input buffer when you are reading "N" or "n". You need to flush an input buffer before new reading. See this question for details.
Briefly just write:
while (getchar() != '\n') {}
right after scanf(...).
I guess this is the terminal which is in cooked mode, thereby only feeding typed characters to the program when the user completes a line by hitting return. You can test it by feeding it input from a pipe instead of interactively from the terminal.

Resources