Input and output functionality is not defined as part of the C++ language, but is instead provided through the C++ standard library.
Many C++ books do not cover this functionality because it is not part of the base language. However, just because this functionality is not part of C++ does not mean that C++ does not support it. For C++ to support this functionality, the <iostream> header file, which is part of the C++ standard library, is used.
In its simplest form, input and output in C++ are implemented with streams. A stream is an array of bytes that can be accessed sequentially. Over time, a stream can potentially produce or consume an unlimited amount of data.
We usually deal with 2 types of flows.
Input streams are used to hold input from a data producer such as a keyboard, file or network. For example, the user can press a key when the program is not expecting any input. Instead of completely ignoring this action of the user, C++ keeps this input in a stream, the data is put into an input stream and waits there until the program is ready.
Output streams are used to hold the output of a specific data consumer such as a monitor, file or printer. When writing data to an output device, the device may not yet be ready to accept the data. For example, the printer may still be warming up when the program writes data to the output stream. The data will remain in the output stream until it starts to be consumed by the printer.
Of course, some instruments can be sources of inputs and outputs. For example files and networks.
The programmer only needs to learn how to control these streams. It does not need to know how the streams interact with devices and resources such as files and networks in the background. This part depends on the environment and the operating system.
The istream class is the primary class used when dealing with input streams. In input streams, the subtraction operator (»
) is used to remove values from the stream.
The ostream class is the primary class used when dealing with output streams. In output streams, the append operator («
) is used to place values into the stream.
The iostream class can handle both input and output and allows bidirectional input/output. Both istream and ostream are derived from the class named ios
A standard flow is a pre-connected flow provided to a computer program by its environment. C++ comes with four predefined standard flow objects for your use.
Unbuffered output is usually processed immediately, while buffered output is usually stored and written as a block. Since Clog is not used very often, it is usually excluded from the list of standard streams.
The iostream
library provides a wide and varied input functionality. Only the necessary information for the input is included here. There are many sub-stream functions. See basic_istream for details.
We can use the subtraction operator (») to read information from an input stream.
C++ has a default subtraction operator for all basic data types. We have also seen how we can overload this operator for our own class types.
Caution when using the extraction operator. In case the input exceeds our buffer object.
char buf[10]; std::cin >> buf;
For example, in the code above, what happens if the user enters more than 10 characters? A situation called buffer overflow occurs and can cause undefined behavior.
We can use manipulators to prevent such situations.
Manipulator is an object used to modify a stream when applied with the subtract (») or add («) operators.
#include <iomanip> char buf[10]; std::cin >> std::setw(10) >> buf;
In the above example, with the setw()
manipulator, we have ensured that the subtraction operator receives a maximum of 9 characters 1) The remaining inputs will remain in the stream until the next subtraction operation.
Another thing to know is that the subtraction operator ignores gaps. To avoid this, we can use the get()
function, which is also in the istream class.
char ch; while (std::cin.get(ch)) std::cout << ch;
Likewise, there is an alternative to the get()
function for strings. The following example retrieves a string 10 characters long from the user. The rest remains in the stream in the same way.
char strBuf[11]; std::cin.get(strBuf, 11); std::cout << strBuf << '\n';
There is an important point to know about these two get()
examples. This function does not read the character \n''. When it encounters this character, it considers the read operation finished. We can use the ''getline()'' function for this case.
The function ''getline()'' works in the same way, except that it also reads the character ''\n%%%
.
char strBuf[11]; // 10 karaktere kadar okuma std::cin.getline(strBuf, 11); std::cout << strBuf << '\n'; // 10 karaktere kadar daha okuyun std::cin.getline(strBuf, 11); std::cout << strBuf << '\n';
The insertion operator («)
is used to put information into an output stream. C++ has predefined append operations for all built-in data types
There are two ways to change formatting: flags and manipulators. You can think of flags as boolean variables that can be turned on and off. Manipulators are objects placed in a stream that affect the way objects enter and exit.
We can use the setf()
and unsetf()
functions to change the flags. For example, in c++, as in math, we do not write the + sign in front of positive numbers by default.
We can enable printing with the std::ios::showpos
flag.
std::cout.setf(std::ios::showpos); // std::ios::showpos bayrağını açtık. std::cout << 27 << '\n';
To activate more than one flag, we can use the |
oparet.
std::cout.setf(std::ios::showpos | std::ios::showpoint); // std::ios::showpos ve std::ios::showpoint bayrağını açtık. std::cout << 27 << '\n';
In the same way, we can use the unsetf()
function to turn off a flag.
std::cout.setf(std::ios::showpos); // std::ios::showpos bayrağını açın std::cout << 27 << '\n'; std::cout.unsetf(std::ios::showpos); // std::ios::showpos bayrağını kapatın std::cout << 28 << '\n';
Another thing to know about flags is that some flags belong to certain groups. These groups are called format groups and format groups keep flags with similar functionality together. The functions setf()
and unsetf()
are not as smart as expected in handling these groups of flags.
For example, the format group basefield has the flags oct
, dec
and hex
which determine the base in which the integer output is processed. By default the dec
flag is on.
If we want to print in hexadecimal by turning on the hex
flag. Separately we need to turn off the dec
flag. Because the setf()
function is smart enough not to turn off the dec
flag when we set the hex
flag. As a result, our code will not work as expected because the dec
flag has priority over the hex
flag.
std::cout.setf(std::ios::hex); // We tried to open the hex output. std::cout << 27 << '\n';
Kodu bize;
27
It will give the result. Because the dec
flag is on, it will process the number 27 as decimal. What we really need to do is;
std::cout.unsetf(std::ios::dec); // dec çıkışını kapattık. std::cout.setf(std::ios::hex); // hex çıkışını açmayı denedik. std::cout << 27 << '\n';
Another convenience is the second parameter of the setf()
function. By typing the name of the group in the second parameter, we can turn off other flags in that group except the flag we turned on.
std::cout.setf(std::ios::hex, std::ios::basefield); std::cout << 27 << '\n';
This way of formatting the output is not very common. C++ gives us a second formatting method. This method is manipulators. The good thing about manipulators is that they can remember to turn off other flags according to the flag we set.
std::cout << std::hex << 27 << '\n'; // Print 27 in hexadecimal std::cout << 28 << '\n'; // Hala hex'teyiz. std::cout << std::dec << 29 << '\n'; // back to the decimal system
Yukarıdaki kod bize ;
1b 1c 29
Sonucunu verecektir.
So why use manipulators and learn to turn flags on and off? Many options can usually be set with manipulators or flags. But some settings can only be set with the manipulator or only with the flag. So it is necessary to know both.
Flags, manipulators and member functions that you may commonly encounter are listed below.
std::ios
.std::
namespace.std::ostream
class.std::ios::boolalpha
flag is on, bool values are printed as true
or false
. If it is off, bool values are printed as 1
or 0
. It is off by default.std::boolalpha
prints bool values “true” or “false”std::noboolalpha
manipulator prints bool values 0 or 1 (default)std::cout << true << ' ' << false << '\n'; std::cout.setf(std::ios::boolalpha); std::cout << true << ' ' << false << '\n'; std::cout << std::noboolalpha << true << ' ' << false << '\n'; std::cout << std::boolalpha << true << ' ' << false << '\n';
std::ios::showpos
flag is on, it puts + in front of positive numbers. If it is off, it does not. It is off by default.std::showpos
puts + in front of positive numbers.std::noshowpos
does not put + in front of positive numbers (default)std::cout << 5 << '\n'; std::cout.setf(std::ios::showpos); std::cout << 5 << '\n'; std::cout << std::noshowpos << 5 << '\n'; std::cout << std::showpos << 5 << '\n';
std::ios::uppercase
flag is on. It is off by default.std::uppercase
manipulator.std::nouppercase
(default)std::cout << 123456.8 << '\n'; std::cout.setf(std::ios::uppercase); std::cout << 123456.8 << '\n'; std::cout << std::nouppercase << 123456.8 << '\n'; std::cout << std::uppercase << 123456.8 << '\n';
std::ios::basefield
format group;std::ios::dec
flag is set, print values in decimal (default)std::ios::hex
flag is set, it prints values in hexadecimal.std::ios::oct
flag is set, it prints values in octal.std::dec
manipulator prints values in decimal (default)std::hex
prints values in hexadecimal.std::oct
prints values in octal.std::cout << 27 << '\n'; std::cout.setf(std::ios::dec, std::ios::basefield); std::cout << 27 << '\n'; std::cout.setf(std::ios::oct, std::ios::basefield); std::cout << 27 << '\n'; std::cout.setf(std::ios::hex, std::ios::basefield); std::cout << 27 << '\n'; std::cout << std::dec << 27 << '\n'; std::cout << std::oct << 27 << '\n'; std::cout << std::hex << 27 << '\n';
std::ios::floatfield
format group;std::ios::fixed
flag is set, use decimal notation for fractional numbers (default)std::ios::scientific
flag is on, it uses scientific notation for fractional numbers.std::ios::showpoint
flag is on, it always shows a decimal point and trailing 0s for fractional values.std::fixed
manipulator uses the decimal system (default)std::scientific
uses scientific notation.std::showpoint
shows the decimal point and trailing 0s for fractional values.std::noshowpoint
does not display the decimal point and trailing 0s for fractional values.std::setprecision(int)
sets the precision of fractional numbers (found in the iomanip header).std::ios_base::precision()
returns the current precision of fractional numbers.std::ios_base::precision(int)
sets the precision of fractional numbers and returns the old precision.If using constant or scientific notation, the precision determines how many decimal places are displayed in the fraction. Note that if the precision is less than the number of significant digits, the number will be rounded.
std::cout << std::fixed << '\n'; std::cout << std::setprecision(3) << 123.456 << '\n'; std::cout << std::setprecision(4) << 123.456 << '\n'; std::cout << std::setprecision(5) << 123.456 << '\n'; std::cout << std::setprecision(6) << 123.456 << '\n'; std::cout << std::setprecision(7) << 123.456 << '\n'; std::cout << std::scientific << '\n'; std::cout << std::setprecision(3) << 123.456 << '\n'; std::cout << std::setprecision(4) << 123.456 << '\n'; std::cout << std::setprecision(5) << 123.456 << '\n'; std::cout << std::setprecision(6) << 123.456 << '\n'; std::cout << std::setprecision(7) << 123.456 << '\n';
Kodu bize;
123.456 123.4560 123.45600 123.456000 123.4560000 1.235e+002 1.2346e+002 1.23456e+002 1.234560e+002 1.2345600e+002
If neither a fixed nor a scientific method is used, precision determines how many significant digits are displayed. Again, if the precision is less than the number of significant digits, the number will be rounded.
std::cout << std::setprecision(3) << 123.456 << '\n'; std::cout << std::setprecision(4) << 123.456 << '\n'; std::cout << std::setprecision(5) << 123.456 << '\n'; std::cout << std::setprecision(6) << 123.456 << '\n'; std::cout << std::setprecision(7) << 123.456 << '\n';
Code gives us.
123 123.5 123.46 123.456 123.456
You can use the showpoint
manipulator or flag to make the stream write a decimal point and trailing zeros.
std::cout << std::showpoint << '\n'; std::cout << std::setprecision(3) << 123.456 << '\n'; std::cout << std::setprecision(4) << 123.456 << '\n'; std::cout << std::setprecision(5) << 123.456 << '\n'; std::cout << std::setprecision(6) << 123.456 << '\n'; std::cout << std::setprecision(7) << 123.456 << '\n';
Code gives us.
123. 123.5 123.46 123.456 123.4560
Taken from UCH Viki. https://wiki.ulascemh.com/doku.php?id=en:cs:cpp:common:basicio Çıkarma operatörü başlığında ikinci satırda aşırı yükleme kısmına link verilecek.