CodeRigor

LESSON

Read what the user types

Prompt for a line of input, read it, turn text into a number, and write programs that ask, read, compute and print.

So far every value in your programs was written into the program itself. A program becomes far more useful when the person running it, the user, can give it values while it runs. What the user types is called input, in the same way that what the program shows is called output.

io.read reads one line

io.read("l") waits for the user to type a line and press Enter. It then hands the typed text back to your program as a string. A function that hands a value back is said to return it, and you can store the returned value in a variable:

Lua
print("What is your name?")
local name = io.read("l")
print("Hello, " .. name .. "!")

io is Lua's collection of input and output functions, read is one of them, and the argument "l" (a lower-case letter L, for "line") asks for one whole line. If the user types Ada and presses Enter, the screen shows:

Text
What is your name?
Ada
Hello, Ada!

The second line is what the user typed. The other two were printed by the program.

Ask the question on the same line

A question that tells the user what to type is called a prompt. print always ends its line, so the answer above appears underneath the question. The function io.write shows text without ending the line, so the user's answer follows the question on the same line:

Lua
io.write("What is your name? ")
local name = io.read("l")
print("Hello, " .. name .. "!")
Text
What is your name? Ada
Hello, Ada!

Notice the space after the question mark, inside the string. Without it the screen would show What is your name?Ada. From now on this unit uses io.write for prompts and print for everything else.

Running programs that read input

The examples above have no Edit & run button, because a lesson page has nobody to type the answers. To run a program that reads input, open the Lua playground, paste the program in, and type the user's answers into the Standard input box, one answer per line, before you press run. ("Standard input" is the technical name for what a program reads from the keyboard.)

One difference from a real keyboard: the playground hands your lines to the program without showing them, so the output there reads What is your name? Hello, Ada!. On your own computer you would see the typed answer and a new line after the prompt, as in the sessions shown in this lesson.

What io.read returns is always text

Even when the user types digits, io.read("l") returns a string. Typing 36 gives the two-character text "36", not the number thirty-six. The function type tells you what kind of value you have:

Lua
local typed = "36"     -- stands in for what the user typed
print(type(typed))
print(typed .. 1)

This prints string and then 361: joining the text 36 and a 1. In examples like this one, a first line such as local typed = "36" stands in for the user's typing, so that the example can run on the page.

Turn text into a number

The function tonumber takes a string and returns the number it spells:

Lua
local typed = "36"     -- stands in for what the user typed
local age = tonumber(typed)
print(type(age))
print(age + 1)

This prints number and then 37. Step through the diagram: the variable typed keeps its text, and age gets a new value of a different kind.

Text in, number out
start / 4 ⇄ code
tonumber does not change typed. It returns a new value, a number, and the assignment gives that number the name age.
Text in, number out
tonumber does not change typed. It returns a new value, a number, and the assignment gives that number the name age.

tonumber("3.5") returns the float 3.5. When the text does not spell a number, as in tonumber("abc"), it returns nil, Lua's "nothing". You will see below what that leads to.

You may have noticed that Lua sometimes converts for you: "36" + 1 is 37. Do not rely on it. It does not happen when you compare values, which is the subject of the next lesson, and a program is easier to follow when each variable holds one known kind of value. The habit to learn is: convert once, right after reading.

Reading and converting are usually written as one line, with one call inside the other:

Lua
io.write("How old are you? ")
local age = tonumber(io.read("l"))

Lua works from the inside out: first io.read("l") returns the typed text, then tonumber turns that text into a number, and age refers to the number. Count the brackets: two opened, two closed.

The shape of an interactive program

Most small console programs have the same shape: ask, read, convert, calculate, print. (A console is a text-only window where a program prints lines and the user types lines.)

Lua
io.write("Width in metres? ")
local width = tonumber(io.read("l"))
io.write("Length in metres? ")
local length = tonumber(io.read("l"))

local area = width * length

print("Area: " .. area .. " square metres")

With the answers 3 and 4 the session is:

Text
Width in metres? 3
Length in metres? 4
Area: 12 square metres
Prompt, read, convert, compute, print
start / 5
Each question repeats the first three boxes. The calculation happens once every value has been read and turned into a number.
Prompt, read, convert, compute, print
Each question repeats the first three boxes. The calculation happens once every value has been read and turned into a number.

Text that stays text needs no conversion. A name is read with io.read("l") alone.

Three errors you will meet

The user types something that is not a number. Suppose the answer to the age question is abc:

Lua
io.write("How old are you? ")
local age = tonumber(io.read("l"))
print("Next year: " .. age + 1)
Text
/usr/bin/lua: solution.lua:3: attempt to perform arithmetic on a nil value (local 'age')
stack traceback:
	solution.lua:3: in main chunk
	[C]: in ?

The message names line 3 and the variable age. The mistake happened earlier, though: tonumber("abc") returned nil on line 2, and the program only stopped when line 3 tried to add 1 to nothing. When a message says a variable is nil, look back to where that variable got its value. (Programs in this unit may assume that the user types a number when asked for one.)

The program reads more lines than the user typed. When there is no more input, io.read("l") returns nil instead of text. A program that asks for a name and then a town, but is given only one line of input, fails like this:

Text
/usr/bin/lua: solution.lua:5: attempt to concatenate a nil value (local 'town')

In the playground and in the exercises, this message usually means your program called io.read more often than there were lines of input, or that you left the Standard input box empty.

A missing bracket. With one call inside another it is easy to drop a closing bracket:

Lua
local age = tonumber(io.read("l")
print(age)
Text
solution.lua:2: ')' expected (to close '(' at line 1) near 'print'

Lua reports line 2, because that is where it noticed that something was missing: it reached print while still waiting for a ). The words in brackets tell you where the real problem is: the ( that was never closed is on line 1. When a message says something was "expected", look at the end of the line before as well.

What you can do now

You can prompt with io.write, read a line with io.read("l"), turn it into a number with tonumber, and write programs with the shape ask, read, convert, compute, print. In the exercises you will predict the output of programs with stand-in input and then write a short conversation with the user.

Next: make decisions with if, elseif and else, so that a program can respond differently to different answers.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →