1.5 — Introduction to iostream: cout, cin, and endl

1.5 — Introduction to iostream: cout, cin, and endl

In this lesson, we’ll talk more about std::cout, which we used in our Hello world! program to output the text Hello world! to the console. We’ll also explore how to get input from the user, which we will use to make our programs more interactive.

The input/output library

The input/output library (io library) is part of the C++ standard library that deals with basic input and output. We’ll use the functionality in this library to get input from the keyboard and output data to the console. The io part of iostream stands for input/output.

To use the functionality defined within the iostream library, we need to include the iostream header at the top of any code file that uses the content defined in iostream, like so:

#include // rest of code that uses iostream functionality here

The iostream library contains a few predefined variables for us to use. One of the most useful is std::cout, which allows us to send data to the console to be printed as text. cout stands for “character output”.

As a reminder, here’s our Hello world program:

#include // for std::cout int main() < std::cout 

In this program, we have included iostream so that we have access to std::cout. Inside our main function, we use std::cout, along with the insertion operator ( , to send the text Hello world! to the console to be printed.

std::cout can not only print text, it can also print numbers:

#include // for std::cout int main() < std::cout 

This produces the result:

It can also be used to print the value of variables:

#include // for std::cout int main() < int x< 5 >; // define integer variable x, initialized with value 5 std::cout 

This produces the result:

#include // for std::cout int main()

This program prints:

Hello world!

Here’s another example where we print both text and the value of a variable in the same statement:

#include // for std::cout int main() < int x< 5 >; std::cout

This program prints:

x is equal to: 5

Using std::endl to output a newline

What would you expect this program to print?

#include // for std::cout int main()

You might be surprised at the result:

Hi!My name is Alex.

Separate output statements don’t result in separate lines of output on the console.

If we want to print separate lines of output to the console, we need to tell the console to move the cursor to the next line. We can do that by outputting a newline. A newline is an OS-specific character or sequence of characters that moves the cursor to the start of the next line.

One way to output a newline is to output std::endl (which stands for “end line”):

#include // for std::cout and std::endl int main() < std::cout 
Hi! My name is Alex.

In the above program, the second std::endl isn’t technically necessary, since the program ends immediately afterward. However, it serves a few useful purposes.

First, it helps indicate that the line of output is a “complete thought” (as opposed to partial output that is completed somewhere later in the code). In this sense, it functions similarly to using a period in standard English.

Second, it positions the cursor on the next line, so that if we later add additional lines of output (e.g. have the program say “bye!”), those lines will appear where we expect (rather than appended to the prior line of output).

Third, after running an executable from the command line, some operating systems do not output a new line before showing the command prompt again. If our program does not end with the cursor on a new line, the command prompt may appear appended to the prior line of output, rather than at the start of a new line as the user would expect.

Output a newline whenever a line of output is complete.

std::cout is buffered

Consider a rollercoaster ride at your favorite amusement park. Passengers show up (at some variable rate) and get in line. Periodically, a train arrives and boards passengers (up to the maximum capacity of the train). When the train is full, or when enough time has passed, the train departs with a batch of passengers, and the ride commences. Any passengers unable to board the current train wait for the next one.

This analogy is similar to how output sent to std::cout is typically processed in C++. Statements in our program request that output be sent to the console. However, that output is typically not sent to the console immediately. Instead, the requested output “gets in line”, and is stored in a region of memory set aside to collect such requests (called a buffer). Periodically, the buffer is flushed, meaning all of the data collected in the buffer is transferred to its destination (in this case, the console).

To use another analogy, flushing a buffer is kind of like flushing a toilet. All of your collected “output” is transferred to … wherever it goes next. Eew.

This also means that if your program crashes, aborts, or is paused (e.g. for debugging purposes) before the buffer is flushed, any output still waiting in the buffer will not be displayed.

The opposite of buffered output is unbuffered output. With unbuffered output, each individual output request is sent directly to the output device.

Writing data to a buffer is typically fast, whereas transferring a batch of data to an output device is comparatively slow. Buffering can significantly increase performance by batching multiple output requests together to minimize the number of times output has to be sent to the output device.

Using std::endl is often inefficient, as it actually does two jobs: it outputs a newline (moving the cursor to the next line of the console), and it flushes the buffer (which is slow). If we output multiple lines of text ending with std::endl , we will get multiple flushes, which is slow and probably unnecessary.

When outputting text to the console, we typically don’t need to explicitly flush the buffer ourselves. C++’s output system is designed to self-flush periodically, and it’s both simpler and more efficient to let it flush itself.

To output a newline without flushing the output buffer, we use \n (inside either single or double quotes), which is a special symbol that the compiler interprets as a newline character. \n moves the cursor to the next line of the console without causing a flush, so it will typically perform better. \n is also more concise to type and can be embedded into existing double-quoted text.

Here’s an example that uses \n in a few different ways:

#include // for std::cout int main() < int x< 5 >; std::cout 
x is equal to: 5 Yep. And that's all, folks!

When \n is not being embedded into an existing line of double-quoted text (e.g. "hello\n") , it is conventionally single quoted ( '\n' ).

For advanced readers

In C++, we use single quotes to represent single characters (such as 'a' or '$' ), and double-quotes to represent text (zero or more characters).

Even though ‘\n’ is represented in source code as two symbols, it is treated by the compiler as a single linefeed (LF) character (with ASCII value 10), and thus is conventionally single quoted (unless embedded into existing double-quoted text). We discuss this more in lesson 4.11 -- Chars.

When ‘\n’ is output, the library doing the outputting is responsible for translating this single LF character into the appropriate newline sequence for the given OS. See Wikipedia for more information on OS conventions for newlines.

Although unconventional, we believe it’s fine to use (or even prefer) double quoted "\n" in standard output statements.

  1. It’s simpler to double-quote all outputted text rather than having to determine what should be single-quoted and double-quoted.
  2. More importantly, it helps avoid inadvertent multicharacter literals. We cover multicharacter literals and some of the unexpected output they can cause in lesson 4.11 -- Chars.

Single quotes should be preferred in non-output cases.

We’ll cover what ‘\n’ is in more detail when we get to the lesson on chars (4.11 -- Chars).

Prefer \n over std::endl when outputting text to the console.

'\n' uses a backslash (as do all special characters in C++), not a forward slash.

Using a forward slash (e.g. '/n' ) or including other characters inside the single quotes (e.g. ' \n' or '.\n' ) will result in unexpected behavior. For example, std::cout

std::cin is another predefined variable in the iostream library. Whereas std::cout prints data to the console (using the insertion operator > to put the input data in a variable (which can then be used in subsequent statements).

#include // for std::cout and std::cin int main() < std::cout ; // define variable x to hold user input (and value-initialize it) std::cin >> x; // get number from keyboard and store it in variable x std::cout

Try compiling this program and running it for yourself. When you run the program, line 5 will print “Enter a number: “. When the code gets to line 8, your program will wait for you to enter input. Once you enter a number (and press enter), the number you enter will be assigned to variable x . Finally, on line 10, the program will print “You entered ” followed by the number you just entered.

For example (entering the value 4 as input):

Enter a number: 4 You entered 4

This is an easy way to get keyboard input from the user, and we will use it in many of our examples going forward.

Note that you don’t need to output '\n' when accepting a line of input, as the user will need to press the enter key to have their input accepted, and this will move the cursor to the next line of the console.

If your screen closes immediately after entering a number, please see lesson 0.8 -- A few common C++ problems for a solution.

Just like it is possible to output more than one bit of text in a single line, it is also possible to input more than one value on a single line:

#include // for std::cout and std::cin int main() < std::cout ; // define variable x to hold user input (and value-initialize it) int y<>; // define variable y to hold user input (and value-initialize it) std::cin >> x >> y; // get two numbers and store in variable x and y respectively std::cout

This produces the output:

Enter two numbers separated by a space: 5 6 You entered 5 and 6

Values entered should be separated by whitespace (spaces, tabs, or newlines).

There’s some debate over whether it’s necessary to initialize a variable immediately before you give it a user provided value via another source (e.g. std::cin), since the user-provided value will just overwrite the initialization value. In line with our previous recommendation that variables should always be initialized, best practice is to initialize the variable first.

For advanced readers

The C++ I/O library does not provide a way to accept keyboard input without the user having to press enter. If this is something you desire, you’ll have to use a third party library. For console applications, we’d recommend pdcurses, FXTUI, cpp-terminal, or notcurses. Many graphical user interface libraries have their own functions to do this kind of thing.

std::cin is buffered

Adding data to the end of a buffer and removing it from the front of a buffer ensures data is processed in the same order in which it was added. This is sometimes called FIFO (first in, first out).

Each line of input data in the input buffer is terminated by a '\n' character.

We’ll demonstrate this using the following program:

#include // for std::cout and std::cin int main() < std::cout ; std::cin >> x; int y<>; std::cin >> y; std::cout

This program inputs to two variables (this time as separate statements). We’ll run this program twice.

Run #1: When std::cin >> x; is encountered, the program will wait for input. Enter the value 4 . The input 4\n goes into the input buffer, and the value 4 is extracted to variable x .

When std::cin >> y; is encountered, the program will again wait for input. Enter the value 5 . The input 5\n goes into the input buffer, and the value 5 is extracted to variable y . Finally, the program will print You entered 4 and 5 .

There should be nothing surprising about this run.

Run #2: When std::cin >> x is encountered, the program will wait for input. Enter 4 5 . The input 4 5\n goes into the input buffer, but only the 4 is extracted to variable x (extraction stops at the space).

When std::cin >> y is encountered, the program will not wait for input. Instead, the 5 that is still in the input buffer is extracted to variable y . The program then prints You entered 4 and 5 .

Note that in run 2, the program didn’t wait for the user to enter additional input when extracting to variable y because there was already prior input in the input buffer that could be used.

std::cin is buffered because it allows us to separate the entering of input from the extract of input. We can enter input once and then perform multiple extraction requests on it.

The basic extraction process

  1. First, leading whitespace (spaces, tabs, and newlines at the front of the buffer) is discarded from the input buffer. This will discard any unextracted newline character remaining from a prior line of input.
  2. If the input buffer is now empty, operator >> will wait for the user to enter more data. Leading whitespace is again discarded.
  3. operator >> then extracts as many consecutive characters as it can, until it encounters either a newline character (representing the end of the line of input) or a character that is not valid for the variable being extracted to.

Any non-extracted characters (including newlines) remain available for the next extraction attempt.

We discuss how to detect and handle extraction failures, handle extraneous input, and clear std::cin in lesson 9.5 -- std::cin and handling invalid input.

For example, given the following snippet:

int x<>; std::cin >> x;

If the user types 5a and enter, 5a\n will be added to the buffer. 5 will be extracted, converted to an integer, and assigned to variable x . a\n will be left in the input buffer for the next extraction.

If the user types ‘b’ and enter, b\n would be added to the buffer. Because b is not a valid integer, no characters can be extracted, so this is an extraction failure. Variable x would be set to 0 , and future extractions will fail until the input stream is cleared.

We’ll explore more cases in the quiz below.

Consider the following program that we used above:

#include // for std::cout and std::cin int main() < std::cout ; // define variable x to hold user input std::cin >> x; // get number from keyboard and store it in variable x std::cout

The program expects you to enter an integer value, as the variable x that the user input will be put into is an integer variable.

Run this program multiple times and describe the output that results when you enter the following types of input:

a) A letter, such as h .

Result: 0 is always printed.
What’s happening: An integer can’t hold a letter, so extraction completely fails. x is assigned the value 0.

b) A number with a fractional part (e.g. 3.2 ). Try numbers with fractional parts less than 0.5 and greater than 0.5 (e.g. 3.2 and 3.7 ).

Result: The fractional part is dropped (not rounded).
What’s happening: Given the number 3.2 , the 3 gets extracted, but . is an invalid character, so extraction stops here. The .2 remains for a future extraction attempt.

c) A small negative integer, such as -3 .

Result: The entered number is output.
What’s happening: A minus sign at the beginning of a number is acceptable, so it is extracted. The remaining numbers are extracted as well.

d) A word, such as Hello .

Result: 0 is always printed.
What’s happening: An integer can’t hold a letter, so extraction completely fails. x is assigned the value 0.

e) A really big number (at least 3 billion).

Result: You are most likely to get the number 2147483647 .
What’s happening: x can only hold numbers up to a certain size. If you enter a value larger than the largest number x can hold, it will be set to the largest number that x can hold (which is probably 2147483647 , but might be different on your system). We discuss this further in lesson 4.4 -- Signed integers.

f) A small number followed by some letters, such as 123abc .

Result: The numeric values are printed (e.g. 123).
What’s happening: 123 is extracted, the remaining characters (e.g. abc ) are left for a later extraction.

g) A few letters followed by a small number, such as abc123 .

Result: 0 is always printed.
What’s happening: An integer can’t hold a letter, so extraction completely fails. x is assigned the value 0.

h) +5 (three spaces, followed by a plus symbol, and a 5).

Result: 5 is printed.
What’s happening: The leading whitespace is skipped. Plus is a valid symbol at the start of a number (just as a minus sign would be), so it is extracted. The 5 is also extracted.

Result: 5 is printed.
What’s happening: 5 is extracted. b is invalid, so extraction stops here. The b6 remains for a future extraction attempt.

Ask the user to enter three values. The program should then print these values. Add an appropriate comment above function main() .

The program should match the following output (when run with input values 4 , 5 , and 6 ):

Enter three numbers: 4 5 6 You entered 4, 5, and 6.
Hint: Comments above a function should describe what the function does. Hint: Make sure you’re double quoting your output.
#include // Asks the user to enter three values and then print those values as a sentence. int main() < std::cout ; int y<>; int z<>; std::cin >> x >> y >> z; std::cout

Note that ".\n" must be double-quoted since we’re outputting more than one character.