In principle, input and output operators behave symmetrically. There is only one important difference: for output you control the precise format of the inserted character sequence, while for input the format of an extracted character sequence is never exactly described. This is for practical reasons. You may want to extract the next floating point value from a stream, for example, without necessarily knowing its exact format. You want it whether it is signed or not, or in exponential notation with a small or capital E for the exponent, etc. Hence, extractors in general accept an item in any format permitted for its type.
Formatted input is handled as follows:
Unless explicitly specified otherwise, extractors automatically ignore all white space characters (blanks, tabulators, newlines) that precede the item to be extracted. [The classification of a character as white space depends on the character set used. The extractor takes the information from the locale's ctype facet.]
When the first relevant character is found, they extract characters from the input stream until they find a separator; that is, a character that does not belong to the item. White space characters in particular are separators.
The separator remains in the input stream and becomes the first character extracted in a subsequent extraction.
Several format parameters, which control insertion, are irrelevant for extraction. The format parameter fill character, returned by std::ios::fill(), and the adjustment flags, std::ios_base::left, std::ios_base::right, and std::ios_base::internal, have no effect on extraction. The field width is relevant only for extraction of strings, and ignored otherwise.
You can use the manipulator std::noskipws to switch off the automatic skipping of white space characters. For example, extracting white space characters may be necessary if you expect the input has a certain format, and you need to check for violations of the format requirements. This procedure is shown in the following code:
std::cin >> std::noskipws; char c; do { float fl; std::cin >> fl >> c; // extract number and separator if (c == ',' || c == '\n') // next char is ',' or newline ? process(fl); // yes: use the number } while (std::cin && c == ','); // check whether stream is good if (c != '\n') error(); // no: error!
If you must skip a sequence of characters other than white spaces, you can use the function std::istream::ignore(). The call:
basic_ifstream<myChar,myTraits> InputStream("file-name"); InputStream.ignore(std::numeric_limits<streamsize>::max(), myChar('\n'));
or, for ordinary narrow characters of type char:
std::ifstream InputStream("file-name"); InputStream.ignore(std::numeric_limits<streamsize>::max(),'\n');
ignores all characters until the end of the line. This example uses a stream object of type std::basic_ifstream<myChar, myTraits> that is not predefined by the library. File streams are described in Section 27.4.1.5.
When you extract strings or character arrays from an input stream, strm, characters are read until:
A white space character is found
The end of the input is reached
A certain number of characters is extracted, if strm.width() != 0; . In the case of a string, this number is the field width strm.width(). In the case of a character array, this number is strm.width()-1. The last position is reserved for the terminating NUL character.
Note that the field width is reset to 0 after the extraction of a string.
There are subtle differences between extracting a character sequence into a character array and extracting it into a string object. For example:
char buf[SZ]; std::cin >> buf;
is different from
std::string s; std::cin >> s;
Extraction into a string is safe, because strings automatically extend their capacity as necessary. You can extract as many characters as you want since the string always adjusts its size accordingly. Character arrays, on the other hand, have fixed size and cannot dynamically extend their capacity. If you extract more characters than the character array can take, the extractor writes beyond the end of the array. To prevent this, you must set the field width as follows each time you extract characters into a character array:
char buf[SZ]; std::cin >> std::width(SZ) >> buf;