Hm, okay, I’m going to write out some feedback but be mindful that if you apply it all it might not make your TAs (or whoever grades you) too happy. Ask them whether or not they appreciate you putting in extra effort, or if they are only interested in having you solve the problem at hand.
As an example of a suggestion I’d make, that would be educational for you, would be to give more meaningful feedback on erroneous input. Let’s say some input can be wrong in two ways,
// Less good
if (!cond1 && !cond2) {
puts("Wrong you buffoon!");
exit(1);
}
I’d urge the following,
// Better
if (!cond1) {
puts("Wrong you buffoon! Expected cond1 to be satisfied");
exit(1);
}
if (!cond2) {
puts("Wrong you buffoon! Expected cond2 to be satisfied");
exit(1);
}
but if you apply this your software ends up being lengthier as a consequence. Sometimes, when someone grades you, they aren’t interested in how good you are, or how good a program you can submit, they only want it to be good enough.
Here are some remarks in no particular order, I do not consider the top-ones more urgent than the others.
A. Use the compiler
I’m not sure what C-standard you are being held to, but try compiling your program like this,
gcc -Wextra file.c # or whatever else your C-file is called
and you’ll get plenty of warnings.
- Fix those warnings
- Read up on other flags, here’s a good link
- Notice the flags that you feel would benefit you catch problems with your software and start using them
4 (optional). If you are using Makefiles, update those
5 (optional). Add an alias to your shell so that you can compile with those flags easy.
For 5, do this in your terminal: echo $SHELL and then google the last part of the output together with the word “alias”. Example:
echo $SHELL
/usr/bin/fish
Google “fish”.
B. Program structure
Decompose your program into additional functions, for instance, this bit
// get input
if(scanf("%d", &nMatches) != 1 || nMatches < 1) {
puts("incorrect input.");
return 0;
}
could easily be wrapped as a function called parseNumberOfMatches. I’d argue that for every input 1…4 it would have been prudent to write a function, i.e.
parseNumberOfMatches() -> n (have this yields a number, I just call it n, so that item 2 makes sense)
parseCategories(n) -> ??? (I write ??? because I want you to figure out what a good return would be here
parseParticipants() -> p (spell participants correctly)
parseScores(n, p) -> ???
And how could you write these and communicate that something went wrong to the caller?
and then the remaining bits belong in their own functions also,
- Find each category’s winner
- Overall winner
C. Explore alternatives
This remark is C-specific because there are a lot of functions around that shouldn’t be used anymore. Find alternatives for puts/scanf, when are they appropriate, what other alternatives are there? Do they offer more utility than these ones, and how much extra work would they comparatively be to use?
D. Exercise
How would you have to rewrite your program to be able to test it out automatically? I.e., if you were to write out the parsing functions I mentioned we could have this,
#include <stdbool.h>
int testThatNumberOfMatchesFailsOnZero() {
// Figure out a way to get a number when the input is appropriate,
// and something that indicates an error if something went wrong.
// Add the necessary checks here to check that we get a failure
// for the input of 0 and another test function that checks that
// for a given input < 0 we also fail. Finally, one more test that
// checks that for a given input number that is larger than 0 we
// get that number back
parseNumberOfMatches(-1)
}
This might seem silly, as the purpose of parseNumberOfMatches is to give the number back to us if it is correct but it creates a “barrier” between getting the number from the user, and evaluating that number. Programs written in incremental steps like these are usually easier to change, test, and debug. So rather than
int parseNumberOfMatches() {
// do some scanf-ing here
}
we adjust our program flow to go through the following sequence,
1. Get user input
2. Pass user input into validation function
Because now, unlike before, you can replace the user with a computer instead.
I had more thoughts but I don’t want to overwhelm you.