15. Getting input — Homework solutions

The .go solution files are in exercises/15/homework/solutions/.

Problem 1 — Greet by name

Problem. Prompt, read a name, greet with an exclamation mark.

How to think about it. Make the reader, print the prompt, read the line, trim it, then print the greeting. The exclamation mark goes inside the string, after the variable.

Worked solution.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("First name: ")
    text, _ := reader.ReadString('\n')
    name := strings.TrimSpace(text)

    fmt.Println("Hello, " + name + "!")
}

Common mistakes.

  • Forgetting strings.TrimSpace. The line ending stays in the name, so the ! lands on the line below.
  • Forgetting the trailing space in the prompt. "First name:" jams the cursor against the colon; "First name: " leaves room.
  • Writing "\n" instead of '\n'. ReadString wants one character, in single quotes, and Go stops with a cannot use error on the double-quoted form.

Problem 2 — Sum of two

Problem. Read two numbers; print a + b = c.

How to think about it. Two prompts, two reads, each one trimmed and converted with strconv.Atoi. The first read declares text with := and the second one reuses it with =. Build the output with fmt.Printf.

Worked solution.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("First number:  ")
    text, _ := reader.ReadString('\n')
    a, _ := strconv.Atoi(strings.TrimSpace(text))

    fmt.Print("Second number: ")
    text, _ = reader.ReadString('\n')
    b, _ := strconv.Atoi(strings.TrimSpace(text))

    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
}

Typing 3 and 4, the output is:

First number:  3
Second number: 4
3 + 4 = 7

Common mistakes.

  • Skipping the conversion. The values stay strings, so a + b joins them instead of adding: "3" + "4" is "34", not 7.
  • Skipping strings.TrimSpace. Each strconv.Atoi then sees the line ending and gives 0, so the output is 0 + 0 = 0.
  • Writing text, _ := reader.ReadString('\n') for the second read. Go stops with no new variables on left side of :=.
  • Writing a := strconv.Atoi(...) with one name. Go stops with assignment mismatch: 1 variable but strconv.Atoi returns 2 values.

Problem 3 — Years to retirement

Problem. Compute 65 - age and print a labelled sentence.

How to think about it. Prompt, read, trim, convert, subtract, print. Mind the order: 65 - age, not age - 65.

Worked solution.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Your current age: ")
    text, _ := reader.ReadString('\n')
    age, _ := strconv.Atoi(strings.TrimSpace(text))

    yearsLeft := 65 - age
    fmt.Printf("You have %d years until retirement.\n", yearsLeft)
}

Common mistakes.

  • Doing age - 65, which prints a negative for everyone under 65. Subtraction is not commutative — order matters.
  • Reading the result for bad input as an age. Typing abc makes age 0, so the program says You have 65 years until retirement. and shows no sign that anything went wrong.

Challenge — BMI

Problem. Prompt for height and weight (decimals), compute BMI, print it to one decimal place.

How to think about it. Two prompts, two reads, both through strconv.ParseFloat because the values have decimal points. weight / (height * height) gives a float64; %.1f shows one digit after the decimal point.

Worked solution.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Height in metres (e.g. 1.78): ")
    text, _ := reader.ReadString('\n')
    height, _ := strconv.ParseFloat(strings.TrimSpace(text), 64)

    fmt.Print("Weight in kg (e.g. 72.5):     ")
    text, _ = reader.ReadString('\n')
    weight, _ := strconv.ParseFloat(strings.TrimSpace(text), 64)

    bmi := weight / (height * height)
    fmt.Printf("BMI: %.1f\n", bmi)
}

Typing 1.78 and 72.5, the output is:

Height in metres (e.g. 1.78): 1.78
Weight in kg (e.g. 72.5):     72.5
BMI: 22.9

Common mistakes.

  • Using strconv.Atoi instead of strconv.ParseFloat. Heights like 1.78 are not whole numbers, so strconv.Atoi gives 0. Dividing an int by an int zero stops the program with panic: runtime error: integer divide by zero.
  • Typing letters for the height. strconv.ParseFloat gives 0, and the BMI prints as +Inf, Go's way of showing a float64 divided by zero.
  • Forgetting the parentheses in height * height. Without them, weight / height * height runs left to right: divide by height, then multiply by it again — the heights cancel and you get weight back.
  • Entering height in centimetres (like 178) instead of metres (1.78). BMI uses metres, as the prompt says.

Done?

Every Part 3 chapter is done. The mini-project — the Character Sheet — uses everything from chapters 11 to 15.