which is the best practice (if any)

Hello again,

Trying to understand program execution I first compiled the following :
(as found in my text book)

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
  #include <stdio.h>

#define MAX_GRADE 100
#define STUDENTS 10

int grades[STUDENTS];

int idx;
int total=0;

int main()
{
    for (idx=0; idx<STUDENTS; idx++)
    {
        printf("\nEnter person's %d grade : ", idx+1);
        scanf("%d", &grades[idx]);

        while (grades[idx]>MAX_GRADE)
        {
        printf("\nThe highest grade possible is 100");
        printf("\nEnter correct grade : ");
        scanf("%d", &grades[idx]);
        }

    total += grades[idx];
    }
    printf("\n\nThe average grade is %d\n", (total/STUDENTS));
    return 0;
}


then I canged it to the following just to see if my logic was correct...

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
#include <stdio.h>

#define MAX_GRADE 100
#define STUDENTS 10

int grades[STUDENTS];

int idx;
int total=0;

int main()
{
    for (idx=0; idx<STUDENTS; idx++)
    {
        printf("\nEnter person's %d grade : ", idx+1);
        scanf("%d", &grades[idx]);

        if (grades[idx]>MAX_GRADE)
        {
        printf("\nThe highest grade possible is 100");
        printf("\nEnter correct grade : ");
        scanf("%d", &grades[idx]);
        }
        else
    total += grades[idx];
    }
    printf("\n\nThe average grade is %d\n", (total/STUDENTS));
    return 0;
}


The program compiles and the results are equal, or so it seems.

So if the result is the same, is one technique better than the other? and why?

First one, because the while is put there to request a new value every-time you enter something invalid, while yours will only work for one invalid value. Try inputting 1000 two times in a row with your code and see what I'm talking about.
The book is correct. The while loop is to ensure even if the user enter invalid score repeatedly the program can still handle it. The if-else actually makes things worse.

First example : Try to enter 101, then later you change it to 98 when you see an error. You see if the total score adds up.

And show an example so that we know whether it is correct or not correct.
You are both correct, my assumption (no surprise here) was invalid.
Main flaw was that - while clearly I have to study more - my test was not performed well...I placed an incorect value JUST ONCE and using grade values 5 & 10 alternatively.

Thank you very much.
Some other points:

Don't use #define for constants, make them const variables instead, and declare them inside main:

1
2
const unsigned short MaxGrade = 100;
const unsigned short NumStudents = 10;


Don't use global variables, they are evil :+)

If you are going to use scanf, make use of it's return value to see if it worked. There are other safer version of scanf:

http://en.cppreference.com/w/c/io/fscanf

Always use braces even if there is only 1 statement, as in line 25

Another question rises in my mind :

Trying to understand how a computer reads/ executes all those instryctions :

In the second erroneous listing, the user inputs a value.ok?

Then the value from line 16 gets evaluated via the if statement on line18. If line 18 is TRUE then executes the block { } lines 19-23 and then jumps to line 13 untill the for condition gets its full circle and arrives to idx=10. Correct?

If line 18 is FALSE then the for loop continues untill idx= 10 at which point execution jumps to line 24...

THIS OF COURSE IS MY LOGIC, which is clearly faulty...can you tell me where i go wrong?

(another question : why idx<STUDENTS and not idx<=STUDENTS ? After all idx arrives at 10 and then stops...9 would be the correct statement since 9<STUDENTS while 10<STUDENTS is not a correct statement)
while 10<STUDENTS is not a correct statement

It should be time the for loop terminates as there are no more array elements to spare.
wouldn't do while loop be better ????
If line 18 is FALSE then the for loop continues untill idx= 10 at which point execution jumps to line 24...
No, when idx==10, execution jumps to the statement after the for loop, which is line 27. It might help to view the code with indentation that reflects the actual block structure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int
main()
{
    for (idx = 0; idx < STUDENTS; idx++) {
	printf("\nEnter person's %d grade : ", idx + 1);
	scanf("%d", &grades[idx]);

	if (grades[idx] > MAX_GRADE) {
	    printf("\nThe highest grade possible is 100");
	    printf("\nEnter correct grade : ");
	    scanf("%d", &grades[idx]);
	} else
	    total += grades[idx];
    }
    printf("\n\nThe average grade is %d\n", (total / STUDENTS));
    return 0;
}

another question : why idx<STUDENTS and not idx<=STUDENTS

In a C++ array of size N, the indices go from 0 to N-1, not from 1 to N. So idx < STUDENTS is correct.

Errors and issues aside,
there is no best practice on what loop or logic to use. Use what makes sense to the reader and expresses what you need done. All the c++ loops have uses. Generally for loops are the most common, and the most flexible as you can even make a loop that does work inside it (below). Do-while avoids the "seed before loop" issue (below). While is used often when unsure how much you have.

for(i =0, x=0; i< 100; x=i++); //a silly loop that assigns x 0 - 99 without a loop body
//this isnt recommended, because it has no advantages and is hard to understand.
its a case of just because you can do something does not mean you should... but there are uses of this technique to initialize variables and such. Other for loop hackery..

for(;;) //infinite loop (conditional break to exit)
for (; condition;) //... while loop surrogate



x = 0;
while (x != 10) /seeded while loop
cin >> x;

do
cin >> x;
while (x != 10) /better than seeding

Topic archived. No new replies allowed.