Input and Output

Every program so far had its numbers written into its text. To try another number you had to edit the program. In this lesson a program takes its values from outside while it runs, and prints its results in tidy lines: money with two decimal places, and tables in columns.

A program that waits

This program works out the cost of some tickets at 12 pounds each. The number of tickets is not in the program.

#include <iostream>

int main() {
    int tickets = 0;
    std::cin >> tickets;
    std::cout << tickets << " tickets cost " << tickets * 12 << " pounds.\n";
}
3
3 tickets cost 36 pounds.

The text a program receives while it runs is its input. std::cin is the input, as std::cout is the output.

Read std::cin >> tickets; as "take the next value from the input and store it in tickets". The arrows >> point from std::cin towards the variable, the direction the value travels. With std::cout the arrows point the other way.

When the program reaches that statement it waits until a value is available. Then it stores the value and goes on to the next statement. So the last line can use tickets, and it prints 36 because the input was 3.

The variable still gets a starting value, int tickets = 0;, as every variable should. The read then replaces it.

The value is stored as the type of the variable. The same statement with a double variable reads a number with a fraction.

#include <iostream>

int main() {
    double litres = 0.0;
    std::cin >> litres;
    std::cout << "Two bottles hold " << litres * 2 << " litres.\n";
}
1.75
Two bottles hold 3.5 litres.

A read into an int or a double expects a number. If the input holds something else there, such as the word three, the read fails and the variable holds nothing you can use. Module 4 shows how a program can find out that a read failed. Until then, give each program the kind of input it expects.

Where input comes from in the lab

On the lab page there is an Input box next to the editor. Type there what the program should receive, then press Run.

Everything in the box is available to the program from the start. The program still takes it one read at a time, in order, but it never has to wait for you to type.

Many programs print a question before they read. A short text that asks for input is called a prompt.

#include <iostream>

int main() {
    int tickets = 0;
    std::cout << "How many tickets? ";
    std::cin >> tickets;
    std::cout << "That is " << tickets * 12 << " pounds.\n";
}
3
How many tickets? That is 36 pounds.

Look at the output closely. There are two things to notice.

This is also how a program is tested by a machine. Each check in the lab puts its own text in the input, runs your program, and compares what it printed with the expected output, character by character. From this module on, most tasks say exactly what the output must be for a given input. A missing space or a missing \n counts as a difference.

Several values

One statement can read several values. Each >> takes the next one.

#include <iostream>

int main() {
    int hours = 0;
    int minutes = 0;
    std::cin >> hours >> minutes;
    std::cout << hours * 60 + minutes << " minutes\n";
}
2 15
135 minutes

The first >> stores 2 in hours. The second stores 15 in minutes.

How does >> know where one value stops and the next begins? Before it reads a value, >> skips any spaces and line ends in front of it. Then it takes characters for as long as they can belong to the value, and stops. So values may be separated by one space, by several, or by line ends. It makes no difference.

The next program reads the same two values with two statements, and its input has them on two lines, the second with spaces in front.

#include <iostream>

int main() {
    int hours = 0;
    int minutes = 0;
    std::cin >> hours;
    std::cin >> minutes;
    std::cout << hours * 60 + minutes << " minutes\n";
}
2
    15
135 minutes

std::cin >> hours >> minutes; and the two separate statements do the same thing. A read continues where the read before it stopped, whichever statement it is in.

The order of the reads is the order of the values in the input. If the program reads hours first, the first number in the input is the hours.

Words and whole lines

>> can fill a std::string as well. It follows the same rule: skip spaces and line ends, then take characters until the next space or line end. For text that means one word.

#include <iostream>
#include <string>

int main() {
    std::string city;
    std::cin >> city;
    std::cout << "City: " << city << "\n";
}
New York
City: New

The read stopped at the space. York was not thrown away. It is still in the input, and the next read would get it.

To read text that may contain spaces, read the whole line. That is a different call.

#include <iostream>
#include <string>

int main() {
    std::string city;
    std::getline(std::cin, city);
    std::cout << "City: " << city << "\n";
}
New York
City: New York

std::getline(std::cin, city); has two values in its parentheses: where to read from, and the variable to fill. It takes every character up to the end of the line, spaces included, and stores them in city. It also removes the line end from the input, but does not store it.

Statement What it reads
std::cin >> word; skips spaces and line ends, then one word
std::getline(std::cin, line); everything up to the end of the line, skipping nothing

The line end that stays behind

The two ways of reading do not mix as you might expect. This program reads a number, then a line.

#include <iostream>
#include <string>

int main() {
    int count = 0;
    std::string fruit;
    std::cin >> count;
    std::getline(std::cin, fruit);
    std::cout << count << " x <" << fruit << ">\n";
}
3
Red apples
3 x <>

fruit is empty. To see why, look at the input as the program gets it: one run of characters, in which every line end is a character too. Here each line end is written as ⏎.

3⏎Red apples⏎

std::cin >> count; takes the 3 and stops. It does not take the line end after it. What is left is this.

⏎Red apples⏎

std::getline reads up to the next line end, and the next line end is the very first character. So it reads a line with nothing in it. Red apples is still waiting, unread.

The repair is to skip the spaces and line ends before reading the line. std::ws does that when it is given to >>.

#include <iostream>
#include <string>

int main() {
    int count = 0;
    std::string fruit;
    std::cin >> count;
    std::getline(std::cin >> std::ws, fruit);
    std::cout << count << " x <" << fruit << ">\n";
}
3
Red apples
3 x <Red apples>

Read std::cin >> std::ws as "skip forward to the next character that is not a space or a line end". The getline then starts at the R.

The rule to remember: a getline that comes after a >> needs std::ws. A getline that comes first in the program, or straight after another getline, does not need it, because getline removes the line end it stopped at.

#include <iostream>
#include <string>

int main() {
    std::string fruit;
    std::string shop;
    std::getline(std::cin, fruit);
    std::getline(std::cin, shop);
    std::cout << fruit << " from " << shop << "\n";
}
Red apples
Hill Farm
Red apples from Hill Farm

Naming the headers you use

Until now the #include lines were part of the frame, given to you. From this module they are yours to write.

C++ itself is small. Most of what you use, std::cout and std::string included, comes from the standard library: ready-made code that is delivered with every C++ compiler. The library is divided into headers. A line such as #include <iostream> tells the compiler to read one header before it reads your program. After that, the names from that header are known.

Header What it gives you
<iostream> std::cin, std::cout, std::ws
<string> std::string, std::getline
<iomanip> std::setprecision, std::setw: the formatting in the next two sections

The std:: in front of each name says that the name belongs to the standard library.

A name whose header is missing is a name the compiler has never seen. This program has no #include line at all.

int main() {
    std::cout << "Hello\n";
}

The compiler answers with a message like this one.

your_program.cpp:2:5: error: use of undeclared identifier 'std'

It is the same kind of message as for a misspelt name. When the name in the message is spelt correctly and comes from the library, look at your #include lines first.

Three habits keep this from happening.

Printing money

std::cout prints a double in the shortest form that shows its value, up to six digits. For money that is not what you want.

#include <iostream>

int main() {
    double price = 4.5;
    double third = 20.0 / 3;
    std::cout << price << "\n";
    std::cout << third << "\n";
}
4.5
6.66667

A price should read 4.50. Two names arrange that: std::fixed, which comes with <iostream>, and std::setprecision, which needs <iomanip>. They are sent to std::cout with << like a value, but they print nothing. They change how the values after them are printed.

#include <iomanip>
#include <iostream>

int main() {
    double price = 4.5;
    double third = 20.0 / 3;
    int count = 3;
    std::cout << std::fixed << std::setprecision(2);
    std::cout << price << "\n";
    std::cout << third << "\n";
    std::cout << count << "\n";
    std::cout << std::setprecision(1);
    std::cout << third << "\n";
}
4.50
6.67
3
6.7

Notice four things in the output.

Only the printing changes. The variable third holds the same value throughout.

Columns

To line values up under one another, each value must take the same number of characters, whatever its length. std::setw(8), from <iomanip>, prints the next value in a space eight characters wide. The name is short for "set width". If the value is shorter than the width, spaces fill the rest.

#include <iomanip>
#include <iostream>

int main() {
    std::cout << std::setw(6) << 42 << "|\n";
    std::cout << std::setw(6) << 7 << 7 << "|\n";
}
    42|
     77|

In the first line, 42 is two characters, so four spaces come before it. The value sits at the right of its space.

The second line shows how std::setw differs from std::setprecision: it applies to one value only. The first 7 is printed six wide. The second 7 has no width, so it follows directly. Write std::setw again before every value that needs a width.

Numbers read best at the right of a column, and names at the left. std::left and std::right choose the side. They come with <iostream>. Unlike std::setw, these two stay on until the other one is sent.

#include <iomanip>
#include <iostream>

int main() {
    std::cout << std::fixed << std::setprecision(1);
    std::cout << std::left << std::setw(12) << "Leeds" << std::right << std::setw(7) << 272.5 << "\n";
    std::cout << std::left << std::setw(12) << "Southampton" << std::right << std::setw(7) << 112.0 << "\n";
    std::cout << std::left << std::setw(12) << "Bath" << std::right << std::setw(7) << 97.4 << "\n";
}
Leeds         272.5
Southampton   112.0
Bath           97.4

Each line does the same four things: switch to the left, print a name twelve wide, switch to the right, print a number seven wide. The names start under one another and the numbers end under one another.

Count the characters when a table looks wrong. Southampton has eleven letters, so one space fills its column of twelve. A value longer than its width is not cut short. It is printed in full and pushes the rest of the line to the right, so choose a width larger than the longest value.