Skip to content
ExamSpine

Lesson 6.10

Convert fields before use

Part 6: Errors, testing and filesReading, about 7 min2 exercises in this lesson

Java answers can't run on ExamSpine yet. You can still read Java, trace it, and put an answer's lines in order.

Convert fields before use

By the end of this you will be able to turn the text you read from a file into numbers before you add, compare or average them, and say what goes wrong when you forget.

Everything a program reads from a file is text, even a field that looks like 58. Text and numbers behave differently: you can add numbers, but "adding" text joins it, and text is compared letter by letter, not by size.

How it is asked

As with the other file lessons, no past paper has a file question yet. This lesson's skill is part of almost every file task that involves numbers, so it is usually one mark inside a bigger question, not a question of its own. It is the mark that is easiest to drop without noticing.

Key idea: A field is text until you convert it: int(...) in Python, Integer.parseInt(...) in Java.

Convert, then use

points.csv holds a name and the points scored, one player per line. Step through and watch points change from the text in fields to a number.

Text compares letter by letter

The bug that hurts most is the one with no error message. Comparing two fields while they are still text works, but it compares them as words in a dictionary, character by character, not as numbers.

So finding the biggest or smallest value, or sorting, with unconverted fields gives a wrong answer for some files and a right one for others. A test where the numbers have different numbers of digits, such as 9 and 10, catches it.

What each conversion forgives

The two languages are not equally strict about the text they convert.

  • Python's int(...) ignores spaces and the line end around the digits, so int("12\n") and int(" 7 ") both work. float(...) does the same for decimals.
  • Java's Integer.parseInt(...) does not: Integer.parseInt(" 7") throws a NumberFormatException. For decimals Java has Double.parseDouble(...), which, unlike parseInt, does ignore spaces around the number.

Both refuse text that is not a number at all, such as a header word: int("seconds") raises ValueError, and Integer.parseInt("seconds") throws NumberFormatException. So skip the header before you convert, and when a file might have bad lines, convert inside a try, as in the lesson on catching exceptions.

How it is marked

An exam-style question of our own, marked one mark for each point a correct answer must show, as IB computer science markschemes mark code.

Now try it yourself on the questions below.

Exercise 6.10.16.10.1 · Write itFastest lap

A running club saves lap times in laps.csv. Write a program that finds the fastest lap and the total time.

  1. The first line is a header, name,seconds. Every other line is one lap: the runner's name, a comma, then the lap time in whole seconds, such as Bo,58.
  2. Print Fastest: , the name of the runner with the smallest time, in , that time, and seconds, such as Fastest: Bo in 58 seconds.
  3. If two laps share the smallest time, the one nearer the top of the file is the fastest.
  4. Then print Total: , the sum of all the times, and seconds.
  5. There is at least one lap. Times are whole numbers from 1 to 999, written with digits only, and no field has spaces around it. The last line may or may not end with a line end.

Your program is run several times, each time in a folder that holds only the files shown for that run.

Running Java here comes later. You can put this answer's lines in order instead. You can still write your Java answer (it stays while this page is open) and compare it with our worked solution. Or try this exercise in Python.

Examples

Your program is run 9 times: the 2 examples below, and 7 hidden ones that check the rules above. Only what it prints is checked. Each run starts in an empty folder that holds only the files shown for it.

  • three laps, the fastest in the middle (rules 2 and 4)

    You type

    Nothing

    It prints

    Fastest: Bo in 58 seconds
    Total: 183 seconds

    Files in its folder

    laps.csv
    name,seconds
    Ana,64
    Bo,58
    Cy,61
  • times with different numbers of digits: 9 is less than 10 (rules 2 and 5)

    You type

    Nothing

    It prints

    Fastest: Bo in 9 seconds
    Total: 31 seconds

    Files in its folder

    laps.csv
    name,seconds
    Ana,12
    Bo,9
    Cy,10
solution.pySolution.java

Exercise 6.10.26.10.2 · Answer itTop score as text

The file scores.csv holds three lines: Ana,85, then Bo,100, then Cy,9. Scores are whole numbers from 1 to 100. This program (in Java, the lines are inside a main that throws IOException, with the imports it needs) is meant to print the name of the student with the highest score. It runs with no error.

best_name = ""
best_score = ""
with open("scores.csv") as f:
    for raw in f:
        fields = raw.rstrip("\n").split(",")
        if fields[1] > best_score:
            best_name = fields[0]
            best_score = fields[1]
print(best_name)
String bestName = "";
String bestScore = "";
try (BufferedReader f = new BufferedReader(new FileReader("scores.csv"))) {
    String line = f.readLine();
    while (line != null) {
        String[] fields = line.split(",");
        if (fields[1].compareTo(bestScore) > 0) {
            bestName = fields[0];
            bestScore = fields[1];
        }
        line = f.readLine();
    }
}
System.out.println(bestName);

(a) State the name the program prints. [1]

(b) Explain why it does not print Bo. [2]

(c) State the change that makes the program correct. [1]

[4]

Report a problem with this page