Table of Contents
Girdi ve Çıktı Akışları
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.
What is Flow?
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
Standard Flows
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.
- cin – an istream object bound to standard input (typically keyboard)
- cout – an ostream object connected to standard output (typically a monitor)
- cerr – an ostream object that provides unbuffered output, connected to standard error (typically the monitor)
- clog – an ostream object that provides buffered output, connected to standard error (typically the monitor)
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.
Input with istream
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.
Subtraction operator
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';
out with ostream and ios
Insertion Operator
The insertion operator («)
is used to put information into an output stream. C++ has predefined append operations for all built-in data types
Formatting
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.
Other Formatters
Flags, manipulators and member functions that you may commonly encounter are listed below.
- Flags are of class
std::ios
. - Manipulators reside in the
std::
namespace. - Member functions are contained in the
std::ostream
class.
- If the
std::ios::boolalpha
flag is on, bool values are printed astrue
orfalse
. If it is off, bool values are printed as1
or0
. It is off by default. - The manipulator
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';
- If the
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. - The manipulator
std::showpos
puts + in front of positive numbers. - The manipulator
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';
- Capital letters are used if the
std::ios::uppercase
flag is on. It is off by default. - Capital letters are used with the
std::uppercase
manipulator. - Lowercase letters are used with the 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;- If the
std::ios::dec
flag is set, print values in decimal (default) - If the
std::ios::hex
flag is set, it prints values in hexadecimal. - If the
std::ios::oct
flag is set, it prints values in octal.
- The
std::dec
manipulator prints values in decimal (default) - The manipulator
std::hex
prints values in hexadecimal. - The manipulator
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;- If the
std::ios::fixed
flag is set, use decimal notation for fractional numbers (default) - If the
std::ios::scientific
flag is on, it uses scientific notation for fractional numbers. - If the
std::ios::showpoint
flag is on, it always shows a decimal point and trailing 0s for fractional values. - If the flag is not specified, constant is used for low-digit numbers, otherwise scientific is used.
- The
std::fixed
manipulator uses the decimal system (default) - The manipulator
std::scientific
uses scientific notation. - The manipulator
std::showpoint
shows the decimal point and trailing 0s for fractional values. - The manipulator
std::noshowpoint
does not display the decimal point and trailing 0s for fractional values. - The manipulator
std::setprecision(int)
sets the precision of fractional numbers (found in the iomanip header).
- The member function
std::ios_base::precision()
returns the current precision of fractional numbers. - The member function
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.