Assignment 5 — Pointers, and functions that change your variables

Four small programs where a function is handed the address of a variable instead of its value — the swap from Assignment 3 that could not work, working, and functions that hand back more than one answer.

Due Oct 7, 2026

A3’s swap.c compiled clean and swapped nothing, and it ended: the tool that fixes it is week 9. It is week 6, and here it is. A function that is given the address of a variable can change the variable itself, not a copy of it — which is also how one function can hand back two answers.

The reading for the week is [DIS] 2.2 — C’s Pointer Variables and [DIS] 2.3 — Pointers and Functions. Quiz 5 on Tuesday is on it.

You will hand in five files: order.c, minmax.c, divide.c, readnum.c and notes.txt — and calc.c, if you do the optional step 6.

If the week runs out, do order.c first

Every other program here makes the same move it does — pass an address, then change what is at it — so it is the one that makes the rest quick.

Every program compiles with gcc -Wall and no warnings. Every function you write gets the design recipe’s one-line comment above it. Every program also gets at least one assert of your own, beside the ones given.

  1. order.c — a swap that decides. Write void order(int * a, int * b). If the value at a is larger than the value at b, swap them, so the smaller one always ends up in the first variable. Then, in the same file, write void sort3(int * a, int * b, int * c), which puts three variables in increasing order by calling order three times. Your main:

    int main() {
        int x = 8;
        int y = 3;
        order(&x, &y);
        assert(x == 3);
        assert(y == 8);
        order(&x, &y);
        assert(x == 3);
        assert(y == 8);
    
        int p = 9;
        int q = 2;
        int r = 5;
        sort3(&p, &q, &r);
        assert(p == 2);
        assert(q == 5);
        assert(r == 9);
        printf("all examples passed\n");
    }

    Done when it prints all examples passed.

  2. minmax.c — two answers from one function. Write void min_max(int arr[], int n, int * min, int * max), which stores the smallest of the n values in *min and the largest in *max. Your main:

    #define SIZE 4
    
    int main() {
        int values[SIZE] = {4, -2, 9, 0};
        int low;
        int high;
        min_max(values, SIZE, &low, &high);
        assert(low == -2);
        assert(high == 9);
    
        int cold[SIZE] = {-5, -1, -9, -3};
        min_max(cold, SIZE, &low, &high);
        assert(low == -9);
        assert(high == -1);
        printf("all examples passed\n");
    }

    Done when it prints all examples passed. The second array is all negative on purpose: it is the case a function that starts from 0 gets wrong.

  3. divide.c — an answer, and whether there is one. Write int divide(int a, int b, int * quotient, int * remainder). When b is 0 it returns 0 and leaves both variables alone. Otherwise it stores a / b in *quotient and a % b in *remainder, and returns 1. Your main:

    int main() {
        int q = 0;
        int r = 0;
        assert(divide(17, 5, &q, &r) == 1);
        assert(q == 3);
        assert(r == 2);
        assert(divide(7, 0, &q, &r) == 0);
        assert(q == 3);
        assert(r == 2);
        printf("all examples passed\n");
    }

    Done when it prints all examples passed. The last two asserts check that dividing by zero left the earlier answers where they were.

  4. readnum.c — scanf, from the inside. Write int read_number(int * out), which reads one number with scanf and puts it in the variable out points to. It returns 1 if it read a number and 0 if it could not. You need one fact for this: scanf returns how many values it read, so 1 means it got the number. Your main reads numbers until there are none left:

    int main() {
        int n;
        int count = 0;
        int total = 0;
        while (read_number(&n)) {
            count = count + 1;
            total = total + n;
        }
        printf("%d numbers, total %d\n", count, total);
    }

    Make a file numbers.txt holding 4 8 15 16 23 42, then run

    ./readnum < numbers.txt

    The < hands the file to your program as if you had typed it. Done when it prints 6 numbers, total 108.

  5. notes.txt — three short answers.

    1. A3’s swap compiled clean and changed nothing. In two or three sentences: what did it actually swap, and what does the swap inside your order have that it did not?
    2. Inside sort3 the calls are order(a, b), with no &. Why not? Then put an & in front of each, compile, and paste the first line gcc prints.
    3. Every scanf you had written before this week had an &. The one in read_number has none. Why?
  6. calc.c — optional: finish the calculator. This step is optional and not needed for full marks. Finish the calculator from Class 12, every stage on that page: * and / before + and -, the two error messages, and reading expressions until there are none left. Make a file exprs.txt holding these seven lines:

    12+34
    12+34-5+100
    2+3*4
    10-2*3
    100/7*7
    7/0
    12+

    then run

    ./calc < exprs.txt

    Done when it prints these seven lines:

    46
    141
    14
    4
    98
    cannot divide by zero
    missing number