Skip to content

Exercise 10 of 10 · A complete program

The Cafe Ticket

What you will make

A printed cafe receipt with the shop name at the top, three item rows in straight columns, a subtotal, a service charge the program works out itself, a total, and a thank-you line at the bottom.

The one new idea: Assembling a complete program from parts you already know

Nothing in this program is new, and that is the point. Real software is almost never one clever idea; it is a handful of ordinary ones stacked in the order the work happens. Once you can look at a finished C program and name the parts, you can read other people's code and keep building your own.

Go straight to the code ↓

Nothing new, all at once

Every exercise so far handed you one new idea and somewhere small to try it. This one hands you no new idea at all. Every line in the editor is something you have already met.

That is what a finished program is. Not one clever trick, but a handful of ordinary ones arranged in the order the work actually happens. Here is this receipt, named piece by piece:

  • printf puts each line on the screen. That was the very first thing you wrote in this whole path.
  • Variables hold the parts that change: name, qty, price.
  • Arithmetic turns them into amounts: qty * price for one row, subtotal / 10 for a tenth of the bill.
  • An if decides whether the service charge applies to this order at all.
  • Field widths — %-12s, %6d — are what make the columns land in a straight line instead of wandering.
  • An array and a for loop print the small notes at the bottom without a separate printf for each one.
  • A running total, subtotal += cost;, collects the order as it goes, exactly as it collected a week of rainfall.

Seven ideas, none of them new here, all of them in one receipt.

The running total, one more time

int subtotal = 0; sits above the items, and subtotal += cost; appears once per item. It is the same line you wrote for the rainfall chart, doing the same job on different values: read whatever subtotal holds now, add this row's cost, store the answer back under the same name. The rainfall chart had a loop repeat that line for it; here the three items sit one under the other, so it is repeated by hand instead. The pattern does not mind either way.

It sits behind every bill, every score and every count you will write. A total is not typed. It is collected.

A worked example

A market stall rather than a cafe, so the receipt in the editor stays yours to finish:

C
#include <stdio.h>

int main(void) {
    int total = 0;
    const char *name;
    int qty, price, cost;

    name = "Apples";
    qty = 4;
    price = 12;
    cost = qty * price;
    total += cost;
    printf("%-8s%5d\n", name, cost);

    name = "Bread";
    qty = 1;
    price = 30;
    cost = qty * price;
    total += cost;
    printf("%-8s%5d\n", name, cost);

    printf("-------------\n");
    printf("TOTAL%8d\n", total);
    return 0;
}
Output
Apples     48
Bread      30
-------------
TOTAL      78

Two blocks of the same six lines with different values in them, and a total nobody typed in. Change the 4 to a 5 and both the apples row and the total move with it, because both are worked out rather than written down.

Your turn

Press Run before changing anything. Most of the receipt is already correct: the header, the first two item rows, the service charge, the notes at the bottom.

Two lines are marked, and both of them already run. They are wrong, not missing.

  1. The cake's row still prints its four values with bare placeholders and typed spaces, so the numbers land nowhere near the columns above them. Rewrite it as a printf call matching the two rows above it, character for character except for the values.
  2. total is set to 0, so the bottom of the receipt disagrees with the rest of it. Work it out from the two values the program already has: the amount for the items, and the service charge.

Then change something: the cake to two slices, the chai to another price. Run it again. The row, the subtotal, the service charge and the total should all move together. That is the difference between a receipt that is worked out and one that is typed.

If something goes wrong

The likeliest slip is the total, and it announces itself: the TOTAL line shows 0, or a number that does not match the two above it. Check that both names on the right of the = are spelled as they are spelled further up, and that the line still sits below the service charge — C reads top to bottom, so a value has to exist before it can be added to anything.

If the cake row prints its four values glued together with single spaces rather than sitting in columns, the format string is still the bare %s %d %d %d from the starter code rather than the width-specified one from the rows above it.

Nothing here can break. Change the order, run it again, and read your own receipt.

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

Typing the final total in by hand, such as int total = 154;
The number is right this minute and wrong the moment anything changes. Order two slices of cake instead of one and the rows and the subtotal update themselves, while a typed total sits underneath contradicting them. A total is worked out from the values above it, never copied off the screen.
Giving the cake row different width numbers from the rows above it
The rows line up only because every one of them gives the name twelve characters, the quantity three, the price five and the amount six. Change one of those numbers on one row and that row alone drifts out of column while the others stay put.
Writing total = cost + service;
cost holds the amount for the last item only, because the same variable is reassigned by each block, so the receipt would total 55 + 14 instead of 140 + 14. The variable that has been collecting the whole order across all three items is subtotal.
Forgetting the doubled %% in "Service 10%%%15d\n"
A single % inside a printf format string is read as the start of a placeholder, so the compiler expects a conversion letter right after it and either misreads the rest of the line or, with the literal percent sign this row needs, prints something other than a percent sign. %% is how you print one literal % character.

Want a blank editor instead? Open the C playground.