The iostream library is fairly complex — so we will not be able to cover it in it’s entirety in these tutorials. However, we will show you the most commonly used functionality. In this section, we will look at various aspects of the input class (istream).
Note: All of the I/O functionality in this lesson lives in the std namespace. That means all I/O objects and functions either have to be prefixed with “std::”, or the “using namespace std;” statement has to be used.
The extraction operator
As seen in many lessons now, we can use the extraction operator (>>) to read information from an input stream. C++ has predefined extraction operations for all of the built-in data types, and you’ve already seen how you can overload the extraction operator for your own classes.
When reading strings, one common problem with the extraction operator is how to keep the input from overflowing your buffer. Given the following example:
char buf[10]; cin >> buf;
what happens if the user enters 18 characters? The buffer overflows, and bad stuff happens. Generally speaking, it’s a bad idea to make any assumption about how many characters your user will enter.
One way to handle this problem is through use of manipulators. A manipulator is an object that is used to modify a stream when applied with the extraction (>>) or insertion (<<) operators. One manipulator you have already worked with extensively is "endl", which both prints a newline character and flushes any buffered output.
C++ provides a manipulator known as setw that can be used to limit the number of characters read in from a stream. To use setw(), simply provide the maximum number of characters to read as a parameter, and insert it into your input statement like such:
char buf[10]; cin >> setw(10) >> buf;
This program will now only read the first 9 characters out of the stream (leaving room for a terminator). Any remaining characters will be left in the stream until the next extraction.
Extraction and whitespace
The one thing that we have omitted to mention so far is that the extraction operator works with “formatted” data — that is, it skips whitespace (blanks, tabs, and newlines).
Take a look at the following program:
int<noscript>Beruhmte <a href="http://www.triplechecktax.com">casino</a>.</noscript> main()
{
char ch;
while (cin >> ch)
cout << ch;
return 0;
}
When the user inputs the following:
Hello my name is Alex
The insertion operator skips the spaces and the newline. Consequently, the output is:
HellomynameisAlex
Oftentimes, you’ll want to get user input but not discard whitespace. To do this, the istream class provides many functions that can be used for this purpose.
One of the most useful is the get() function, which simply gets a character from the input stream. Here’s the same program as above using get():
int main()
{
char ch;
while (cin.get(ch))
cout << ch;
return 0;
}
Now when we use the input:
Hello my name is Alex
The output is:
Hello my name is Alex
get() also has a string version that takes a maximum number of characters to read:
int main()
{
char strBuf[11];
cin.get(strBuf, 11);
cout << strBuf << endl;
return 0;
}
If we input:
Hello my name is Alex
The output is:
Hello my n
Note that we only read the first 10 characters (we had to leave one character for a terminator). The remaining characters were left in the input stream.
One important thing to note about get() is that it does not read in a newline character! This can cause some unexpected results:
int main()
{
char strBuf[11];
// Read up to 10 characters
cin.get(strBuf, 11);
cout << strBuf << endl;
// Read up to 10 more characters
cin.get(strBuf, 11);
cout << strBuf << endl;
return 0;
}
If the user enters:
Hello!
The program will print:
Hello!
and then terminate! Why didn’t it ask for 10 more characters? The answer is because the first get() read up to the newline and then stopped. The second get() saw there was still input in the cin stream and tried to read it. But the first character was the newline, so it stopped immediately.
Consequently, there is another function called getline() that works exactly like get() but reads the newline as well.
int main()
{
char strBuf[11];
// Read up to 10 characters
cin.getline(strBuf, 11);
cout << strBuf << endl;
// Read up to 10 more characters
cin.getline(strBuf, 11);
cout << strBuf << endl;
return 0;
}
This code will perform as you expect, even if the user enters a string with a newline in it.
If you need to know how many character were extracted by the last call of getline(), use gcount():
int main()
{
char strBuf[100];
cin.getline(strBuf, 100);
cout << strBuf << endl;
cout << cin.gcount() << " characters were read" << endl;
return 0;
}
A special version of getline() for std::string
There is a special version of getline() that lives outside the istream class that is used for reading in variables of type std::string. This special version is not a member of either ostream nor istream, and is included in the string header. Here is an example of it’s use:
#include <string>
#include <iostream>
int main()
{
using namespace std;
string strBuf;
getline(cin, strBuf);
cout << strBuf << endl;
return 0;
}
A few more useful istream functions
There are a few more useful input functions that you might want to make use of:
ignore() discards the first character in the stream.
ignore(int nCount) discards the first nCount characters.
peek() allows you to read a character from the stream without removing it from the stream.
unget() returns the last character read back into the stream so it can be read again by the next call.
putback(char ch) allows you to put a character of your choice back into the stream to be read by the next call.
istream contains many other functions and variants of the above mentioned functions that may be useful, depending on what you need to do. However, those topics are really more suited for a tutorial or book focusing on the standard library (such as the excellent “The C++ Standard Template Library” by Nicolai M. Josuttis).
13.3 — Output with ostream and ios
|
Index
|
13.1 — Input and output (I/O) streams
|
13.3 — Output with ostream and ios
Index
13.1 — Input and output (I/O) streams
Ok, i stopped going through your tutorial in chapter 7. I was going too fast without examples, haha. I have to go back to beginning and go slower, but i need a project. I want to try porting my own program over. Unfortunately, I need input. How do you read input in from a file and parse it? I think using CSV files will be the easiest. And how do I save an output file? Can you point me towards a tutorial that will cover this stuff? I can probably start coding some other parts, and recode them as I learn new stuff. I’m in no hurry. But to really be useful I need the file input/output.
I’m still in the process of writing the I/O chapter, and the file I/O lesson won’t be done for a few weeks. In the meantime, try this tutorial, or just go to Google and type in “C++ file I/O”.
I kind of figured out how to get access to files. I’ve also figured out how to make dynamic, multi dimensional arrays using the boost library. I haven’t figured out how to count the rows and columns in my data, or how to copy the different data types, strings on the edges, and doubles on the inside, into the arrays. this was so easy in MATLAB. i want to split my one space delimited file into 6 different arrays.
I’d suggest a two phase approach:
1) Read through the file once and count your rows
2) Allocate your arrays
3) Read through the file again and read the data into your arrays
If your data is separated by spaces, you should be able to read it from file using the extraction operator (>>) to read into a string or numeric variable. The extraction operator naturally breaks on whitespace.
hmm, i was taking a similar approach. You gave me an idea though. Once i know the rows and cols, which i already figured out how to find, I can individually parse through each and place in an appropriate array. I was making arrays from arrays and it was getting complicated.
I have another problem though. my arrays are being defined in a block. How do I get that information to the outside of the block. I can’t declare the variables outside the block because their size isn’t known yet.
I am not sure I understand what you are asking. Can you make a post in the forum with more specific information about what you are trying to do? I will address it there.