Skip to content

Exercise 9 of 10 · Putting it together

Rainfall Week

What you will make

A seven-day rainfall chart with a row for every day, the week added up underneath it, and the wettest of the seven days picked out.

The one new idea: A variable declared before a loop carries its value from one pass to the next

Adding up as you go, and holding on to the best value you have seen, are two patterns sitting underneath an enormous number of ordinary programs: a basket total, a high score, a longest streak, a running average. Each one is a variable declared before a loop and changed inside it.

Go straight to the code ↓

A variable that outlives one pass of the loop

There is no new syntax in this exercise. An array, a for loop, an if, +=, > — you have met every piece of it. That is the point. Knowing five things separately is not the same as getting them to work together in one program, and the gap between those two is where most people stall.

The idea that joins them up is small. A variable declared above a loop is still alive on every pass, and still alive after the loop ends, so whatever one pass leaves in it is what the next pass finds. Declare that same variable inside the loop instead, and it is created fresh and reset on every single pass, throwing away whatever the pass before it left there. Anything a loop must carry from one day to the next has to be declared above it.

Two things are worth carrying that way.

A running total. Declare a variable at zero above the loop, and inside the loop write total += mm;. += reads the right-hand side first — whatever total was a moment ago, plus this pass's value — and stores the answer back under the same name. After seven passes it holds the sum of all seven.

The best so far. Declare a second variable at zero above the loop, then inside the loop ask whether this pass beats it: if (mm > wettest_mm). When it does, store the new number. That variable then holds the largest value seen up to that moment — and by the final pass, the largest so far is simply the largest there is.

Remembering which day was wettest is one more line, not a new idea: inside the same if, store the day alongside the amount. They change together because they are one fact in two halves — the day that broke the record, and the amount that broke it.

A worked example

Four coins from a jar, with the total printed on every pass so you can watch it climb:

C
#include <stdio.h>

int main(void) {
    int coins[4] = {2, 5, 1, 5};
    int total = 0;
    int biggest = 0;

    for (int i = 0; i < 4; i++) {
        int coin = coins[i];
        total += coin;
        if (coin > biggest) {
            biggest = coin;
        }
        printf("coin %d  total %d\n", coin, total);
    }
    printf("biggest coin: %d\n", biggest);
    return 0;
}
Output
coin 2  total 2
coin 5  total 7
coin 1  total 8
coin 5  total 13
biggest coin: 5

total never drops back to zero, because the line that sets it to zero sits above the loop and runs once, before any counting starts. biggest ends on 5 — and notice it does not change on the last pass, even though that coin is a 5 too: 5 > 5 is false, so a tie leaves the first one in place.

Your turn

The editor holds a week of rainfall. rain is an array of seven measurements in millimetres, and the loop already prints a row for each: a day number and the measurement, right-justified in a field two wide so single-digit and double-digit readings line up.

Press Run first. The chart is correct; the two lines beneath it are not. The total reads 0 mm, and the wettest day comes out as day 0, which is not one of the seven.

Both of your additions go inside the loop, alongside the printf that is already there.

  1. Add this day's rain, mm, to total.
  2. If this day beats wettest_mm, store both the new amount and the day number.

total, wettest_mm and wettest_day already exist above the loop, all holding zero: you are not declaring them, only changing them as the loop goes round.

If something goes wrong

The likeliest slip is where a line is written. A line placed after the loop's closing brace cannot see mm or day at all, because both were declared inside the loop and stop existing the moment it ends — the compiler will point at exactly that line with an undeclared identifier.

If the millimetres come out right but the day stays at 0, the if is updating wettest_mm and forgetting wettest_day. Both lines belong inside the if's braces.

If the compiler warns about an assignment used as a condition, the comparison was written with a single =. The test here needs > in the first place, not == either.

Nothing here can break. Once the week adds up, change one of the numbers in rain and run it again: the total and the wettest day should both move on their own.

Write your code

Runs in your browser. Press Run (or Ctrl/Cmd+Enter) and the output is checked for you.

Ctrl/Cmd+Enter to run

Press Esc then Tab to move keyboard focus out of the code editor.

Ready
Output will appear here after you run your code.

The runtime is starting in the background. You can type now — it will be ready before you are.

The answer appears here once you have run your code at least once.

Things that often go wrong here

Writing total += mm; after the loop's closing brace instead of inside it
A line outside the braces runs once, after every day has already gone past. At that point mm no longer exists — it was declared inside the loop and stopped existing when the loop ended — so this would not even compile; the fix is keeping the line inside the braces where mm is still in scope.
Declaring int total = 0; on the first line inside the loop instead of before it
A declaration inside the loop runs fresh on every pass, so total would be reset to zero seven times and the week would add up to whatever the last day alone held. A starting value has to be declared above the loop, where it happens exactly once.
Remembering the amount but not the day
An if that updates only wettest_mm leaves wettest_day holding the zero it started with, so the last line claims the wettest day was day 0, which is not one of the seven. Both lines belong inside the same if, because they are two halves of one fact.
Writing if (mm = wettest_mm) with one equals sign
That assigns wettest_mm's value into mm rather than comparing them, and the true test here needed was greater than in the first place. The compiler will generally warn about an assignment used as a condition; the fix is both the second equals sign and the right operator, >.

Longer explanation: read the full lesson. Want a blank editor instead? Open the C playground.