Correct program flow

Hello friends.

Like a total newbie I am trying to understand C and more importantly program flow.

So in order to understand the workings of some loops and if statements I made a simple chunk of code, just to get my hands dirty and understand things better.

My program compiles but doesn't exits the way I want.

The progress should be [Menu Sel] -> [Calculation] -> [Exit].

But when I compile and run the program i remain stuck in an endless loop. Only selection [5] gives me the correct flow... What am I doing wrong?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* Simplest of all calculators project */

#include <stdio.h>

int get_menu(choice);

float add(float x, float y);
float sub(float x, float y);
float mult(float x, float y);
float div(float x, float y);

int main (void)
{
    float x;
    float y;
    float z;


    int choice=get_menu(choice); /* this should get number ranging 1-5 representing user's choice and perform the correct calculation */

    while (choice !=5)   /* if this is TRUE then goes to the first if ... correct? */
                         /* if FALSE this does not execute at all and jumps to line 70 ...correct? */
    {
    if (choice == 1)     /* if this is TRUE executes the statements and when the block "{...}" finishes goes to line 70: printf() ... correct? */
                         /* if  FALSE goes to next if */
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=add(x,y);
        printf("%f plus %f equals %f", x, y, z);
    }

    if (choice == 2)     /* if this is TRUE executes the statements and when the block "{...}" finishes goes to line 70: printf() ... correct? */
                         /* if  FALSE goes to next if */
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=sub(x,y);
        printf("%f minus %f equals %f", x, y, z);
    }

    if (choice ==3)     /* if this is TRUE executes the statements and when the block "{...}" finishes goes to line 70: printf() ... correct? */
                        /* if  FALSE goes to next if */
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=mult(x,y);
        printf("%f times %f equals %f", x, y, z);
    }

    if (choice == 4)    /* if this is TRUE executes the statements and when the block "{...}" finishes goes to line 70: printf() ... correct? */
                         /* if  FALSE where does program execution go? */
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=div(x,y);
        printf("%f divided by %f equals %f", x, y, z);
    }

    }


printf("\nExiting...");

    return 0;

}

/*Functions used in my program*/

int get_menu(void)
{
    int sel=0;
    do
    {
    puts("1: +");
    puts("2: -");
    puts("3: *");
    puts("4: /");
    puts("5: EXIT");
    puts("select :");
    scanf("%d", &sel);
    }
    while (sel<1 || sel>5); /* while sel<1 || sel>5 == 0  FALSE this goes to return statement, otherwise goes back to the do keyword...correct? */

    return sel;
}

float add(float x, float y)
{
    float z;
    z=x+y;

    return z;
}

float sub(float x, float y)
{
    float z;

    z=x-y;

    return z;
}

float mult(float x, float y)
{
    float z;

    z=x*y;

    return z;
}

float div(float x, float y)
{
    float z;

    z=x/y;

    return z;
}
Last edited on
Take a look at your code from lines 24 - 65. At what point does 'choice' become five so that the while loop may terminate? The reason you experience the "infinite loop" is because, unless 'choice' is initially equal to five, you'll enter the while loop on line 21 and never exit it because 'choice' never changes from not-five to five.

Additionally, your assumptions about code flow concerning the if-branches is incorrect. Take a look here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {

	int x = 10;

	if (x == 10) {
		//do something
	}

	if (x == 100) {
		//do something else
	}

	if (x == 1000) {
		//do something else again
	}

	return 0;
}


These three if-branches are not dependent on each other. By your logic, once one of the if-branches' conditions are satisfied, the other if-branches are ignored and program execution jumps to the "return 0". This is not true. Regardless of whether or not any of the three if-branches' conditions are satisfied or not, all three expressions will be evaluated. Your assumption would only be correct if they were dependent on each other, which is achieved using if-elseif-else:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main() {

	int x = 10;

	if (x == 10) {
		//do something
	}

	else if (x == 100) {
		//do something else
	}

	else if (x == 1000) {
		//do something else again
	}

	else {
		//x was not 10, 100 or 1000
		//none of the previous conditions were satisfied
	}

	return 0;
}
Last edited on
Hello JackTrades,

You could add an additional choice = get_menu(choice); just before the closing brace of the while loop so the while condition will work with your next menu choice.

Hope that helps,

Andy
Since you always want the loop to execute at least once, it's a good candidate for a do-while loop:
1
2
3
4
5
6
7
8
do {
    choice = get_menu();
    if (choice == 1) {
        ... 
    else if (choice == 2) {
        ...
    }
while (choice != 5);


Also, once you're comfortable with the basic control flow statements, take a look at the switch statement. It's more appropriate for this case because it expresses the idea that you want to do one of several things based on the value of choice:
1
2
3
4
5
6
7
8
9
10
11
12
13
do {
    choice = get_menu();
    switch(choice) {
    case 1:
         ...
         break;
    case 2:
        ...
        break;
    ...
    }

while (choice != 5);
Thank you all!!!
Your explanations are invaluable!

Certain things mentioned in here, are not explained in such a clear way in my text book.

@ Andy thanks in advance, you replied me without asking.

@xismn Thank you again, this makes it more much clearer...

So please correct me if I am wrong now :

In an UNORTHODOX way of correcting things I would have to make:

 
choice=0;


and that would make program flow control work... yes?
I am only stating this because like you correctly stated I am merely trying to understand how things are read by the computer and see if I can "guess" where program execution goes when I read it. And I need to understand the while loop a little bit better as it seems.... so I would like, if at all possible, preserve the while loop to execute my program. (That would mean that I really understand how things are read). So where / how should I assign choice another value to break the infinite while loop?

But if I were to clean things up in a PROPER way ... i would write :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* Simplest of all calculators project */

#include <stdio.h>

int get_menu(choice);

float add(float x, float y);
float sub(float x, float y);
float mult(float x, float y);
float div(float x, float y);

int main (void)
{
    float x;
    float y;
    float z;


    int choice=get_menu(choice); 

    if (choice == 1)     
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=add(x,y);
        printf("%f plus %f equals %f", x, y, z);
    }

    else if (choice == 2)     
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=sub(x,y);
        printf("%f minus %f equals %f", x, y, z);
    }

    else if (choice ==3)    
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=mult(x,y);
        printf("%f times %f equals %f", x, y, z);
    }

    else if (choice == 4)    
    {
        printf("\nEnter the first number : ");
        scanf("%f", &x);
        printf("\nEnter the second number : ");
        scanf("%f", &y);
        z=div(x,y);
        printf("%f divided by %f equals %f", x, y, z);
    }
    
    else printf("\nExiting...");




    return 0;

}

/*Functions used in my program*/

int get_menu(void)
{
    int sel=0;
    do
    {
    puts("1: +");
    puts("2: -");
    puts("3: *");
    puts("4: /");
    puts("5: EXIT");
    puts("select :");
    scanf("%d", &sel);
    }
    while (sel<1 || sel>5); /* while sel<1 || sel>5 == 0  FALSE this goes to return statement, otherwise goes back to the do keyword */

    return sel;
}

float add(float x, float y)
{
    float z;
    z=x+y;

    return z;
}

float sub(float x, float y)
{
    float z;

    z=x-y;

    return z;
}

float mult(float x, float y)
{
    float z;

    z=x*y;

    return z;
}

float div(float x, float y)
{
    float z;

    z=x/y;

    return z;
}


Did I get it?

Last edited on
Line 5: Your forward declaration says get_menu() takes an argument. It should NOT take an argument.

Line 79: Your implementation of get_menu() says it does not take an argument.

To fit this into your original design, you'd do:

1
2
3
4
5
6
7
8
9
int choice = get_menu()
while (choice != 5) {
    if (choice == 1) {
        ...
    } else if (choice == 4) {
        ...
    }
    choice = get_menu();    // Add this line
}
Thank you dhayden, and everyone!
Hello JackTrades,

Weather you define int choice{ 0 }; or int choice = get_menu(); it works the same way. It defines the variable and initializes it.

Referring back to your OP the comments on lines 19 – 22 and for each of the if statement s are mostly correct. Except when the block of an if statement finishes it does not jump to line 70, but it would actually jump to line 68, the end of the while loop where the while loop would start over. It should be going to line 67 which should say choice = get_menu(), but since it does not that is why you have an endless loop because “choice” never changes. So any starting value of “choice” other than “5” results in an endless loop.

As the program begins you first get a menu choice when you call “get_menu();” on line 19. So when you enter the while loop choice has a value to work with. Based on the value of “choice” one of the if statements will execute and when finished the flow will jump to the end of the while loop and start over. At this point “choice” has the same value that you started with before you entered the while loop, so the same if statement will be repeated.

Only when “choice” is set equal to five does the while loop condition become false and the loop ends thus jumping to line 70.

I would stay with your original program post and all you need to add to it is on line 67 put choice = get_menu(); and the program and flow will work correctly.

Hope that helps,

Andy
Topic archived. No new replies allowed.