Learn C Programming

Lesson 6 of 7 · Constants, Qualifiers, Input and Output

Module 3 · Constants, Qualifiers, Input and Output

Problems: Reading and Printing

FreeProblems

In this lesson

  • Read a judge's input with the format the starter gives you, and check what it returned.
  • Print an answer whose every space and digit is where the statement says it is.
  • Answer a yes or no question without an if, by printing the comparison itself.

Ten problems, graded against hidden tests. Eight of them you already met inside the five lessons. Two are new.

The last set was about choosing a type. This one is about the two halves of talking to a judge. Getting the values in, and getting the answer out in exactly the shape that was asked for.

What is new since the last problem set

In Module 2 every answer was one number. Here half the answers are several lines, with widths, and a wrong space is a wrong answer.

Four of the ten are about layout. A field of the right width, a decimal point in the right place, a zero that must be printed rather than dropped.

Three are about the returned count of a read. Module 2 never mentioned it, because every input there was promised to arrive.

So read the Output section of each statement before the story. It is the specification, and the story is only there so you remember which problem it was.

Still no if, no loop and no remainder

This module comes before operators and before decisions. Nothing below needs if, for, while, the conditional ? or the % operator.

One problem asks a pair of yes or no questions, and the answer is a comparison printed with %d. Lesson 5 showed that a comparison is an expression worth 1 or 0.

Two problems compute money in whole paisa and put the decimal point back with printf, which needs division and subtraction and nothing else.

If you find yourself wanting a construct you have not met, the problem is telling you to reread a lesson rather than to look ahead.

Every starter already has its reads

Each graded problem opens with a scanf line written for you, in the right format, with the ampersands in place. Leave it alone.

That is not generosity. Lesson 4's traps are traps you meet once and then design around, and a judge is not the place to meet them. Your work is what happens after the read.

Two starters also declare an array of char for a name. Arrays are Module 9, so read char name[20] as twenty boxes in a row and use the name in a %s.

The specifiers these ten problems need

printf("%d\n", n)              an int
printf("%u\n", n)              an unsigned int
printf("%lld\n", n)            a long long
printf("%10u\n", n)            the same, in a field ten wide
printf("%10x\n", n)  %10X      lower and upper case base 16
printf("%10o\n", n)            base 8
printf("%-12s%5d\n", s, n)     a left aligned name, then a right aligned number
printf("%lld.%02lld\n", t, p)  whole taka, a point, two digits of paisa
printf("VAT %d%%\n", pc)       %% prints one percent sign

scanf("%d %d", &a, &b)         two ints
scanf("%u", &n)                an unsigned int
scanf("%lld", &n)              a long long
scanf("%x %o", &h, &o)         a base 16 then a base 8 number
scanf("%19s", name)            one word, at most 19 characters, no ampersand
  • %02lld pads to two digits, which is how 5 paisa prints as 05.
  • A width is a minimum. A value wider than its field pushes past it, and that is correct.
  • Every read here returns a count, and three problems print that count as part of their answer.

How to test before you submit

Four checks, and the second is the one that catches a layout bug.

  1. Run the sample. If the sample fails, nothing else matters.
  2. Count the characters of your first line against the sample's first line. Not the words, the characters.
  3. Run both ends of the constraints. Copy the largest allowed input out of the statement and paste it in.
  4. Run the empty input where the statement allows one, because two of these problems have a test with nothing in it.

So testing is not reading your program again. It is running it on the inputs the statement has already told you exist.

The hint ladder

Every problem below carries three steps you open in order. Hint 1 names what to notice, Hint 2 describes the approach in words, and Solution explains the whole method in two paragraphs.

Opening a hint is recorded and costs you nothing. Type the program yourself afterwards, because reading is not the skill.

Example 1: a read, and the count it returned

The shape three of these ten problems share. Keep what scanf gave back, then print it beside the values.

#include <stdio.h>

int main(void)
{
    int quantity = 0;
    int price = 0;

    int read = scanf("%d %d", &quantity, &price);

    printf("read %d\n", read);
    printf("quantity %d\n", quantity);
    printf("price %d\n", price);
    return 0;
}
read 2
quantity 12
price 4500

That output is for the input 12 4500. Give it only 12 and the first line reads 1 while the third still prints the 0 from the declaration.

Run in Compiler
Example 2: a table whose columns are the specification

A miniature of invoice-exact. Every width here comes from the statement, not from taste.

#include <stdio.h>

int main(void)
{
    const int VAT_PERCENT = 15;

    printf("%-12s%5s%10s\n", "ITEM", "QTY", "PAISA");
    printf("%-12s%5d%10lld\n", "rice", 12, 54000LL);
    printf("---------------------------\n");
    printf("VAT %d%%%10s%10lld\n", VAT_PERCENT, "", 8100LL);
    printf("%-12s%5s%10lld\n", "TOTAL", "", 62100LL);
    return 0;
}
ITEM          QTY     PAISA
rice           12     54000
---------------------------
VAT 15%                8100
TOTAL                 62100

The VAT line is built differently from the others, because its label carries a number. VAT 15% is seven characters, so the empty %10s after it brings the total to seventeen and the columns still line up.

Run in Compiler
Example 3: money in whole paisa, printed as taka

The two money problems in this set both do exactly this. No decimal type is ever involved.

#include <stdio.h>

int main(void)
{
    const long long VAT_PERCENT = 15;
    const long long PAISA_PER_TAKA = 100;
    const long long PERCENT_WHOLE = 100;

    long long subtotal = 23310;
    long long vat = subtotal * VAT_PERCENT / PERCENT_WHOLE;

    printf("vat paisa : %lld\n", vat);
    printf("vat taka  : %lld.%02lld\n", vat / PAISA_PER_TAKA,
           vat - vat / PAISA_PER_TAKA * PAISA_PER_TAKA);
    return 0;
}
vat paisa : 3496
vat taka  : 34.96

The true answer is 3496.5 paisa and the division dropped the half, which is what the statements mean by "the fraction dropped".

The second line gets the paisa without the % operator: divide, multiply back, subtract. Module 2 lesson 2's Exercise 4 built that idea.

Run in Compiler

Where this is used

  • Every programming contest. ICPC, Codeforces and the Progsity contest platform all judge output character by character. "Wrong answer on test 4" on a problem you believe is right is almost always a width or a decimal place.
  • A point of sale terminal. The receipt a shop prints has fixed columns, so the till roll is readable. The amounts are counted in the smallest unit, for the reason Module 2 lesson 3 gave.
  • Golden file testing. Compilers and command line tools are tested by running them and comparing the output with a saved file. GCC's own test suite works exactly like these hidden tests.
  • Automated marking in this track. The graded exercises in every later module, and the Skill Test's build section, use the same judge as these ten problems.

Common mistakes

1. Printing a prompt.

printf("Enter two numbers: ");
scanf("%d %d", &a, &b);

No message anywhere, and it is helpful when a person is typing. A judge compares every character you print, so the prompt is part of your answer and your answer is wrong. Take prompts out before you submit.

2. Dropping the padding zero on money.

printf("%lld.%lld\n", taka, paisa);

No message, and it passes every test where the paisa is ten or more. A balance of 1200 taka and 5 paisa prints as 1200.5 instead of 1200.05. It is %02lld.

3. Printing the values before the read that changed them.

int first = scanf("%d %d", &a, &b);
int second = scanf("%d %d", &a, &b);
printf("%d %d %d\n", first, a, b);

No message, and the line is correct C. It reports the first read's count beside the second read's values, because both reads write into the same two boxes. Print each line before the next read runs.

4. Trying to trim a value to its field width.

printf("%.10u\n", n);

No message, and it does not do what the writer hoped. A width never cuts a value, and a precision on an integer pads it with zeros instead. If a statement says a field is ten wide, a value of eleven digits is meant to overflow it.

Brain teaser

Bob's answer to line-parser reports the first read's count beside the wrong pair of numbers.

#include <stdio.h>

int main(void)
{
    int a = 0;
    int b = 0;

    int first = scanf("%d %d", &a, &b);
    int second = scanf("%d %d", &a, &b);

    printf("%d %d %d\n", first, a, b);
    printf("%d %d %d\n", second, a, b);
    return 0;
}

On the input 1 2 3 it prints 2 3 2 and then 1 3 2. The second line is right and the first is wrong. Say where the 3 on the first line came from, and where the 1 went.

Then the harder half. Bob wants to fix it without declaring any new variable and without moving the two scanf calls. Say whether that is possible, and why.

Two reads, two boxes, and no more. Ask what is in those boxes at the moment the first printf runs, rather than at the moment the first scanf finished.

Problem 1: sum-and-productEasy

Kenji is testing a calculator's two simplest buttons, on numbers big enough that the second answer will not fit where the first one does.

Input. One line with two integers a and b.

Output. Two lines: the sum, then the product.

Constraints. -100000 <= a, b <= 100000.

Sample. Input 3 4 gives 7 then 12.

#include <stdio.h>

int main(void)
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);

    /* Two printf calls. The product does not fit in an int. */

    return 0;
}
Run in Compiler

Hint 1

The largest allowed product is ten billion. An int stops just past two billion.

Hint 2

Widen one side of the multiplication before it happens, then print the result with %lld.

Solution

The sum fits an int, so print it with %d and nothing more. The product needs a long long, and the multiplication itself has to happen in the wide type. Write (long long)a * b, with the cast on one operand rather than around the whole thing.

A cast around the whole expression, as in (long long)(a * b), computes the product in int first and then widens the wreckage. Both spellings pass the small tests, and only the first passes the largest one.

Problem 2: base-decoderEasy

Amara's config file writes a file permission in base 8 and a colour in base 16. Print both as decimal numbers.

Input. One line with a hexadecimal number then an octal number, with no prefixes.

Output. One line with both in decimal, separated by one space.

Constraints. Hex 0 to FFFFFF in either case, octal 0 to 7777777.

Sample. Input 1F 755 gives 31 493.

#include <stdio.h>

int main(void)
{
    unsigned int from_hex = 0;
    unsigned int from_octal = 0;
    scanf("%x %o", &from_hex, &from_octal);

    /* One printf. Both boxes already hold ordinary numbers. */

    return 0;
}
Run in Compiler

Hint 1

The conversion happened inside scanf. Nothing is left to convert.

Hint 2

One printf with two %u specifiers and a single space between them.

Solution

A base is a way of writing a number, not a property of the number. %x read the text as base 16 and %o read it as base 8, and what landed in each variable is an ordinary value. Printing it with %u writes it in base 10, and that is the whole program.

The variables are unsigned int rather than int because %x and %o are defined for unsigned values. The largest allowed hex value is well inside the range, so nothing overflows. Mixing the two up is a warning on a local build and silent on the Playground.

Problem 3: seat-planEasy

Kenji's exam hall has 12 rows per block and 8 seats per row. Read the blocks and the booked seats and print the three totals.

Input. One line with two integers: the number of blocks, then the seats already booked.

Output. Three lines: rows, capacity and free, each followed by one space and its number.

Constraints. 0 <= blocks <= 10000, 0 <= booked <= capacity. The numbers 12 and 8 appear once each, as named constants.

Sample. Input 3 71 gives rows 36, capacity 288, free 217.

#include <stdio.h>

int main(void)
{
    const int SEATS_PER_ROW = 8;
    const int ROWS_PER_BLOCK = 12;

    int blocks = 0;
    int booked = 0;
    scanf("%d %d", &blocks, &booked);

    /* Three printf calls. Every number in them comes from a name. */

    return 0;
}
Run in Compiler

Hint 1

Rows come first, capacity is built from rows, and free is built from capacity.

Hint 2

Two intermediate variables make the three lines read themselves. The largest capacity is 960000, well inside an int.

Solution

Multiply blocks by the rows constant to get the row count. Multiply that by the seats constant for the capacity, then subtract the booked seats. Three printf calls with %d and the words exactly as the statement writes them.

The judge reads your output and cannot see your constants, so the naming rule is on your honour. Write it once with the bare numbers, then count how many lines you would edit if the hall were rebuilt with nine seats a row. That count is the whole reason lesson 1 exists.

Problem 4: named-receiptMedium

Maria's till, with the VAT rate living in exactly one line. Read a quantity and a unit price in paisa.

Input. One line with two integers: the quantity, then the unit price in paisa.

Output. Three lines, each a word then an amount as whole taka, a full stop, and two digits of paisa.

Constraints. 1 <= quantity <= 100000, 1 <= unit price <= 10000000, VAT 15 percent with the fraction of a paisa dropped. No double.

Sample. Input 3 12000 gives Subtotal 360.00, VAT 54.00, Total 414.00.

#include <stdio.h>

int main(void)
{
    const long long VAT_PERCENT = 15;
    const long long PAISA_PER_TAKA = 100;
    const long long PERCENT_WHOLE = 100;

    long long quantity = 0;
    long long unit_paisa = 0;
    scanf("%lld %lld", &quantity, &unit_paisa);

    /* Three lines. %02lld is what makes five paisa print as 05. */

    return 0;
}
Run in Compiler

Hint 1

Everything is paisa until the last moment. The decimal point is a printf problem, not an arithmetic one.

Hint 2

Taka is the paisa divided by a hundred. The remaining paisa is the total minus the taka times a hundred.

Solution

The subtotal is the quantity times the unit price. The VAT is the subtotal times the percentage divided by a hundred, and the total is their sum. All three are long long, because the largest subtotal here is a thousand billion paisa.

Each line prints two numbers. The taka comes from an integer division by a hundred, and the paisa from the whole minus the taka times a hundred. The second one needs %02lld so that a value below ten prints its leading zero. One hidden test buys a single item at one paisa. The VAT works out to zero there, and every line is a fraction of a taka.

Problem 5: greet-nameMedium

Zara's sign-in desk has a name box nineteen letters wide, and one day somebody will type a longer name into it.

Input. At most one line holding one word with no spaces. It may be empty.

Output. Two lines: Hello, <name>! then read and what scanf returned.

Constraints. The word is 1 to 19 characters. Empty input returns -1 and greets an empty name.

Sample. Input Maria gives Hello, Maria! then read 1.

#include <stdio.h>

int main(void)
{
    char name[20] = {0};

    int read = scanf("%19s", name);

    /* Two lines: the greeting, then what scanf gave back. */

    return 0;
}
Run in Compiler

Hint 1

The greeting is one printf with a %s between the comma and the exclamation mark.

Hint 2

The second line prints the value already sitting in read. On empty input that value is -1 and the name is still empty.

Solution

Two printf calls and nothing else. The first writes Hello, , then the name with %s, then an exclamation mark. The second writes the word read, a space, and the count with %d.

Two hidden tests are the point of the problem. One sends a name of exactly 19 characters, which fills the boxes the starter declared and proves the 19 in the format was doing something. The other sends nothing at all, so scanf returns -1, the array is still all zeros, and %s prints nothing between the comma and the exclamation mark.

Problem 6: hex-octal-dumpMedium

Kenji is reading a device register and needs it in three bases, each pushed into the same ten wide field.

Input. One line with one integer n, written in decimal.

Output. Four lines: dec:, hex:, HEX: and oct:, each followed by n in a field of width 10.

Constraints. 0 <= n <= 4294967295.

Sample. Input 255 gives dec: 255 and three more lines.

#include <stdio.h>

int main(void)
{
    unsigned int n = 0;
    scanf("%u", &n);

    /* Four lines, four bases, one width. */

    return 0;
}
Run in Compiler

Hint 1

Four printf calls, differing in one letter each. The label is four characters and then the field begins.

Hint 2

Upper case X gives upper case digits. The width goes between the percent sign and the conversion letter.

Solution

Print the four labels as ordinary text and follow each with the same variable under a different conversion: %10u, %10x, %10X and %10o. There is no conversion to perform and no second variable to hold.

The hidden test at the top of the range is the one worth understanding. The octal writing of 4294967295 is eleven digits, wider than the field. That line comes out one character longer than the other three. A width is a minimum and never a maximum, and a program that tries to force ten characters is wrong.

Problem 7: in-rangeMedium

Zara's sensor is trusted only inside a band. Print the two facts and let a person read them.

Input. One line with three integers: the lowest allowed, the highest allowed, and the reading.

Output. Two lines, each 1 or 0: at least the lowest, then at most the highest.

Constraints. -1000000 <= lowest <= highest <= 1000000. No if and no &&.

Sample. Input 1 100 50 gives 1 then 1.

#include <stdio.h>

int main(void)
{
    int low = 0;
    int high = 0;
    int reading = 0;
    scanf("%d %d %d", &low, &high, &reading);

    /* Two lines, each a comparison printed with %d. No if anywhere. */

    return 0;
}
Run in Compiler

Hint 1

A comparison is an expression. Its value is 1 when it holds and 0 when it does not.

Hint 2

Put the comparison straight inside the printf, where a value is expected, with a %d for it.

Solution

Two printf calls, each with one %d. The first takes the comparison of the reading against the lowest allowed value, the second the comparison against the highest. Module 2 lesson 4 proved that each of those is a number, and nothing else is needed.

Both comparisons use "or equal", because a reading exactly on a bound is inside the band. Two hidden tests are exactly those cases, and a program written with strict comparisons passes everything else and fails both. Joining the two answers into one would need &&, which is Module 4, and the statement asks for two lines for that reason.

Problem 8: read-reportMedium

Report what a single read actually did: the count it returned, and the value in the variable afterwards.

Input. At most one line holding one token, either an integer or a word. It may be empty.

Output. Two lines: returned and the count, then value and the variable.

Constraints. An integer is between -1000000 and 1000000, a word is 1 to 20 letters, and the variable starts at 0.

Sample. Input twelve gives returned 0 then value 0.

#include <stdio.h>

int main(void)
{
    int amount = 0;

    int read = scanf("%d", &amount);

    /* Two lines. Print what scanf gave back, then what is in the box. */

    return 0;
}
Run in Compiler

Hint 1

Both values you need already exist. Nothing is calculated in this program.

Hint 2

Two printf calls with one %d each, and the words exactly as the statement writes them.

Solution

Print the word returned, a space and read, then the word value, a space and amount. The whole problem is that both numbers are already there. A program which throws the first one away cannot tell the two interesting cases apart.

Three hidden tests make the point. The input 0 gives a second line of value 0 with a first line of 1. The input twelve gives the same second line with a first line of 0, because the read failed and left the declaration's zero alone. Empty input gives -1, which is EOF, and the same untouched zero.

Problem 9: invoice-exactHard

Amara's shop prints an invoice roll and an auditor compares it with the till's own copy, character by character.

Input. Three lines, each with an item name, its quantity and its unit price in paisa.

Output. Eight lines: a header, the three items, a rule of 27 dashes, a subtotal row, a VAT row and a total row. The exact format strings are in the statement.

Constraints. A name is 1 to 12 characters. 0 <= quantity <= 9999, 0 <= unit price <= 99999. VAT is 15 percent of the subtotal in whole paisa, with the fraction dropped.

Sample. The three items rice 12 4500, oil 3 12000 and salt 7 250 give a subtotal of 91750 and a VAT of 13762.

#include <stdio.h>

int main(void)
{
    const int VAT_PERCENT = 15;
    const long long PERCENT_WHOLE = 100;

    char first[16] = {0};
    char second[16] = {0};
    char third[16] = {0};
    long long qty1 = 0;
    long long qty2 = 0;
    long long qty3 = 0;
    long long price1 = 0;
    long long price2 = 0;
    long long price3 = 0;
    scanf("%15s %lld %lld", first, &qty1, &price1);
    scanf("%15s %lld %lld", second, &qty2, &price2);
    scanf("%15s %lld %lld", third, &qty3, &price3);

    /* Eight printf calls, in the widths the statement gives. */

    return 0;
}
Run in Compiler

Hint 1

Six of the eight lines share one format string. Write that one first and get its three widths right.

Hint 2

The VAT row's label carries a number, so it cannot use %-12s. Build it from VAT %d%% and an empty field wide enough to reach the money column.

Solution

Compute a line total for each item, then the total quantity, the subtotal and the VAT, all in long long. Six of the rows use the same three field widths: twelve left aligned, then five, then ten. Getting that one format string right gets all six right.

The VAT row is the one that has to be built by hand. VAT 15% is seven characters and the other rows put seventeen characters before the money column, so an empty field of ten closes the gap. At the top of the constraints every field is exactly full. The subtotal row then runs its two numbers together with no space, and that is correct output rather than a bug.

Problem 10: line-parserHard

Bob's import tool reads pairs of numbers from a file that other people produce, and those people sometimes stop typing halfway.

Input. Between zero and six integers, separated by any whitespace, on any number of lines.

Output. Three lines, one per read: what scanf returned, then the two variables, in that order and at that moment.

Constraints. Each integer is 0 to 1000000. Both variables start at 0. When the input runs out, scanf returns EOF, which prints as -1.

Sample. Input 1 2 3 gives 2 1 2, then 1 3 2, then -1 3 2.

#include <stdio.h>

int main(void)
{
    int a = 0;
    int b = 0;

    int first = scanf("%d %d", &a, &b);
    /* Print first, a and b here, before the next read changes them. */

    int second = scanf("%d %d", &a, &b);
    /* Print second, a and b here. */

    int third = scanf("%d %d", &a, &b);
    /* Print third, a and b here. */

    return 0;
}
Run in Compiler

Hint 1

Three reads and two boxes. Each read writes over what the last one left.

Hint 2

The comments in the starter are in the right places. A printf after all three reads reports the last read's values three times.

Solution

Three printf calls, each with three %d specifiers, each sitting immediately after its own scanf. The order is the entire problem. The two boxes are a moving target, and a line printed later reports a different moment than the count beside it.

The interesting cases come from a half filled read. On the sample the second read finds one number, puts 3 in the first box, runs out, and returns 1. The second box still holds the 2 the first read left there. Once the input has run out every later read returns EOF and changes nothing, which is why the third line repeats the second line's pair.

Common doubts

  • Can I change the scanf line in a starter?

    You can, and there is no reason to. It is already the right format with the ampersands in place, and a judge problem is not where you want to discover lesson 4's traps.

  • Why do three problems print what scanf returned?

    Because that number is the only honest answer to "did the read work". Printing it is what you can do before Module 5 gives you a way to act on it.

  • My output looks right but the judge says wrong answer.

    Count the characters of the first differing line against the sample. It is almost always a missing padding zero, a space between two specifiers, or a prompt you forgot to remove.

  • Is an extra newline at the end a problem?

    No. The judge ignores trailing whitespace at the end of a line and at the end of the output. A missing newline in the middle is a different matter.

  • Which of these will the module test use?

    invoice-exact and read-report, the two named in the test's note. The other eight are practice and stay open.

Key takeaways

  • The Output section is the specification; the story only tells you which problem it was.
  • Every starter's scanf line is correct as given, and your work begins after it.
  • Money is counted in whole paisa and the decimal point is put back by printf.
  • A width is a minimum, so the largest allowed input is meant to fill or overflow its field.
  • A yes or no answer is a comparison printed with %d, with no if in sight.
  • Print a line before the next read runs, or you will report values that arrived later.

Next comes the module test, and then Module 4, where the operators that all ten of these problems worked around finally arrive.

Module test

Ten questions on this module. Pass at 70%, and you can take it as many times as you like.

Take the module test

End of lesson 6

Get every problem accepted, and the lesson is done.

0 of 10 problems accepted

Next: Module Test: Constants, Input and Output