Writing your own functions
Learn
Anatomy of a function
You have called functions you did not write, like printf, and read a few small ones of your own. Now write them on purpose. A function is a named piece of work: values go in, the work happens, one value comes back.
int xp_needed(int level) {
return level * level * 50;
}intin front of the name is the return type, the type of the value handed back.(int level)is the parameter list. Every parameter has its own type, separated by commas.returnhands the value back and ends the call on the spot. Nothing after it on that path runs.
Calling xp_needed(4) passes the argument 4. Inside, level is a fresh variable holding a copy of it, and it only exists while the call is running.
Learn
Types in, types out
Any type can go in and come out:
double hp_percent(int hp, int max_hp); // two ints in, a double out
char grade(int score); // an int in, one char out
void print_bar(int filled, int width); // nothing comes backThe return type converts the value: return 7.9; in an int function hands back 7, chopped like a cast. void means no value at all. The function does its job, usually printing, and the call is a statement on its own: print_bar(6, 10);. A bare return; leaves a void function early.
If a function says int and a path reaches the closing brace without a return, C does not stop you. The caller gets junk. Return on every path.
Learn
Declare before use
The compiler reads top to bottom once, so it must know a function before the first call. Either write the whole function above main, or put its prototype, the first line plus a semicolon, near the top and the body anywhere below. Many programs list every prototype first, so the file opens like a table of contents.
A function cannot see main's variables. Everything it needs comes in through parameters, and the answer goes back through return. If the caller ignores the returned value, it is simply gone.
Try
Run it: a character sheet
The example is already in the editor. Run it, change one thing, and run it again.
#include <stdio.h>
int xp_needed(int level);
double hp_percent(int hp, int max_hp);
void print_bar(int filled, int width);
int main(void) {
int level = 4;
int hp = 27;
int max_hp = 40;
printf("Level %d, level %d at %d XP\n", level, level + 1, xp_needed(level + 1));
printf("HP %d of %d is %.1f percent\n", hp, max_hp, hp_percent(hp, max_hp));
print_bar(hp * 10 / max_hp, 10);
return 0;
}
int xp_needed(int level) {
return level * level * 50;
}
double hp_percent(int hp, int max_hp) {
return 100.0 * hp / max_hp;
}
void print_bar(int filled, int width) {
printf("[");
for (int i = 0; i < width; i++) {
if (i < filled) {
printf("#");
} else {
printf("-");
}
}
printf("]\n");
}
Try
Damage after armour
In a dungeon game, armour soaks up that many points of every attack, but a hit always does at least 1 damage. Finish int damage(int attack, int armour) so it returns the damage that gets through. main is done. Expected:
goblin hits the knight for 3dragon hits the knight for 31bat hits the knight for 1
#include <stdio.h>
int damage(int attack, int armour) {
return 0;
}
int main(void) {
printf("goblin hits the knight for %d\n", damage(12, 9));
printf("dragon hits the knight for %d\n", damage(40, 9));
printf("bat hits the knight for %d\n", damage(3, 9));
return 0;
}
PracticePredict the output
What comes back
Three functions, three rules from the lesson: a parameter is a copy, the return type converts, and return ends the call. Type exactly what this prints.
Read the program, type exactly what it prints, then lock it in. It runs after that.
#include <stdio.h>
int level_up(int level) {
level = level + 1;
return level * 10;
}
int split_loot(double gold) {
return gold / 2;
}
void join_party(int size) {
if (size >= 4) {
printf("party full\n");
return;
}
printf("joined, party of %d\n", size + 1);
}
int main(void) {
int level = 3;
int reward = level_up(level);
printf("%d %d\n", level, reward);
printf("%d\n", split_loot(7.0));
join_party(2);
join_party(4);
return 0;
}
Break/fixFix the bug
A bonus that never lands
A combo of 10 hits or more earns 5 points per hit. The function is right, but the score never changes. Fix main so it prints:
after a 12-hit combo: 260after a 3-hit combo: 260
#include <stdio.h>
int add_combo_bonus(int score, int combo) {
if (combo >= 10) {
score = score + combo * 5;
}
return score;
}
int main(void) {
int score = 200;
add_combo_bonus(score, 12);
printf("after a 12-hit combo: %d\n", score);
add_combo_bonus(score, 3);
printf("after a 3-hit combo: %d\n", score);
return 0;
}
Your turn
Judge a rhythm game
A rhythm game judges every note by how far off the beat you hit it, in milliseconds: negative is early, positive is late. Write three functions:
char judge(int ms_off)returns'P'(Perfect) within 30 ms either side,'G'(Good) within 80 ms, otherwise'M'(Miss).int combo_after(int combo, char result)returns the combo after a note: one more after a Perfect or a Good, back to 0 after a Miss.double accuracy(int perfect, int good, int notes)returns a percentage ofnoteswhere a Perfect counts as a whole note and a Good as half a note, fraction kept. With 0 notes it returns 0.
On your own. Hints open after your first check.
Passed
You can now