CPP‐INPUT‐OUTPUT - rFronteddu/general_wiki GitHub Wiki

The io library is part of the C++ std lib that deals wi basic input and 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 <iostream>

std::cout

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”.

#include <iostream> // for std::cout

int main()
{
    std::cout << "Hello world!";
  • insertion operator (<<): Can be used multiple times in a single statement to concatenate multiple pieces of output.
  • std::endl: To output a newline. A newline is an OS-specific character or sequence of characters that moves the cursor to the start of the next line.
    std::cout << "Hi!" << std::endl; // std::endl will cause the cursor to move to the next line
  • std::cout is buffered: 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). 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.

  • std::endl vs \n: 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. 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. 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).

std::cin

std::cin is another predefined variable in the iostream library. Whereas std::cout prints data to the console (using the insertion operator << to provide the data), std::cin (which stands for “character input”) reads input from keyboard. We typically use the extraction operator >> to put the input data in a variable (which can then be used in subsequent statements).

#include <iostream>  // for std::cout and std::cin

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

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:

    int x{}; // 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 separated by a whitespace and store in variable x and y respectively
  • std::cin is buffered
  • The individual characters you enter as input are added to the end of an input buffer (inside std::cin). The enter key (pressed to submit the data) is also stored as a '\n' character.
  • The extraction operator ‘>>’ removes characters from the front of the input buffer and converts them into a value that is assigned (via copy-assignment) to the associated variable. This variable can then be used in subsequent statements.
  • Each line of input data in the input buffer is terminated by a '\n' character.
  1. If std::cin is not in a good state (e.g. the prior extraction failed and std::cin has not yet been cleared), no extraction is attempted, and the extraction process aborts immediately.
  2. Leading whitespace characters are discarded from the input buffer.
  3. If the input buffer is now empty, operator >> will wait for the user to enter more data. Any leading whitespace is discarded from the entered data.
  4. operator >> then extracts as many consecutive characters as it can, until it encounters either a newline character or a character that is not valid for the variable being extracted to.

The result of the extraction process is as follows:

  • If the extraction aborted in step 1, then no extraction attempt occurred. Nothing else happens.
  • If any characters were extracted in step 4 above, extraction is a success. The extracted characters are converted into a value that is then copy-assigned to the variable.
  • If no characters could be extracted in step 4 above, extraction has failed. The object being extracted to is copy-assigned the value 0 (as of C++11), and any future extractions will immediately fail (until std::cin is cleared).

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

  • Note: std::cin and std::cout always go on the left-hand side of the operator.

Example

#include <iostream>  // for std::cout and std::cin

int main()
{
    std::cout << "Enter a number: "; // ask user for a number
    int x{}; // define variable x to hold user input
    std::cin >> x; // get number from keyboard and store it in variable x
    std::cout << "You entered " << x << '\n';

    return 0;
}
  • If we input a letter, it prints 0 becuase an integer can't hold a letter, so extraction fails. x is assigned 0.
  • If we put a number with a fractional part, the fractional part is dropped (not rounded), note that narrowing conversions are only disallowed during list-initialization.
  • A very big number: most likely it will print the biggest number an int can hold.
  • 1234abc: only the number will be printed, letters are left for future extraction
  • abc1234: it will print zero because int can't hold a character so the process will fail
  • " 123": The leading space willb e skipped and ne number printed

Debugging

When printing information for debugging purposes, use std::cerr instead of std::cout. One reason for this is that std::cout may be buffered, which means a bit of time may pass between when you ask std::cout to output text and when it actually does. If you output using std::cout and then your program crashes immediately afterward, std::cout may or may not have actually output yet. This can mislead you about where the issue is. On the other hand, std::cerr is unbuffered, which means anything you send to it will output immediately.

You can also force cout to not buffer with:

#ifdef DEBUG
std::cout << std::unitbuf; // enable automatic flushing for std::cout (for debugging)
#endif

Floating Numbers

#include <iomanip> // for output manipulator std::setprecision()
#include <iostream>

int main()
{
    std::cout << std::setprecision(17); // show 17 digits of precision
    std::cout << 3.33333333333333333333333333333333333333f <<'\n'; // f suffix means float
    std::cout << 3.33333333333333333333333333333333333333 << '\n'; // no suffix means double

    return 0;
}

Printing bool

Use std::boolalpha to print true or false

By default, std::cin only accepts numeric input for Boolean variables: 0 is false, and 1 is true. Any other numeric value will be interpreted as true, and will cause std::cin to enter failure mode. Any non-numeric value will be interpreted as false and will cause std::cin to enter failure mode.

To allow std::cin to accept the words false and true as inputs, you must first input to std::boolalpha.

Note that we use std::cin >> std::boolalpha; to input bool values as true or false, and std::cout << std::boolalpha; to output bool values as true or false. These are independent controls that can be turned on (using std::boolalpha) or off (using std::noboolalpha) separately.

Printing chars

When using std::cout to print a char, std::cout outputs the char variable as an ASCII character:

#include <iostream>

int main()
{
    char ch1{ 'a' }; // (preferred)
    std::cout << ch1; // cout prints character 'a'

    char ch2{ 98 }; // code point for 'b' (not preferred)
    std::cout << ch2; // cout prints a character ('b')


    return 0;
}

Because extracting input ignores leading whitespace, this can lead to unexpected results when trying to extract whitespace characters to a char variable:

#include <iostream>

int main()
{
    std::cout << "Input a keyboard character: "; // assume the user enters "a b" (without quotes)

    char ch{};
    std::cin >> ch; // extracts a, leaves " b\n" in stream
    std::cout << "You entered: " << ch << '\n';

    std::cin >> ch; // skips leading whitespace (the space), extracts b, leaves "\n" in stream
    std::cout << "You entered: " << ch << '\n';

    return 0;
}

In the above example, we may have expected to extract the space, but because leading whitespace is skipped, we extracted the b character instead.

One simple way to address this is to use the std::cin.get() function to perform the extraction instead, as this function does not ignore leading whitespace.

Char is defined by C++ to always be 1 byte in size. By default, a char may be signed or unsigned (though it’s usually signed). If you’re using chars to hold ASCII characters, you don’t need to specify a sign (since both signed and unsigned chars can hold values between 0 and 127).

If you’re using a char to hold small integers (something you should not do unless you’re explicitly optimizing for space), you should always specify whether it is signed or unsigned. A signed char can hold a number between -128 and 127. An unsigned char can hold a number between 0 and 255.

There are some sequences of characters in C++ that have special meaning. These characters are called escape sequences. An escape sequence starts with a ‘\’ (backslash) character, and then a following letter or number.

For backwards compatibility reasons, many C++ compilers support multicharacter literals, which are char literals that contain multiple characters (e.g. '56'). If supported, these have an implementation-defined value (meaning it varies depending on the compiler). Because they are not part of the C++ standard, and their value is not strictly defined, multicharacter literals should be avoided.

Much like ASCII maps the integers 0-127 to American English characters, other character encoding standards exist to map integers (of varying sizes) to characters in other languages. The most well-known mapping outside of ASCII is the Unicode standard, which maps over 144,000 integers to characters in many different languages. Because Unicode contains so many code points, a single Unicode code point needs 32-bits to represent a character (called UTF-32). However, Unicode characters can also be encoded using multiple 16-bit or 8-bit characters (called UTF-16 and UTF-8 respectively).

char16_t and char32_t were added to C++11 to provide explicit support for 16-bit and 32-bit Unicode characters. These char types have the same size as std::uint_least16_t and std::uint_least32_t respectively (but are distinct types). char8_t was added in C++20 to provide support for 8-bit Unicode (UTF-8). It is a distinct type that uses the same representation as unsigned char.

You won’t need to use char8_t, char16_t, or char32_t unless you’re planning on making your program Unicode compatible. wchar_t should be avoided in almost all cases (except when interfacing with the Windows API), as its size is implementation-defined.

Outputting values in decimal, octal, or hexadecimal

By default, C++ outputs values in decimal. However, you can change the output format via use of the std::dec, std::oct, and std::hex I/O manipulators:

#include <iostream>

int main()
{
    int x { 12 };
    std::cout << x << '\n'; // decimal (by default)
    std::cout << std::hex << x << '\n'; // hexadecimal
    std::cout << x << '\n'; // now hexadecimal
    std::cout << std::oct << x << '\n'; // octal
    std::cout << std::dec << x << '\n'; // return to decimal
    std::cout << x << '\n'; // decimal

    return 0;
}

Outputting values in binary is a little harder, as std::cout doesn’t come with this capability built-in. Fortunately, the C++ standard library includes a type called std::bitset that will do this for us (in the header).

To use std::bitset, we can define a std::bitset variable and tell std::bitset how many bits we want to store. The number of bits must be a compile-time constant. std::bitset can be initialized with an integral value (in any format, including decimal, octal, hex, or binary).

#include <bitset> // for std::bitset
#include <iostream>

int main()
{
	// std::bitset<8> means we want to store 8 bits
	std::bitset<8> bin1{ 0b1100'0101 }; // binary literal for binary 1100 0101
	std::bitset<8> bin2{ 0xC5 }; // hexadecimal literal for binary 1100 0101

	std::cout << bin1 << '\n' << bin2 << '\n';
	std::cout << std::bitset<4>{ 0b1010 } << '\n'; // create a temporary std::bitset and print it

	return 0;
}

In C++20 and C++23, we have better options for printing binary via the new Format Library (C++20) and Print Library (C++23):

#include <format> // C++20
#include <iostream>
#include <print> // C++23

int main()
{
    std::cout << std::format("{:b}\n", 0b1010);  // C++20, {:b} formats the argument as binary digits
    std::cout << std::format("{:#b}\n", 0b1010); // C++20, {:#b} formats the argument as 0b-prefixed binary digits

    std::println("{:b} {:#b}", 0b1010, 0b1010);  // C++23, format/print two arguments (same as above) and a newline

    return 0;
}
⚠️ **GitHub.com Fallback** ⚠️