0

I've been trying to figure this out the last few days, but no luck. The objective is to find the sum, average, minimum, and maximum grades and display them.

Here is my code, everything except minimum, maximum and grade input seem to work

// Includes printf and scanf functions
#include <stdio.h>

int main(void) {
    unsigned int counter; // number of grade to be entered next
    int grade; // grade value
    int total; // sum of grades entered by user
    float average; // average of grades
    int maxi; // Max grade
    int mini; // min grade
    int i;
    int max;
    int min;

    maxi = 1;
    mini = 1;

    printf("Enter number of grades: "); // User enters number of grades
    scanf("%d", &counter); // Countss number of grades
    //scanf("%d%d", &min, &max);

    for (i = 1; i <= counter; i++) {
        printf("Enter grade %d: ", i); // User enters grade
        scanf("%d", &grade); // Counts grades
        //scanf("%d",&counter);

        if (grade < 0 || grade > 100) {
            printf("Please enter a number between 0 and 100!\n"); // Lets user know if input is invalid
            i--;
            break;
        }
        else {
            total = total + grade;
            average = (float)total / counter; // NOTE: integer division,    not decimal
        }
    }

    max = (grade < maxi) ? maxi : grade;
    min = (grade > mini) ? mini : grade;

    printf("Class average is: %.3f\n", average); // Displays average
    printf("Your maximum grade is %d\n", max); // Displays Max
    printf("Your minimum grade is %d\n", min); // Displays minimum
    printf("Sum: %d\n", total); // Displays total
}

Output:

Enter number of grades: 2
5
7
Enter grade 1: 4
Enter grade 2: 3
Class average is: 3.500
Your maximum grade is 3
Your minimum grade is 1
Sum: 7

For some reason when I start the program, I have to enter a few numbers, in this case 5 & 7 before it prompts me to "Enter grade" then from there it calculates everything. Also, it seems that the Maximum is always the last grade that I enter and shows 1 as the minimum when no where in the input is 1. I am supposed to use a conditional operator for the max/min, I tried looking it up and reading the book, but they just use letters like a,b,c, etc. Which just confused me so I'm not sure if I did it wrong.

Could that be what is messing everything up? If it isn't what am I doing wrong?

Another thing is I'm thinking I need a While loop if I want to make the counter have an input from 1-100, is that right?

Edit: just realized I had to remove the scanf for max and min. Taht's why I had to inptu 2 nubmers first

Swordfish
  • 12,971
  • 3
  • 21
  • 43
SirChryse
  • 61
  • 1
  • 2
  • 8
  • 1
    `maxi=1; mini=1;` should start with extreme values like `maxi=0; mini=100;` in this case. – chux - Reinstate Monica Sep 25 '18 at 13:36
  • Hint: the first time `total + grade` is called, what is the value of `total`? – chux - Reinstate Monica Sep 25 '18 at 13:37
  • 1
    Min/max could also be initialized by [INT_MAX](https://www.tutorialspoint.com/c_standard_library/limits_h.htm). I believe your initial problem of needing to enter a few numbers to start the loop starts is because you are asking the program to scanf for three numbers (In your case, number of grades, min, and max) before it can start the for loop. Just remove the second scanf statement to rectify that. – Reticulated Spline Sep 25 '18 at 13:38
  • @chux So for maximum it should be 0 and minimum it should be 100? – SirChryse Sep 25 '18 at 13:46
  • @ChrisD93 Yes. In general, a simple idea to to initialized `max` with the most minimal value like `INT_MIN` and `min` with the greatest `INT_MAX`. Should you use 0,100 or `INT_MIN,INT_MAX`, the error condiiton of "no grades entered, unable to report min/max" is detectable with `if(min > max)`. It depends on what you want to report when no grades are entered. (`counter <= 0`). – chux - Reinstate Monica Sep 25 '18 at 13:54

5 Answers5

1

There are two major problems, as I see it

  • The variable total is not initialized, so the first occurrence of total = total + grade; would invoke undefined behaviour.

    You have to initialize it explicitly to 0.

  • The same variable grade is used for holding the repeated input. After the loop, grade will only hold the last input value.

    You need to either use an array for storing inputs and comparison, or, compare and update the min and max as you go, inside the loop.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
1

For future references, please seperate your code in different functions or add comments, since analyzing an unfamiliar code always takes much time.

min: Your problem here lies, that you're initializing your min value with 1. That value is most of the time below your input grades. If you want to initialize it, you should use a high number. For example:

#include <limits.h>
int min = INT_MAX;

max: Your "grade" will be always the last typed grade, which you scanned. That's not what you want. It would be good, to save all values, which you get as input in an array or a list.

Also your codesnippet at the end

max = (grade<maxi) ? maxi : grade;
min = (grade>mini) ? mini : grade;

will just compare one grade. You need to compare all values, which you entered. You could just put them in the for-loop.

gradeinput: You need to temporarily save your inputs in a datastructure like an array/list to use them in your program.

int x[counter];
for (i = 1; i <= counter; i++) {
    printf("Enter grade %d: ", i);
    x[i]=scanf("%d", &grade);
}
dnsiv
  • 520
  • 4
  • 20
1

.. have to enter a few numbers, in this case 5 & 7 before it prompts me to "Enter grade"

This happens because OP's stdout is buffered and not one character at a time.

To insure output is seen before the scanf(), use fflush().
See What are the rules of automatic flushing stdout buffer in C?

printf("Enter number of grades: ");
fflush(stdout); // add
scanf("%d", &counter);

Rather than set the min = 1, set to a great value

maxi = 1;
mini = 1;

maxi = 0;
mini = 100;
// or 
maxi = INT_MIN;
mini = INT_MAX;

Move the test for min/max in the loop to test each value and fold maxi, max into the same variable.

    if (max > grade) max = grade;
    if (min < grade) min = grade;

The first total + grade is a problem as total is uninitialized.

// int total; // sum of grades entered by user
int total = 0; // sum of grades entered by user

Unnecessary to calculate average each time though the loop. Sufficient to do so afterward.

Style: After the break; the else is not needed.

Good that code tests user input range. Yet the i-- is incorrect. If code is to break, just break. If code it to try again, the i-- makes sense, but then code should continue.

The comment // NOTE: integer division, not decimal is incorrect as (float) total / counter is FP division.

    if (grade < 0 || grade > 100) {
      printf("Please enter a number between 0 and 100!\n");
      i--;
      continue;
    }
    total = total + grade;
  } // end for
  average = (float) total / counter;

In general, casting should be avoided.

Advanced issue: Consider the situation if later on code was improved to handle a wider range of integers and used higher precision FP math.

The 1st form causes total to become a float (this could lose precision) and perhaps use float to calculate the quotient, even if average was a double. Of course the (float) cast could be edited to (double) as part of the upgrade, but that is a common failure about updates. Types may be changed, but their affected object uses are not fully vetted.

The 2nd form below causes total to become the same type as average and use the matching math for the type. Reduced changed needed as the types change. This form is also easier to review as one does not need to go back and check the FP type of average to see if a cast to float, double or even long double was needed.

  average = (float) total / counter;
  // or
  average = total;
  average /= counter;
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

For some reason when I start the program, I have to enter a few numbers, in this case 5 & 7 before it prompts me to "Enter grade"

You have two scanf before "Enter grade"

scanf("%d", &counter);
scanf("%d%d", &min, &max);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0
#include <stdio.h>

int main(void) {
    int counter; // number of grade to be entered next
    int grade; // grade value
    int total=0; // sum of grades entered by user
    float average; // average of grades
    int i;
    int max;
    int min;

    printf("Enter number of grades: "); // User enters number of grades
    scanf("%d", &counter); // Countss number of grades

    for (i = 1; i <= counter; i++) {
        printf("Enter grade %d: ", i); // User enters grade
        scanf("%d", &grade); // Counts grades

        if (grade < 0 || grade > 100) {
            printf("Please enter a number between 0 and 100!\n"); // Lets user know if input is invalid
            i--;
        } else {
          if(i==1){
              max = grade;
              min = grade;
          }
          else{
              max = (grade < max) ? max : grade;
              min = (grade > min) ? min : grade;
          }
          total = total + grade;
          average = (float) total / counter; // NOTE: integer division,    not decimal
        }
      }

    printf("Class average is: %.3f\n", average); // Displays average
    printf("Your maximum grade is %d\n", max); // Displays Max
    printf("Your minimum grade is %d\n", min); // Displays minimum
    printf("Sum: %d\n", total); // Displays total
}

I've edited your Code as there were some mistakes. First, you were not initialising the total, which may make it take some garbage value. The second one is no need of using break as you are reducing the value of i.The third one is that you are updating the min and max outside the for loop, where the value of grade will be the last entered grade. And maxi and mini are not at all needed. The code was running perfectly without waiting for dummy values. Cheers!

sriharshay
  • 63
  • 9
  • That makes sense now, thank you. just curious though, how come maxi and mini weren't needed? – SirChryse Sep 25 '18 at 18:17
  • You used then just for initializing max and min right. You have max and min separately, which you can initialize with the first grade as the first grade that we enter will be both max. and min. of your inputs. From the next iteration, you check if the new grade is bigger or smaller. That's it. 'maxi' and 'mini' are just redundant here. – sriharshay Sep 26 '18 at 08:36