I'm having problems within a for loop getting the loop to continue where it left off after an invalid entry. This is what the output should look like:
This program calculates the average of as many grades you wish to enter.
First, enter the number of grades to process: 4
Now enter the 4 grades to be averaged.
Enter grade #1: 90
Enter grade #2: 80
Enter grade # 3: -20
*** Invalid entry. Grade must be 0 to 100. ***
Enter grade #3: 25
Enter grade #4: 54
The average of the 4 grades entered is 62
You have a letter grade of F
This is what I have so far...I'm guessing I need to use "continue" after the if else statements but I'm not sure about the placement or what additional entries I need to make it work...this is what I have so far (this is homework and your guidance is greatly appreciated).
intnumOfGrades,i,grade;intgradeTotal=0;intgradeAvg;/* Comment about the function of the program. */printf("\nThisprogramcalculatestheaverageofasmanygradesyouwishtoenter.\n");/* Prompt user for number of grades to process. */printf("\nFirst,enterthenumberofgradestoprocess:");scanf("%i",&numOfGrades);fflush(stdin);/* Prompt user for the number of grades to be averaged. */printf("\nNowenterthe%igradestobeaveraged.\n",numOfGrades);/* Define loop, calculate average for total number of grades */for(i=1;i<=numOfGrades;++i){/* Prompt user for grades. */printf("\nEntergrade#%i:",i);scanf("%i",&grade);fflush(stdin);/* Display error message when entry is less than 0 or more than 100 */if(grade<0)printf("***Invalidentry.Grademustbe0to100.***\n");elseif(grade>100)printf("***Invalidentry.Grademustbe0to100.***\n");gradeTotal=gradeTotal+grade;}/* End for loop*/gradeAvg=gradeTotal/numOfGrades;/* Display the overall average of the grades entered. */printf("\nTheaverageofthe%igradesenteredis%i\n",numOfGrades,gradeAvg);/* Display the letter grade based on the average and grading standards. */if(gradeAvg>=90&&gradeAvg<=100)printf("\nYouhavealettergradeofA\n");elseif(gradeAvg>=80&&gradeAvg<=89)printf("\nYouhavealettergradeofB\n");elseif(gradeAvg>=70&&gradeAvg<=79)printf("\nYouhavealettergradeofC\n");elseif(gradeAvg>=60&&gradeAvg<=69)printf("\nYouhavealettergradeofD\n");elseif(gradeAvg<60)printf("\nYouhavealettergradeofF\n");getchar();
} / End main /
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> you still need to get each score (the outer loop) until
> it is valid (the inner loop). That is how you need to be thinking.
To clarify that point, when describing requirements, you might put it like that in English (or your native language), the assignment may say that, and you should be able to identify phrases such as "get each" and "until it is valid" as directly mapping to programming constructs; then you are thinking like a programmer.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I figured out continue is not what I'm looking for and a trap is closer to the mark but I'm still at a loss for how to define it. I cleaned up the if statement in the loop. This is what I have so far...how do I get the program to prompt me again for the #3 grade when an invalid entry is made?
intnumOfGrades,i,grade;intgradeTotal=0;intgradeAvg;/* Comment about the function of the program. */printf("\nThisprogramcalculatestheaverageofasmanygradesyouwishtoenter.\n");/* Prompt user for number of grades to process. */printf("\nFirst,enterthenumberofgradestoprocess:");scanf("%i",&numOfGrades);fflush(stdin);/* Prompt user for the number of grades to be averaged. */printf("\nNowenterthe%igradestobeaveraged.\n",numOfGrades);/* Define loop, calculate average for total number of grades */for(i=1;i<=numOfGrades;++i){/* Prompt user for grades. */printf("\nEntergrade#%i:",i);scanf("%i",&grade);fflush(stdin);/* Display error message when entry is less than 0 or more than 100 */if(grade<0||grade>100)printf("***Invalidentry.Grademustbe0to100.***\n");gradeTotal=gradeTotal+grade;}/* End for loop*/gradeAvg=gradeTotal/numOfGrades;/* Display the overall average of the grades entered. */printf("\nTheaverageofthe%igradesenteredis%i\n",numOfGrades,gradeAvg);/* Display the letter grade based on the average and grading standards. */if(gradeAvg>=90&&gradeAvg<=100)printf("\nYouhavealettergradeofA\n");elseif(gradeAvg>=80&&gradeAvg<=89)printf("\nYouhavealettergradeofB\n");elseif(gradeAvg>=70&&gradeAvg<=79)printf("\nYouhavealettergradeofC\n");elseif(gradeAvg>=64&&gradeAvg<=69)printf("\nYouhavealettergradeofD\n");elseif(gradeAvg<64)printf("\nYouhavealettergradeofF\n");getchar();
} / End main /
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Goog for you for being honest about it being homework. You of course realise that we need to be careful about how much help we can give.
Think clearly (like a programmer ;-) ): What you are trying to do is "do something until it is right". Now C does not have a do-until construct, so switch it around: "do something while it is still wrong"
Want perhaps a few extra marks? Consider you if/else if/else construct at the end. You can make the conditions far simpler if you reverse the order of the tests - starting from F. Only the first matching condition is executed, so you only then need to test the upper bound in each case because the lower bounds would have been trapped by a preceeding condition. Also it is simpler (visually at least) to test the bound in such a way as to use < rather than <=:
Note that you never need to test for >100 because you validated the inputs in the first instance. Also you never need a test to the final condition because if it gets that far, it must be true, so that can (and should) be just a plain else not an "else if".
Some style points you may take or leave:
1) Don't place a blank line between a comment and the block the comment refers to. They should be tightly coupled.
2) Always use {...} around a conditional block even if it is a single line. It is easier to read and maintain (i.e. you may later add more code to the block) and is less error prone. Less importantly perhaps when you post the code here and the forum removes all your indenting, it is easier to distinguish.
3) Conventionally in if/else if/else constructs the "else if" is placed on one line, and the subsequent block is not indented. Although it is in fact syntactically a series of nested if/else constructs, it is generally considered a different construct and laid out accordingly. For example, I reformatted your code in VC++ using its auto-format and it laid the code out with increasing indentation, placing the if and the else together causes it to us a more conventional vertical layout even though it is syntactically identical.
On the whole however, nice job - the code you posted compiled cleanly and executed without error.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you for the quick reply, after some effort back at the drawing board I think I'm close but the grade average calculation is incorrect (13 instead of 62?) and I don't see where I funked it up...here's what I have now (I'll definitely work on the style after the do =):
intnumOfGrades,i,grade;intgradeTotal=0;intgradeAvg;/* Comment about the function of the program. */printf("\nThisprogramcalculatestheaverageofasmanygradesyouwishtoenter.\n");/* Prompt user for number of grades to process. */printf("\nFirst,enterthenumberofgradestoprocess:");scanf("%i",&numOfGrades);fflush(stdin);for(i=1;i<=numOfGrades;++i)do{/* Prompt user for grades. */printf("\nEntergrade#%i:",i);scanf("%i",&grade);fflush(stdin);/* Display error message when entry is less than 0 or more than 100 */if(grade<0||grade>100)printf("***Invalidentry.Grademustbe0to100.***\n");}while(grade<0||grade>100);gradeTotal=gradeTotal+grade;gradeAvg=gradeTotal/numOfGrades;/* Display the overall average of the grades entered. */printf("\nTheaverageofthe%igradesenteredis%i\n",numOfGrades,gradeAvg);/* Display the letter grade based on the average and grading standards. */if(gradeAvg>=90&&gradeAvg<=100)printf("\nYouhavealettergradeofA\n");elseif(gradeAvg>=80&&gradeAvg<=89)printf("\nYouhavealettergradeofB\n");elseif(gradeAvg>=70&&gradeAvg<=79)printf("\nYouhavealettergradeofC\n");elseif(gradeAvg>=64&&gradeAvg<=69)printf("\nYouhavealettergradeofD\n");elseif(gradeAvg<64)printf("\nYouhavealettergradeofF\n");getchar();
} / End main /
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You should do it twice.
Once to validate the number of grades input (before the for loop).
Next to validate each of the grades input (inside the for loop).
It might help to create a function that can do this.
int GetInteger(const char *prompt, const int min, const int max)
{
int input;
> You should do it twice.
> Once to validate the number of grades input (before the for loop).
Good point; although entering a negative number or zero, the loop will simply fall through, which might be acceptable. Of course a reasonable maximum might be in order, but that is arguable, the user might be there a long time entering data, but it won't break the code.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Doah! Hand smack to the forehead! I just noticed that too. I do appreciate it guys, this class I'm taking is a little tough for an old man like me. I owe you both a Guinness.
Cheers!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> is the do loop within the for loop or instead of the for loop?
Within, you still need to get each score (the outer loop) until it is valid (the inner loop). That is how you need to be thinking.
> but the grade average calculation is incorrect (13 instead of 62?)
You broke it! ;-) You have been hoisted on your own petard, and I did warn you always use {...} even for single statement blocks. In updating the code you seem to have removed the {..} from the for loop, so only the while loop is contained within the loop, the accumulation of gradeTotal is outside the loop and only executed once for the last value entered.
An conventional and consistent code indentation style should have highlighted that problem - it is impossible to tell because of this forums removal of such layout.
If you always follow an if, for, while, or do with a { even when you don't technically need to, you will more easily be able to spot such errors. Using {...} in all cases is consistent. When it is missing, you have to think - "was this intentional, or was it a screw-up?", save yourself the bother, just do it.
> I'll definitely work on the style after the do =):
Probably a good idea, but style is something taht should become a habit, not something you apply afterwards. As I said, consistent layout should help show up faults such as the omission of the {..} in teh for loop.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm having problems within a for loop getting the loop to continue where it left off after an invalid entry. This is what the output should look like:
This program calculates the average of as many grades you wish to enter.
First, enter the number of grades to process: 4
Now enter the 4 grades to be averaged.
Enter grade #1: 90
Enter grade #2: 80
Enter grade # 3: -20
*** Invalid entry. Grade must be 0 to 100. ***
Enter grade #3: 25
Enter grade #4: 54
The average of the 4 grades entered is 62
You have a letter grade of F
This is what I have so far...I'm guessing I need to use "continue" after the if else statements but I'm not sure about the placement or what additional entries I need to make it work...this is what I have so far (this is homework and your guidance is greatly appreciated).
include <stdio.h>
int main(void)
{
/ declare variables. /
} / End main /
> you still need to get each score (the outer loop) until
> it is valid (the inner loop). That is how you need to be thinking.
To clarify that point, when describing requirements, you might put it like that in English (or your native language), the assignment may say that, and you should be able to identify phrases such as "get each" and "until it is valid" as directly mapping to programming constructs; then you are thinking like a programmer.
Clifford
I figured out continue is not what I'm looking for and a trap is closer to the mark but I'm still at a loss for how to define it. I cleaned up the if statement in the loop. This is what I have so far...how do I get the program to prompt me again for the #3 grade when an invalid entry is made?
include <stdio.h>
int main(void)
{
/ declare variables. /
} / End main /
Goog for you for being honest about it being homework. You of course realise that we need to be careful about how much help we can give.
Think clearly (like a programmer ;-) ): What you are trying to do is "do something until it is right". Now C does not have a do-until construct, so switch it around: "do something while it is still wrong"
...
...
} while( grade < 0 || grade > 100 ) ;
Want perhaps a few extra marks? Consider you if/else if/else construct at the end. You can make the conditions far simpler if you reverse the order of the tests - starting from F. Only the first matching condition is executed, so you only then need to test the upper bound in each case because the lower bounds would have been trapped by a preceeding condition. Also it is simpler (visually at least) to test the bound in such a way as to use < rather than <=:
Of course you need not reverse it you could test the lower bounds
Note that you never need to test for >100 because you validated the inputs in the first instance. Also you never need a test to the final condition because if it gets that far, it must be true, so that can (and should) be just a plain else not an "else if".
Some style points you may take or leave:
1) Don't place a blank line between a comment and the block the comment refers to. They should be tightly coupled.
2) Always use {...} around a conditional block even if it is a single line. It is easier to read and maintain (i.e. you may later add more code to the block) and is less error prone. Less importantly perhaps when you post the code here and the forum removes all your indenting, it is easier to distinguish.
3) Conventionally in if/else if/else constructs the "else if" is placed on one line, and the subsequent block is not indented. Although it is in fact syntactically a series of nested if/else constructs, it is generally considered a different construct and laid out accordingly. For example, I reformatted your code in VC++ using its auto-format and it laid the code out with increasing indentation, placing the if and the else together causes it to us a more conventional vertical layout even though it is syntactically identical.
On the whole however, nice job - the code you posted compiled cleanly and executed without error.
Clifford
I think I follow you on the do loop but I'm missing the mark a little...is the do loop within the for loop or instead of the for loop?
Hey Clifford,
Thank you for the quick reply, after some effort back at the drawing board I think I'm close but the grade average calculation is incorrect (13 instead of 62?) and I don't see where I funked it up...here's what I have now (I'll definitely work on the style after the do =):
include <stdio.h>
int main(void)
{
/ declare variables. /
} / End main /
You should do it twice.
Once to validate the number of grades input (before the for loop).
Next to validate each of the grades input (inside the for loop).
It might help to create a function that can do this.
int GetInteger(const char *prompt, const int min, const int max)
{
int input;
do
{
printf("%s",prompt);
scanf("%i",&input);
} while(input < min || input > max);
return input;
}
> You should do it twice.
> Once to validate the number of grades input (before the for loop).
Good point; although entering a negative number or zero, the loop will simply fall through, which might be acceptable. Of course a reasonable maximum might be in order, but that is arguable, the user might be there a long time entering data, but it won't break the code.
Clifford
As for the bug you mention, is the scope of the for loop.
for ( i = 1; i <= numOfGrades; ++i )
{ // add this opener...............................................
...
gradeTotal = gradeTotal + grade;
} // add this closer..................................................
gradeAvg = gradeTotal /numOfGrades;
Thanks Ron!
Doah! Hand smack to the forehead! I just noticed that too. I do appreciate it guys, this class I'm taking is a little tough for an old man like me. I owe you both a Guinness.
Cheers!
> is the do loop within the for loop or instead of the for loop?
Within, you still need to get each score (the outer loop) until it is valid (the inner loop). That is how you need to be thinking.
> but the grade average calculation is incorrect (13 instead of 62?)
You broke it! ;-) You have been hoisted on your own petard, and I did warn you always use {...} even for single statement blocks. In updating the code you seem to have removed the {..} from the for loop, so only the while loop is contained within the loop, the accumulation of gradeTotal is outside the loop and only executed once for the last value entered.
An conventional and consistent code indentation style should have highlighted that problem - it is impossible to tell because of this forums removal of such layout.
If you always follow an if, for, while, or do with a { even when you don't technically need to, you will more easily be able to spot such errors. Using {...} in all cases is consistent. When it is missing, you have to think - "was this intentional, or was it a screw-up?", save yourself the bother, just do it.
> I'll definitely work on the style after the do =):
Probably a good idea, but style is something taht should become a habit, not something you apply afterwards. As I said, consistent layout should help show up faults such as the omission of the {..} in teh for loop.
Clifford