© Peter Van Weert and Marc Gregoire 2016
Peter Van Weert and Marc GregoireC++ Standard Library Quick Reference10.1007/978-1-4842-1876-1_5

5. Stream I/O

Peter Van Weert and Marc Gregoire2
(1)
Kessel-Lo, Belgium
(2)
Meldert, Belgium
 
The C++ stream-based I/O library allows you to perform I/O operations without having to know details about the target to or source from which you are streaming. A stream’s target or source could be a string, a file, a memory buffer, and so on.

Input and Output with Streams

The stream classes provided by the Standard Library are organized in a hierarchy and a set of headers, as shown in Figure 5-1.
A417649_1_En_5_Fig1_HTML.jpg
Figure 5-1.
The hierarchy of stream-related classes
More accurately, the library defines templates called basic_ios, basic_ostream, basic_istringstream, and so on, all templated on a character type. All classes in the hierarchy, except ios_base, are typedefs for these templated classes with char as template type. For example, std::ostream is a typedef for std::basic_ostream<char>. There are equivalent typedefs for the wchar_t character type called wios, wostream, wofstream, and so on. The remainder of this chapter only uses the char typedefs shown in Figure 5-1.
In addition to the headers in the figure, there is also <iostream>. Somewhat confusingly, this does not really define std::iostream itself, because this is done by <istream>. Instead, <iostream> includes <ios>, <streambuf>, <istream>, <ostream>, and <iosfwd>, while itself adding the standard input and output streams (w)cin, (w)cout, (w)cerr, and (w)clog. The latter two are intended for output of errors and logging information, respectively. Their destinations are implementation specific.
The library also provides the std::basic_streambuf, basic_filebuf, and basic_stringbuf templates and their various typedefs, plus istreambuf_iterator and ostreambuf_iterator. These are, or work on, stream buffers and are the basis for the implementation of other stream classes, such as ostream, ifstream, and so on. They are briefly discussed toward the end of this chapter.
The header <iosfwd> contains forward declarations of all the standard I/O library types. It is useful to include it in other header files without having to include the complete template definitions of all the types you require.

Helper Types    <ios>

The following helper types are defined in <ios>:
Type
Description
std::streamsize
A typedef for a signed integral type used to represent the number of characters transferred during an I/O operation, or to represent the size of an I/O buffer.
std::streamoff
A typedef for a signed integral type used to represent an offset into a stream.
std::fpos
A class template containing an absolute position in a stream and a conversion operator to convert it into a streamoff. Certain arithmetic operations are supported: a streamoff can be added to or subtracted from an fpos, resulting in an fpos (using +, -, +=, or -=), and two fpos objects can be compared (using == or !=) or subtracted, resulting in a streamoff (using -). Predefined typedefs are provided: std::streampos and wstreampos for the character types char and wchar_t.

std::ios_base         <ios>

The ios_base class , defined in <ios>, is the base class for all input and output stream classes. It keeps track of formatting options and flags to manipulate how data is read and written. The following methods are provided:
Method
Description
precision()
precision(streamsize)
Returns the precision for floating-point I/O, or changes it while returning the old one. The semantics of the precision depend on which floatfield formatting flag is set (see Table 5-1 and Table 5-2). If either fixed or scientific is set, the precision specifies exactly how many digits to show after the decimal separator, even if this means adding trailing zeros. If neither is set, then it denotes the maximum number of digits to show, counting both the digits before and after the decimal separator (no zeros are added in this case). And if both are set, the precision is ignored.
width()
width(streamsize)
Returns the width of the next field, or changes it while returning the old one. This width specifies the minimum number of characters to output with certain I/O operations. To reach this minimum, fill characters (explained later) are added. Only has an effect on the next I/O operation.
getloc()
imbue(locale)
Returns the locale used during I/O, or changes it while returning the old one. See Chapter 6 for details on locales.
flags()
flags(fmtflags)
Returns the currently set formatting flags, or replaces the current flags while returning the old ones. Table 5-1 lists all available fmtflags flags, which can be combined bitwise.
setf(fmtflags)
unsetf(fmtflags)
Sets or unsets individual flags without touching others. The flags prior to the update are returned.
setf(fmtflags flags,
            fmtflags mask)
Sets flags while unsetting others in a group, specified as a mask. Table 5-2 lists the predefined masks. For example, setf(right | fixed, adjustfield | floatfield) sets the right and fixed flags while unsetting the left, internal, and scientific flags.
It is also possible to modify flags by streaming I/O manipulators, discussed in the next section.
Table 5-1.
std::ios_base::fmtflags Formatting Flags Defined in <ios>
Flag
Description
boolalpha
Use true and false instead of 1 and 0 for Boolean I/O.
left,
right,internal
Output is left aligned with fill characters added to the right, or right aligned with padding on the left, or adjusted by padding in the middle. The third flag, internal, works for numerical and monetary values, with the designated padding point being between the value and any of its prefixes: a sign, numerical base, and/or currency symbol. Otherwise, internal is equivalent to right. The results of the different alignment options are shown in the example section.
scientific, fixed
If neither of these flags is set, use default notation for floating-point I/O (for instance: 0.0314). Otherwise, use scientific (3.140000e-02) or fixed notation (0.031400). If both are combined, scientific | fixed, use hexadecimal floating-point notation (0x1.013a92p-5).
dec, oct, hex
Use a decimal, octal, or hexadecimal base for integer I/O.
showbase
For integer I/O, write or expect the base prefix as specified with dec, oct, or hex. When performing monetary I/O, std::put_money() prefixes values with the locale-dependent currency symbol, and std::get_money() requires a currency symbol prefix.
showpoint
Always use a locale-dependent decimal separator character for floating-point I/O, even if the decimal part is zero.
showpos
Use a + character for non-negative numeric I/O.
skipws
Instructs all formatted input operations (explained later) to skip leading whitespace.
unitbuf
Forces the output to be flushed after each output operation.
uppercase
Instructs floating-point and hexadecimal integer output operations to use uppercase letters instead of lowercase ones.
Table 5-2.
std::ios_base::fmtflags Masks Defined in <ios>
Flag
Description
basefield
dec | oct | hex
adjustfield
left | right | internal
floatfield
scientific | fixed

I/O Manipulators    <ios>, <iomanip>

Manipulators allow you to change flags using operator<< and operator>> instead of flags(fmtflags) or setf().
The <ios> header defines I/O manipulators in the global std scope for all the flags defined in Table 5-1: std::scientific, std::left, and so on. For flags that are part of a mask defined in Table 5-2, the I/O manipulator uses that mask. For example, std::dec actually calls ios_base::setf(dec, basefield).
For boolalpha, showbase, showpoint, showpos, skipws, uppercase, and unitbuf, negative manipulators are available as well, which have the same name but are prefixed with no: for example, std::noboolalpha.
In addition to std::fixed and scientific, there are also std::hexfloat (scientific | fixed) and std::defaultfloat (no floatfield flags set) manipulators.
Additionally, the <iomanip> header defines the following manipulators:
Manipulator
Description
setiosflags(fmtflags)
resetiosflags(fmtflags)
Sets/unsets the given fmtflags.
setbase(int)
Changes the base used for integer I/O. A value other than 16 (hex), 8 (oct), or 10 (dec) sets the base to 10.
setfill(char)
Changes the fill character. See the example later.
setprecision(int)
Changes the number of decimal places for floating-point output as if set with ios_base::precision().
setw(int)
Sets the width of the next field. See the example.
get_money(m&, bool=false)
put_money(m&, bool=false)
Reads or writes a monetary value. If the Boolean is true, use international currency strings (e.g. "USD "); otherwise use currency symbols (e.g. "$"). The type of m can be either std::string or long double. See Chapter 6 for more details on monetary formatting.
get_time(tm*, char*)
put_time(tm*, char*)
Reads or writes a date/time. The formatting is the same as for std::strftime(), discussed in Chapter 2.
quoted()
Reads or writes quoted strings and properly handles embedded quotes. An example of this manipulator is given in the section on how to implement your own operator<< and operator>> later in this chapter.

Example

This code snippet additionally needs <locale>:
A417649_1_En_5_Figa_HTML.gif
On an American system, the output is as follows:
Left:     $1.23__
Right:    __$1.23
Internal: 0x___7b

std::ios         <ios>

The ios class defined in <ios> inherits from ios_base and provides a number of methods to inspect and modify the state of a stream, which is a bitwise combination of the state flags listed in Table 5-3.
Table 5-3.
std::ios_base::iostate State Constants Defined in <ios>
iostate
Description
goodbit
The stream is not in any error state. No bits are set: i.e. the state is 0.
badbit
The stream is in an unrecoverable error state.
failbit
An input or output operation failed. For example, reading a numerical value into an integer could cause the failbit to be set if the numerical value overflows the integer.
eofbit
The stream is at its end.
The following state-related methods are provided:
Method
Description
good()
eof()
bad()
fail()
Returns true if, respectively, the badbit, failbit, and eofbit are not set,
the eofbit is set,
the badbit is set, or
either the failbit or badbit is set.
operator!
Equivalent to fail().
operator bool
Equivalent to !fail().
rdstate()
Returns the current ios_base::iostate state.
clear(state)
Changes the state of the stream to the given one if a valid stream buffer is attached (see later); otherwise sets it to state | badbit.
setstate(state)
Calls clear(state | rdstate()).
Besides these state-related methods, the following additional ones are defined by ios:
Method
Description
fill()
fill(char)
Returns the current fill character, or changes it while returning the old one. To change it, you can also use the setfill() manipulator.
copyfmt()
Copies everything from another ios instance except its state.
tie()
Ties any output stream to the this stream, which means the tied output stream is flushed each time an input or output operation is performed on the this stream.
narrow()
widen()
Converts a wide character to its narrow equivalent or vice versa in a locale-specific manner. See Chapter 6 for details on locales.
The default initialization of std::ios has the following effect:
  • Flags are set to skipws | dec.
  • Precision is set to 6.
  • The field width is set to 0.
  • The fill character is set to widen(' ').
  • The state is set to goodbit if there is a valid stream buffer attached (see later), or badbit otherwise.

Error Handling

By default, stream operations report errors by setting the state bits (good, bad, fail, and eof) of the stream, but they do not throw exceptions. Exceptions can be enabled, though, with the exceptions() method. It either returns the current exceptions mask or accepts one. This mask is a bitwise combination of std::ios_base::iostate state flags (see Table 5-3). For each state flag in the mask that is set to 1, the stream throws an exception when that state bit is set for the stream.
For example, the following code tries to open a nonexistent file using a file stream (explained in detail later in this chapter). No exceptions are thrown; only the fail bit of the stream is set to 1:
A417649_1_En_5_Figb_HTML.gif
If you want to use exceptions instead, the code can be rewritten as follows:
A417649_1_En_5_Figc_HTML.gif
A possible output could be
ios_base::failbit set: iostream stream error

std::ostream  <ostream>

The ostream class supports formatted and unformatted output to char-based streams . Formatted output means the format of what is written can be influenced by formatting options, such as the width of a field, the number of decimal digits for floating-point numbers, and so on. Formatted output is generally also influenced by the stream’s locale, as explained in Chapter 6. Unformatted output entails simply writing characters or character buffers as is.
ostream provides a swap() method and the following high-level output operations. If no return type is mentioned, the operation returns an ostream&, allowing operations to be chained:
Operation
Description
operator<<
Writes formatted data to the stream.
put(char)
write(const char*, n)
Writes a single character or n characters unformatted to the stream.
fpos tellp()
seekp(pos)
seekp(off, dir)
Returns or changes the current position in the stream. The p is shorthand for put and denotes that these methods are working on an output stream. seekp() accepts either an absolute position (fpos) or an offset (streamoff) and a direction (seekdir: see Table 5-4) in which to start the offset.
flush()
Forcefully flushes the buffer to the target.
Table 5-4.
std::ios_base::seekdir Constants Defined in <ios>
seekdir
Description
beg
The beginning of the stream
end
The end of the stream
cur
The current position in the stream
<ostream> also defines the following extra I/O manipulators :
Manipulator
Description
ends
Writes (null character) to the stream.
flush
Flushes the stream. Same as calling flush() on the ostream.
endl
Writes widen(' ') to the stream and flushes it.
The <iostream> header provides the following global ostream instances :
  • cout/wcout: Outputs to the standard C output stream, stdout
  • cerr/wcerr: Outputs to the standard C error stream, stderr
  • clog/wclog: Outputs to the standard C error stream, stderr
(w)cout is automatically tied to (w)cin. This means an input operation on (w)cin causes (w)cout to flush its buffers. (w)cout is also automatically tied to (w)cerr, so any output operation on (w)cerr causes (w)cout to flush.
std::ios_base provides a static method called sync_with_stdio() to synchronize these global ostreams with the underlying C streams after each output operation. This ensures that they both use the same buffers, allowing you to safely mix C++ and C-style output. It also guarantees that the standard streams are thread-safe: that is, there are no data races. Character interleaving remains possible, though.
Note
When working with the standard streams cout, cerr, clog, and cin (discussed later), you do not have to take care of platform-dependent end-of-line characters. For example, on Windows, a line usually ends with , whereas on Linux it ends with . However, the translation happens automatically for you, so you can just always use .

Example

The following example demonstrates the three different methods of output:
std::cout << "PI = " << 3.1415 << std::endl;
std::cout.put(' ');
std::cout.write("C++", 3);

std::istream    <istream>

The istream class supports formatted and unformatted input from char-based streams . It provides swap() and the following high-level input operations. Unless otherwise specified, the operation returns an istream&, which facilitates chaining:
Operation
Description
operator>>
Reads formatted data from the stream. All other input operations work with unformatted data.
get(char*, count
       [, delim])
getline(char*, count
                 [, delim])
read(char*, count)
Reads count characters from the stream and stores them in a char* buffer. A terminating null character ('') is automatically added by get() and getline(), but not by read(). For the first two, input stops when encountering the delimiter, by default ' '. get() does not extract the delimiter from the stream, but getline() does. The delimiter is never stored in the char* buffer.
streamsize readsome(
      char*, count)
Reads at most count characters that are immediately available into a given char* buffer. These are the characters the underlying stream buffer (discussed later) can return without having to wait for them, used for instance to read data from asynchronous sources without blocking. Returns the number of extracted characters.
get(char&)
int get()
int peek()
Reads a single character from the stream. The first version stores the read character in a char reference. The last two return an integer that is either a valid read character or EOF if no characters are available. peek() does not remove the character from the stream.
unget()
putback(char)
Puts the last read character or a given one on the stream so it is available for the next read operation.
ignore([count
              [,delim]])
Reads count characters (1 by default) from the stream or until a given delimiting character is encountered (eof by default) and discards them. The delimiter is removed as well.
streamsize gcount()
Returns the number of characters that were extracted by the last unformatted input operation: get(), getline(), read(), readsome(), peek(), unget(), putback(), or ignore().
fpos tellg()
seekg(pos)
seekg(off, dir)
Returns or changes the current position in the stream. The g is shorthand for get and denotes that these methods are working on an input stream. seekg()accepts either an absolute position (fpos) or an offset (streamoff) and a direction (seekdir: see Table 5-4) in which to start the offset.
int sync()
Synchronizes the input stream with the underlying stream buffer (discussed later). This is an advanced, rarely used method.
<istream> also defines the following extra I/O manipulator :
Manipulator
Description
ws
Discards any whitespace currently in the stream.
The <iostream> header provides the following global istream instances :
  • cin/wcin: Reads from the standard C input stream, stdin
The ios_base::sync_with_stdio() function affects (w)cin as well. See the explanation given for cout, cerr, and clog earlier.
As explained earlier, istream provides a getline() method to extract characters. Unfortunately, you have to pass it a char* buffer of proper size. The <string> header defines a std::getline() method that is easier to use and that accepts a std::string as target buffer. The following example illustrates its use.

Example

int anInt;
double aDouble;
std::cout << "Enter an integer followed by some whitespace "
          << "and a double, and press enter: ";
std::cin >> anInt >> aDouble;
std::cout << "You entered: ";
std::cout << "Integer = " << anInt << ", Double = " << aDouble << std::endl;
std::string message;
std::cout << "Enter a string. End input with a * and enter: ";
std::getline(std::cin >> std::ws, message, '*');
std::cout << "You entered: '" << message << "'" << std::endl;
Here is a possible output of this program:
Enter an integer followed by some whitespace
and a double, and press enter: 1 3.2 ↩
You entered: Integer = 1, Double = 3.2
Enter a string. End input with a * and enter: This is ↩
a multiline test* ↩
You entered: 'This is ↩
a multiline test'

std::iostream    <istream>

The iostream class , defined in <istream> (not in <iostream>!), inherits from both ostream and istream and provides high-level input and output operations. It keeps track of two independent positions in the stream: an input and an output position. This is the reason ostream has tellp() and seekp() methods, whereas istream has tellg() and seekg(): iostream contains all four, so they need a different name. It does not provide additional functionality beyond what is inherited.

String Streams  <sstream>

String streams allow you to use stream I/O on strings. The library provides istringstream (input, inherits from istream), ostringstream (output, inherits from ostream), and stringstream (input and output, inherits from iostream). See Figure 5-1 for the inheritance chart. All three classes have a similar set of constructors :
  • [i|o]stringstream(ios_base::openmode): Constructs a new string stream with the given openmode, a bitwise combination of the flags defined in Table 5-5
    Table 5-5.
    std::ios_base::openmode Constants Defined in <ios>
    openmode
    Description
    app
    Short for append. Seeks to the end of the stream before each write.
    binary
    A stream opened in binary mode. If not specified, the stream is opened in text mode. See the File Streams section for the difference.
    in / out
    A stream opened for reading / writing respectively.
    trunc
    Removes the contents of the stream after opening it.
    ate
    Seeks to the end of the stream after opening it.
  • [i|o]stringstream(string&, ios_base::openmode): Constructs a new string stream with a copy of the given string as initial stream contents and with the given openmode
  • [i|o]stringstream([i|o]stringstream&&): Move constructor
The openmode in the first two constructors has a default: out for ostringstream, in for istringstream, and out|in for stringstream. For ostringstream and istringstream, the given openmode is always combined with the default one; for example, for ostringstream, the actual openmode is given_openmode |ios_base::out.
All three classes add only two methods:
  • string str(): Returns a copy of the underlying string object
  • void str(string&): Sets the underlying string object to a copy of the given one

Example

std::ostringstream oss;
oss << 123 << " " << 3.1415;
std::string myString = oss.str();
std::cout << "ostringstream contains: '" << myString << "'" << std::endl;
std::istringstream iss(myString);
int myInt; double myDouble;
iss >> myInt >> myDouble;
std::cout << "int = " << myInt << ", double = " << myDouble << std::endl;

File Streams    <fstream>

File streams allow you to use stream I/O on files. The library provides an ifstream (input, inherits from istream), ofstream (output, inherits from ostream), and fstream (input and output, inherits from iostream). See Figure 5-1 for the inheritance chart. All three classes have a similar set of constructors:
  • [i|o]fstream(filename, ios_base::openmode): Constructs a file stream and opens the given file with the given openmode. The file can be specified as a const char* or a std::string&.
  • [i|o]fstream([i|o]fstream&&): Move constructor.
All three classes add the following methods:
  • open(filename, ios_base::openmode): Opens a file similar to the first constructor
  • is_open(): Returns true if a file is opened for input and/or output
  • close(): Closes the currently opened file
The openmode (see Table 5-5) in the constructors and in the open() method has a default: out for ofstream, in for ifstream, and out|in for fstream. For ofstream and ifstream, the given openmode is always combined with the default one; for example: for ofstream, the actual openmode is given_openmode |ios_base::out.
If the ios_base::in flag is specified, whether or not in combination with ios_base::out, the file you are trying to open must already exist. The following code opens a file for input and output and creates the file if it does not exist yet:
A417649_1_En_5_Figd_HTML.gif
If a file is opened in text mode, as opposed to binary mode, the library is allowed to translate certain special characters to match how the platform uses those. For example, on Windows, lines usually end with , whereas on Linux they usually end with . When a file is opened in text mode, you do not read/write the on Windows yourself; the library handles this translation for you.
The fstream class , supporting both input and output, handles the current position differently compared to other combined input and output streams, such as stringstream. A file stream has only one position, so the output and input positions are always the same.
Tip
The destructor of a file stream automatically closes the file.

Example

The following example is similar to the example given earlier for string streams but uses a file instead. In this example, the ofstream is explicitly closed using close(), and the ifstream is implicitly closed by the destructor of ifs:
const std::string filename = "output.txt";
std::ofstream ofs(filename);
ofs << 123 << " " << 3.1415;
ofs.close();
std::ifstream ifs(filename);
int myInt; double myDouble;
ifs >> myInt >> myDouble;
std::cout << "int = " << myInt << ", double = " << myDouble << std::endl;

operator<< and >> for Custom Types

You can write your own versions of the stream output and extraction operators operator<< and operator>>. Here is an example of both operators for the Person class, using the std::quoted() manipulator to handle spaces in names:
std::ostream& operator<<(std::ostream& os, const Person& person) {
   os << std::quoted(person.GetFirstName()) << ' '
      << std::quoted(person.GetLastName());
   return os;
}
std::istream& operator>>(std::istream& is, Person& person) {
   std::string firstName, lastName;
   is >> std::quoted(firstName) >> std::quoted(lastName);
   person.SetFirstName(firstName); person.SetLastName(lastName);
   return is;
}
These operators can be used as follows (<sstream> is also required):
A417649_1_En_5_Fige_HTML.gif

Stream Iterators    <iterator>

The <iterator> header defines two stream iterators, std::istream_iterator and std::ostream_iterator, in addition to the other iterators discussed in Chapters 3 and 4.

std::ostream_iterator

The ostream_iterator is an output iterator capable of outputting a sequence of objects of a certain type to an ostream using operator<<. The type of the objects to output is specified as a template type parameter. There is one constructor that accepts a reference to the ostream to use and an optional delimiter that is written to the stream after each output.
Stream iterators are very powerful in combination with the algorithms discussed in Chapter 4. As an example, the following code snippet writes a vector of doubles to the console using the std::copy() algorithm, where each double is followed by a tab character (additionally requires <vector> and <algorithm>):
std::vector<double> vec{ 1.11, 2.22, 3.33, 4.44 };
std::copy(cbegin(vec), cend(vec),
          std::ostream_iterator<double>(std::cout, " "));

std::istream_iterator

The istream_iterator is an input iterator capable of iterating over objects of a certain type in an istream by extracting them one by one using operator>>. The type of the objects to extract from the stream is specified as a template type parameter. There are three constructors:
  • istream_iterator(): The default constructor, which results in an iterator pointing to the end of the stream
  • istream_iterator(istream&): Constructs an iterator that extracts objects from the given istream
  • istream_iterator(istream_iterator&): Copy constructor
Just like an ostream_iterator, istream_iterators are very powerful in combination with algorithms. The following example uses the for_each() algorithm in combination with an istream_iterator to read an unspecified number of double values from the standard input stream and sum them to calculate the average (additionally needs <algorithm>):
std::istream_iterator<double> begin(std::cin), end;
double sum = 0.0; int count = 0;
std::for_each(begin, end, [&](double value){ sum += value; ++count;});
std::cout << sum / count << std::endl;
Input is terminated by pressing Ctrl+Z on Windows or Ctrl+D on Linux, followed by Enter.
This second example uses both an istream_iterator to read an unspecified number of doubles from the console and an ostream_iterator to write the read doubles to a stringstream separated by tabs (additionally needs <sstream> and <algorithm>):
std::ostringstream oss;
std::istream_iterator<double> begin(std::cin), end;
std::copy(begin, end, std::ostream_iterator<double>(oss, " "));
std::cout << oss.str() << std::endl;

Stream Buffers        <streambuf>

Stream classes do not work directly with a target such as a string in memory, a file on disk, and so on. Instead, they use the concept of stream buffers, defined by std::basic_streambuf<CharType> . Two typedefs are provided, std::streambuf and std::wstreambuf, where the template type is, respectively, char or wchar_t. File streams use std::(w)filebuf, and string streams use std::(w)stringbuf, both inheriting from (w)streambuf.
Each stream has a stream buffer associated with it to which you can get a pointer with rdbuf() . A call to rdbuf(streambuf*) returns the current associated stream buffer and changes it to the given one.
Stream buffers can be used to write a stream-redirector class that redirects one stream to another stream. As a basic example, the following code snippet redirects all std::cout output to a file (additionally needs <fstream>):
A417649_1_En_5_Figf_HTML.gif
Caution
When changing the buffer for one of the standard streams, do not forget to restore the old buffer before terminating the application, as is done in the previous example. Otherwise your code may crash with certain library implementations.
It can also be used to implement a tee class that redirects output to two or more target streams. Another use is to easily read an entire file:
std::ifstream ifs("test.txt");
std::stringstream buffer;
buffer << ifs.rdbuf();
The exact behavior of stream buffers is implementation dependent. Working directly with stream buffers is an advanced topic that we cannot discuss further in detail due to page constraints.

C-Style Output and Input   <cstdio>

In addition to the file utilities explained in Chapter 2, the <cstdio> header also defines the C-style I/O library, including functions for character-based I/O (getc(), putc(), ...) and formatted I/O (printf(), scanf(), ...). All the C-style I/O functionality is subsumed by the type-safe C++ streams, which also have better-defined, portable error handling.1 This section does discuss the std::printf() and std::scanf() families of functions, and only these, because they remain more convenient at times than C++ streams due to their compact formatting syntax.

std::printf() Family

The following printf() family of functions is defined in <cstdio> :
std::printf(const char* format, ...)
std::fprintf(FILE* file, const char* format, ...)
std::snprintf(char* buffer, size_t bufferSize, const char* format, ...)
std::sprintf(char* buffer, const char* format, ...)
They write formatted output to, respectively, standard output, a file, a buffer of given size, or a buffer, and return the number of characters written out. The last one, sprintf() , is less safe than snprintf(). They all have a variable number of arguments following the format string. There are also versions prefixed with a v that accept a va_list for the arguments: for example, vprintf(const char* format, va_list). For the first three, wide-character versions are provided as well: (v)wprintf(), (v)fwprintf(), and (v)swprintf().
How the output is formatted is controlled by the given format string. All of its characters are written out as is, except sequences that start with a %. The basic syntax for a formatting option is % followed by a conversion specifier . This tells printf() how to interpret the next value in the variable-length list of arguments. The arguments passed to printf() must be in the same order as the % directives in format. Table 5-6 explains the available conversion specifiers. The expected argument types listed are for the case where no length modifier is used (discussed later).
Table 5-6.
Available Conversion Specifiers for printf()-Like Functions
Specifier
Description
d, i
A signed int argument converted to decimal representation [-]ddd.
o, u, x, X
An unsigned int argument converted to an octal (o), decimal (u), or hexadecimal representation, the latter with either lowercase (x) or uppercase digits (X).
f, F
A double argument converted to a decimal notation in the style [-]ddd.dd (with lowercase or, respectively, uppercase letters used for infinity and NaN values).
e, E
A double argument converted to scientific notation: i.e. [-]d.dde±dd or [-]d.ddE±dd (again with lowercase/uppercase letters for special values).
g, G
A double argument converted as if with f/F or e/E, whichever is more compact for the given value and precision. e/E is only used if the exponent is greater than or equal to the precision, or less than -4.
a, A
A double argument converted to hexadecimal format: [-]0xh.hhhp±d or [-]0Xh.hhhP±d (infinity and NaN values are printed as with f, F).
c
An int argument converted to a single unsigned char.
s
The argument is a pointer to a char array. The precision specifies the maximum number of bytes to output. If no precision is given, writes everything until the null terminator. Note: do not pass a std::string object as is as argument for a %s modifier!
p
The argument is interpreted as a void pointer, and the pointer is converted to an implementation-dependent format.
n
The argument is a pointer to a signed int that receives the number of characters written out so far by this call to printf().
%
Outputs a % character. No corresponding argument must be passed.
Caution
The C-style I/O functions are not type safe. If your conversion specifier says to interpret an argument value as a double, then that argument must be a true double (and not, for instance, a float or an integer). It will compile and run if a wrong type is passed, but this rarely ends well. This also means you should never pass a C++ std::string as-is as an argument for a string conversion specifier: instead, use c_str() as shown in the following example.
The following example prints the lyrics of the traditional American folk song “99 Bottles of Beer” (it assumes a using namespace std):
string bottles = "bottles of beer";
char on_wall[99];
for (int i = 99; i > 0; --i) {
   snprintf(on_wall, sizeof(on_wall), "%s on the wall", bottles.c_str());
   printf("%d %s, %d %s. ", i, on_wall, i, bottles.c_str());
   printf("Take one down, pass it around, %d %s. ", i-1, on_wall);
}
The formatting options are much more powerful than the basic conversions discussed so far. The full syntax of the % directive is as follows:
%<flags><width><precision><length_modifier><conversion>
with
  • <flags>: Zero or more flags that change the meaning of the conversion specifier. See Table 5-7.
    Table 5-7.
    Available Flags
    Flag
    Description
    -
    Left-justify the output. By default, output is right justified.
    +
    Always output the sign of a number, even for positive numbers.
    space-character
    Prefix the output with a space if the number to output is non-negative or results in no characters. Ignored if + is also specified.
    #
    Output a so-called alternative form.
    For x and X, the result is prefixed with 0x or 0X if the number is not zero.
    For all floating-point specifiers (a, A, e, E, f, F, g, and G), the output always contains a decimal point character.
    For g and G, trailing zeros are not removed.
    For o, precision is increased such that the first digit to output is a zero.
    0
    For all integer and floating-point conversion specifiers (d, i, o, u, x, X, a, A, e, E, f, F, g, and G), padding is done with zeros instead of spaces. Ignored if - is specified as well, or for all integer specifiers in combination with a precision.
  • <width>: Optional minimum field width (truncation is never done: only padding). Padding is applied if the converted value has fewer characters than the specified width. By default, spaces are used for padding. <width> can be either a non-negative integer or *, which means to take the width from an integer argument from the argument list. This width has to precede the value to be formatted.
  • <precision>: A dot followed by an optional non-negative integer (0 is assumed if not specified), or a *, which again means to take the precision from an integer argument from the argument list. The precision is optional, and determines the following:
    • The maximum number of bytes for s. By default, a zero-terminated character array is expected.
    • The minimum number of digits to output for all integer conversion specifiers (d, i, o, u, x, and X). Default: 1.
    • The number of digits to output after the decimal point for most floating-point conversion specifiers (a, A, e, E, f, and F). If not specified, the default precision is 6.
    • The maximum number of significant digits for g and G. The default is again 6.
  • <length_modifier>: An optional modifier that alters the type of the argument to be passed. Table 5-8 gives an overview of all supported modifiers for numeric conversions. For character and strings (c and s conversion specifiers, respectively), the l length modifier (note: this is the letter l) changes the expected input type from int and char* to wint_t and wchar_t*, respectively.2
    Table 5-8.
    Length Modifiers for All Numeric Conversion Specifiers
    Modifier
    d, i
    o, u, x, X
    n
    a, A, e, E, f, F, g, G
    (none)
    int
    unsigned int
    int*
    double
    hh
    char
    unsigned char
    char*
     
    h
    short
    unsigned short
    short*
     
    l
    long
    unsigned long
    long*
     
    ll
    long long
    unsigned long long
    long long*
     
    j
    intmax_t
    uintmax_t
    intmax_t*
     
    z
    size_t
    size_t
    size_t*
     
    t
    ptrdiff_t
    ptrdiff_t
    ptrdiff_t*
     
    L
       
    long double
  • <conversion>: The only required component, which specifies the conversion to apply to the argument. (See Table 5-6.)
The modifiers in Table 5-8 determine the type of the inputs that must be passed as indicated. std::intmax_t and uintmax_ t are defined in <cstdint> (see Chapter 1), and size_t and ptrdiff_t are defined in <cstddef>. Note also that the long and long long modifiers use the letter l, and not the number 1.

Example

A417649_1_En_5_Figg_HTML.gif

std::scanf() Family

The following scanf() family of functions is defined in <cstdio> :
std::scanf(const char* format, ...)
std::fscanf(FILE* file, const char* format, ...)
std::sscanf(const char* buffer, const char* format, ...)
They read, respectively, from standard input, a file, or a buffer. In addition to these functions, which have a variable number of arguments following the format string, there are also versions whose names are prefixed with v and that accept a va_list for the arguments: for example, vscanf(const char* format, va_list). Wide-character versions are provided as well: (v)wscanf(), (v)fwscanf(), and (v)swscanf().
They all read formatted data based on a given format string. The scanf() formatting grammar used is similar to that of printf(), seen earlier. All characters in the format string are simply used to compare with the input, except sequences that start with a %. These % directives result in values being parsed and stored in the location pointed to by the function’s arguments, in order. The basic syntax is a % sign followed by one of the conversion specifiers from Table 5-9. The last column shows the argument type in case no length modifiers are specified (see Table 5-10).
Table 5-9.
Available Conversion Specifiers for scanf()-Like Functions
Specifier
Matches...
Argument
d
Optionally signed decimal integer.
int*
i
Optionally signed integer whose base is determined from the integer’s prefix: decimal by default, but octal if it starts with 0 and hexadecimal if it starts with 0x or 0X.
int*
o / u / x, X
Optionally signed octal / decimal / hexadecimal integer.
unsigned int*
a, A, e, E,
f, F, g, G
Optionally signed floating-point number, infinity, or NaN. All eight specifiers are completely equivalent: e.g., they all parse scientific notation as well.
float*
c
A character sequence whose length is specified by the field width, or of length one if no width is specified.
char**
s
A sequence of non-whitespace characters.
char**
[...]
A non-empty character sequence from a set of expected characters. The set is specified between square brackets, e.g. [abc]. To match all characters except those in a set, use [^abc].
char**
p
An implementation-dependent sequence of characters as produced by %p with printf().
void**
n
Does not extract/parse any input. The argument receives the number of characters read from the input stream so far.
int*
%
A % character.
/
Table 5-10.
Available Length Modifiers for the Numeric Conversion Specifiers of scanf()-Like Functions
Modifier
d, i
o, u, x, X
n
a, A, e, E, f, F, g, G
(none)
int*
unsigned int*
int*
float*
hh
char*
unsigned char*
char*
 
h
short*
unsigned short*
short*
 
l
long*
unsigned long*
long*
double*
ll
long long*
unsigned long long*
long long*
 
j
intmax_t*
uintmax_t*
intmax_t*
 
z
size_t*
size_t*
size_t*
 
t
ptrdiff_t*
ptrdiff_t*
ptrdiff_t*
 
L
  
long double*
For all directives except those with conversion specifier c, s, or [...], any whitespace characters are skipped until the first non-whitespace one. Parsing stops when the end of the input string is reached, when a stream input error occurs, or when a parsing error occurs. The return value equals the number of assigned values or EOF if an input failure occurred before starting the first conversion. The number of assigned values will be less than the number of directives if the end of the stream is reached or a parsing error occurs: for example, zero if this occurs during the first conversion.
The full syntax of the % directive is as follows:
%<*><width><length_modifier><conversion>
with:
  • <*>: An optional * sign that causes scanf() to parse the data from the input without storing it in any of the arguments.
  • <width>: Optional maximum field width in characters.
  • <length_modifier>: Optional length modifier: see Table 5-10. When applied to a c, s, or [...] specifier, the l (letter l) modifies the required input type from char** to wchar_t**.
  • <conversion>: Required. Specifies the conversion to apply; see Table 5-9.
The only non-obvious difference between Table 5-10 and Table 5-8 is that by default, floating-point arguments must point to a float and not a double.

Example

std::string s = "int: +123; double: -2.34E-3; chars: abcdef";
int i = 0; double d = 0.0; char chars[4] = { 0 };
std::sscanf(s.data(), "int: %i; double: %lE; chars: %[abc]", &i, &d, chars);
std::printf("int: %+i; double: %.2lE; chars: %s", i, d, chars);
Footnotes
1
Some library implementations use errno (see Chapter 8) to report errors for C-style I/O functions, including the printf() and scanf() functions: consult your library documentation to confirm.
 
2
wint_t is defined in <cwchar> and is a typedef for an integral type large enough to hold any wide character (wchar_t value) and at least one value that is not a valid wide character (WEOF).
 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset