CodeRigor

LESSON

Read what the user types

Read the lines a user types from standard input, turn text into a number with Number and build programs that prompt, read, compute and print.

So far every value was written into the program. A useful program takes information from the person running it and responds to what they type. The person running a program is called its user, and what they give the program is its input.

Two lines that read everything typed

A console program receives its input as text, through a channel called standard input. Normally standard input is the keyboard.

In Node, these two lines read everything the user types. You will write the same two lines in every program that reads input:

JavaScript
const fs = require("node:fs");
const lines = fs.readFileSync(0, "utf8").split("\n");

console.log(`Hello, ${lines[0]}!`);

If the user types Ada, the program prints Hello, Ada!.

Here is what each part does, in the order Node carries it out:

  • require("node:fs") asks Node for a set of tools that comes with it. The set named fs reads and writes files, and Node treats what the user types as one more file to read. The first line gives that set of tools the name fs.
  • fs.readFileSync(0, "utf8") reads all of standard input and produces it as one string. The 0 is the number Node uses for standard input, and "utf8" says that you want the result as text.
  • .split("\n") cuts that string into pieces, one piece for each typed line. Inside a string, \n stands for the end of a line.
  • The result is a list of strings, which the second line names lines. A list of values is called an array, and each value in it is an element.

To pick one value out of an array, write its position in square brackets after the name. Positions count from zero: lines[0] is the first line the user typed, lines[1] is the second and lines[2] is the third.

You do not need to remember every detail of those two lines yet. You need to know what they leave behind: an array named lines that holds the typed lines, in order.

JavaScript
const typed = "Ada\nLovelace";   // stands in for two typed lines
const lines = typed.split("\n");
console.log(lines[0]);
console.log(lines[1]);

This example has no real input, so that it can run on the page: the string typed stands in for what a user would type. It prints Ada and then Lovelace.

Running programs that read input

The first example above has no Edit & run button, because the button supplies no input. Run it in the JavaScript playground instead:

  1. Copy the program into the editor.
  2. Open Standard input below the output and type what the user would type, one answer per line. For this program, type Ada.
  3. Press Run.

On your own computer, type node greet.js, then type the answers, each followed by Enter. When you have typed everything, press Ctrl+D on a new line (on Windows, Ctrl+Z and then Enter). That tells the program the input is complete, and only then does it carry on and print its reply. On Windows each typed line can also end with an extra invisible character. If a piece of typed text prints oddly there, write lines[0].trim(): .trim() removes spaces and invisible characters from both ends of a string. Number ignores them without help.

That is the honest limit of these two lines: the program reads all of its input first and answers afterwards. A program that replies after each typed line needs a way to wait in the middle of its work. Node does that with a technique that a later unit of this course builds up to. Everything else in this lesson stays true when you get there.

Say what to type before you read

Since the reading happens in one go, tell the user what to type before the program reads. A message that asks the user for input is called a prompt.

JavaScript
console.log("Type your name and press Enter.");

const fs = require("node:fs");
const lines = fs.readFileSync(0, "utf8").split("\n");

console.log(`Hello, ${lines[0]}!`);

Statements run from top to bottom, so the prompt appears first. Then the program waits at readFileSync until the input is complete, and after that it prints the greeting. With Ada as the input, the output is:

Text
Type your name and press Enter.
Hello, Ada!

What you read is always text

Every element of lines is a string, even when the user types digits. That matters as soon as you calculate.

JavaScript
const answer = "36";
console.log(answer + 1);
console.log(answer + answer);

This prints 361 and 3636. When one side of + is a string, + joins text instead of adding. The string "36" is two characters, a 3 and a 6. It is not the number thirty-six. JavaScript gives no error message here, so this mistake shows up only as a strange result.

Turn text into a number

The function Number takes a string that spells a number and returns that number.

JavaScript
const answer = "36";
const age = Number(answer);
console.log(age + 1);
console.log(Number("2.5") * 2);

This prints 37 and 5. A function call can produce a value: programmers say the function returns it. Changing a value from one type to another is called converting it.

You can convert in the same statement that picks the line:

JavaScript
const age = Number(lines[1]);

Read that from the inside out: lines[1] is the second typed line, Number converts it, and the name age refers to the result.

Step through this program to see the text become a number.

JavaScript
const typed = "Ada\n36";   // stands in for two typed lines
const lines = typed.split("\n");
const name = lines[0];
const age = Number(lines[1]);
console.log(`${name} will be ${age + 1}.`);
From typed text to a number you can calculate with
start / 5 ⇄ code
The user types two lines. Both arrive as strings. Number converts the second one, and only then does + 1 mean arithmetic.
From typed text to a number you can calculate with
The user types two lines. Both arrive as strings. Number converts the second one, and only then does + 1 mean arithmetic.

Prompt, read, compute, print

Most small programs have the same four-part shape.

Prompt, read, compute, print
start / 4
Say what to type, read the typed lines as text, convert and calculate, then show the result. Longer programs repeat this shape.
Prompt, read, compute, print
Say what to type, read the typed lines as text, convert and calculate, then show the result. Longer programs repeat this shape.

Here is a complete program in that shape. It works out the cost of some tickets.

JavaScript
// Prompt
console.log("Type the ticket price, then the number of tickets, each on its own line.");

// Read
const fs = require("node:fs");
const lines = fs.readFileSync(0, "utf8").split("\n");

// Compute
const price = Number(lines[0]);
const count = Number(lines[1]);
const cost = price * count;

// Print
console.log(`${count} tickets cost ${cost.toFixed(2)}`);

Try it in the playground with this standard input:

Text
4.5
3

The output is:

Text
Type the ticket price, then the number of tickets, each on its own line.
3 tickets cost 13.50

Three mistakes you will meet

Text that does not spell a number. Number cannot convert "three", and it does not stop the program. It returns a special value that prints as NaN, which is short for "not a number". Any arithmetic that uses NaN gives NaN again.

JavaScript
const count = Number("three");
console.log(count);
console.log(count * 4.5);

This prints NaN twice.

A line that was never typed. Asking an array for a position it does not have gives the special value undefined, which means "there is nothing here". Number(undefined) is NaN.

JavaScript
const typed = "4.5";   // the user typed one line, not two
const lines = typed.split("\n");
console.log(lines[1]);
console.log(Number(lines[1]) * 2);

This prints undefined and then NaN. When you see NaN or undefined in your output, check two things: that each position in square brackets matches the order in which the lines are typed, and that the input has as many lines as the program reads. Remember that the first line is lines[0], not lines[1].

Leaving out the first reading line. This one does give an error message:

JavaScript
const lines = fs.readFileSync(0, "utf8").split("\n");
console.log(lines[0]);
Text
/work/main.js:1
const lines = fs.readFileSync(0, "utf8").split("\n");
              ^

ReferenceError: fs is not defined
    at Object.<anonymous> (/work/main.js:1:15)

ReferenceError means an unknown name, and the ^ points at fs. The name fs exists only after the line const fs = require("node:fs"); has run, so that line must come first.

What you can do now

You can read the lines a user types, pick each one out of the array by its position, convert text to a number and write programs in the prompt, read, compute, print shape. In the exercises you will predict what conversions print, then write a program that greets its user by name.

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

Watch & read

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

Starts at chapter 5, 'Type conversion' (39:09), about five and a half minutes on changing a value from one type to another, such as text to a number. The chapter before it, 'Accept user input', is about input in a web browser, which works differently from Node; this lesson's two reading lines take its place.