C Tutorial
C Project: Grade Book
Store scores in an array, print each mark, then compute the average and the highest score.
What you will build
A grade book is a short table of students and marks. C stores that table as an array of structs. You print every row, add the marks, divide by the count for the average, and walk the array once more (or in the same loop) to keep the highest score.
Demo data is hardcoded so the program runs with no scanf. OpenTry it in C under an example for /c/try.
An array of marks
Before names, practice on a plain int array. A running total and a running maximum both start from the first element. The average is a double so a set such as 70, 80, 90 does not become 80 through integer division.
Example
#include <stdio.h>
int main(void) {
int scores[] = {70, 85, 90, 64, 88};
int n = (int)(sizeof scores / sizeof scores[0]);
int total = 0;
int highest = scores[0];
for (int i = 0; i < n; i++) {
printf("mark %d: %d\n", i + 1, scores[i]);
total += scores[i];
if (scores[i] > highest) {
highest = scores[i];
}
}
printf("average: %.1f\n", (double)total / n);
printf("highest: %d\n", highest);
return 0;
}Cast total to double before dividing. total / n with two ints throws away the fraction.
Records with a name and a score
A mark without a name is hard to read. A struct pairs them. Each element of the array is one student. The loop still prints every mark. The average and the maximum use the score field only.
Example
#include <stdio.h>
struct Student {
char name[24];
int score;
};
int main(void) {
struct Student book[] = {
{"Ada", 92},
{"Nia", 76},
{"Omar", 88},
{"Pia", 81},
};
int n = (int)(sizeof book / sizeof book[0]);
for (int i = 0; i < n; i++) {
printf("%-8s %3d\n", book[i].name, book[i].score);
}
return 0;
}Compile the table at /c/try. %-8s left-aligns the name in eight columns so the numbers line up. This is the C track editor at /c/try.
Average and highest in one pass
Walk the roster once. Add every score. Remember the index of the largest score, not only the number, so you can print the student who earned it. If two people tie, this version keeps the first one it saw.
Example
#include <stdio.h>
struct Student {
char name[24];
int score;
};
int main(void) {
struct Student book[] = {
{"Ada", 92},
{"Nia", 76},
{"Omar", 88},
{"Pia", 81},
{"Rae", 92},
};
int n = (int)(sizeof book / sizeof book[0]);
int total = 0;
int best = 0;
printf("%-8s %s\n", "name", "score");
for (int i = 0; i < n; i++) {
printf("%-8s %3d\n", book[i].name, book[i].score);
total += book[i].score;
if (book[i].score > book[best].score) {
best = i;
}
}
printf("average: %.2f\n", (double)total / n);
printf("highest: %d (%s)\n", book[best].score, book[best].name);
return 0;
}Ada and Rae both have 92. best stays 0 because Rae is not strictly greater. That rule is easy to explain and easy to change if you want the last tie instead.
Helpers for average and max
Once the loop is correct, move the arithmetic into functions. They take the array and the length. mainprints. Helpers that do not print are easier to test: you can call them on a tiny array of two records.
Example
#include <stdio.h>
struct Student {
char name[24];
int score;
};
double average(const struct Student list[], int n) {
int total = 0;
for (int i = 0; i < n; i++) {
total += list[i].score;
}
return (double)total / n;
}
int max_index(const struct Student list[], int n) {
int best = 0;
for (int i = 1; i < n; i++) {
if (list[i].score > list[best].score) {
best = i;
}
}
return best;
}
int main(void) {
struct Student book[] = {
{"Ada", 92},
{"Nia", 76},
{"Omar", 88},
};
int n = (int)(sizeof book / sizeof book[0]);
int hi = max_index(book, n);
for (int i = 0; i < n; i++) {
printf("%s: %d\n", book[i].name, book[i].score);
}
printf("average %.2f, max %d\n", average(book, n), book[hi].score);
return 0;
}Common mistakes
- Dividing two ints for the average. Always convert one side to
doublefirst. - Starting
highestat 0 when scores can be zero or the book can be empty. For a non-empty array, start fromscores[0]or from index 0. - Using
==to compare names. Names are arrays. Print them with%s; search them withstrcmpin a later project. - Writing past
name[24]with a long string. Keep demo names short, or enlarge the array.
Practice
- Print the lowest score and the student who earned it, using the same roster.
- Count how many marks are at least 80 and print that count after the table.
- Add a letter-grade helper: 90 and up is A, 80 is B, 70 is C, 60 is D, else F, and print it beside each mark.