Search

18.2 — Input with istream

The iostream library is fairly complex -- so we will not be able to cover it in its 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:

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 (in the iomanip.h header) 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:

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:

When the user inputs the following:

Hello my name is Alex

The extraction 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():

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:

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:

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.

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():

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 its use:

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 Library” by Nicolai M. Josuttis).

18.3 -- Output with ostream and ios
Index
18.1 -- Input and output (I/O) streams

49 comments to 18.2 — Input with istream

  • Chad

    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”.

    • Ankita Panchal

      If you going to fast, I need some help. I’m having some problem with the game programming. If you could email me back with some tutorial at email adress that is mention, I will appreciate it.

      Thanks,

      Ankita

  • Chad

    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.

  • Chad

    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.

  • Shmuck

    Been working through the tutorial, great so far, just wanted to point out that someone seems to have sneaked some link spam into one of the examples on this page - the first extraction and whitespace codeblock.

    [ Wow, I have no idea how that happened. Removed. Thanks for letting me know! -Alex ]

  • rohan

    Please tell me where my reasoning is wrong-
    In the third example ‘ch’ being ‘char’ should accept only one letter. So according to me it should print only the first letter and then wait for the user to enter another string(Because of the WHILE loop).

    • Here’s what actually happens. If the cin buffer is empty, it lets you type as many characters as you want into the buffer. As long as there is a character in the buffer that is non-zero, the while statement succeeds and the next character is printed (and removed from the buffer).

      When all the characters you typed have been printed, the buffer is empty again and it will wait for you to enter more characters into it.

  • Julie

    So in “while (cin.get(ch))” what does “cin.get(ch)” do, exactly? Does it mean, as long as a character can be read in from cin AND it is successfully stored in ch?

    Similarly would you please explain in detail “while (cin >> ch)” - does it mean, as long as something can be successfully read from cin and it is successfully stored in ch?

    More generally, it would be a big help if you could explain things used in loop (or if) conditions which aren’t straightforward expressions like i<5. I find them hard to follow or understand but I couldn’t find anything about those in your control flow tutorials. I know they’re meant to evaluate to true or false but I’m not sure how you evaluate some of those conditions, especially if they involve pointers or operators like << etc.

    And even more generally, may I say that your site has been very useful in explaining the basics in a way that’s clear, practical and provides a solid foundation for the reader to build on and progress from. Thank you very much.

    • get(ch) returns a result of type istream&. Since this is a reference, it is guaranteed to always be non-zero. Consequently, “while (cin.get(ch))” is logically equivalent to:

      Note that this is actually an infinite loop, and thus probably not something you’d want to do in a non-sample program.

  • prabodh

    please tell why simple i/o prog. run only in dos shell?
    and streams run in prog. mode [ant+r] . .

  • Alex

    You need to tell tell the people that you need to include the header “iomanip” if people want to use setw(). Visual C++ 2005 express edition gives the error “identifier not found :’setw'”.

    [ Thanks for the note. I updated the example. -Alex ]

  • The above code didn’t work as expected.

    When I inserted “Avishee Patterson is a very nice boy.” for the first getline, it only printed “Avishee Pa” and two “new lines” and exited.

    What’s the catch? Why didn’t it work?
    Is it because, I have more than 11 characters?
    Is there any more feasible reason for this?

    Does a C++ Program error has exactly only one reason? I mean, does a C++ error depends only on one cause?

    • Here’s what I suspect happened:
      * The first getline took all your input, but only saved the first 10 chars into strBuf. Because it could not write all of the characters you entered into the buffer, it set some sort of error state. I talk about this more in lesson 13.5 -- stream states and input validation
      * Because the error state was set, the other input lines were ignored.

      You can probably fix this by clearing any error state after the each getline().

      A C++ program can have lots of errors. Having multiple errors in the same place can make identifying them very difficult.

  • Javed Nazim

    some code to demonstrate removing the newline character left by get

  • mslade

    Looks like you got spammed on this page, too: “Note that we only read”.

  • vish

    like if i am taking two lines input here but in output its only prints the last output
    how to print output  respectively
    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;
    }

  • Devashish

    “If you need to know how many character were extracted by the last call of getline(), use gcount():”

    gcount() also works with get(), right???

    But fails with simple cin:

    No matter how many characters I input, it always prints : “0 characters were read.” Why???

    • Alex

      Apparently the value returned by gcount() doesn’t get set from operator >>. It only gets set from the functions get, getline, ignore, peek, read, readsome, putback and unget. 😐

  • Devashish

    “C++ provides a manipulator known as setw (in the iomanip.h header)”
    Modern Compilers may not understand the .h version of iomanip (My Code::Blocks doesn’t). sorry, I forgot to mention this in my previous comment.

  • Matt

    Some more "it’s" typos that should be "its":
    * "The iostream library is fairly complex -- so we will not be able to cover it in it’s entirety in these tutorials."
    * "Here is an example of it’s use:"

  • Vaibhav

    Hi alex;
    I have a doubt in the very first example which shows that the cin extractor ignores the whitespaces and shows the content without it..I tried executing the program and it is very much true..But this where the doubt comes..In the topic ‘An introduction to std::string’ remember the John Doe example!?
    It said there that the cin extractor takes input only till the first whitespace and the rest of it is left for the next extraction..So why does’nt it work the same way over here..I think I am mixing two diff things..Pls help me.

    • Alex

      The cin extractor does ignore whitespace, and there’s no inconsistency.

      When reading in data using cin and the extraction operator, leading whitespace is ignored. Then the non-whitespace data is read. For a char, a single char is read, and the extraction is done. For a std::string, as many chars as are in the stream until a ‘\0’ (end of string) or whitespace character is encountered.

      The only reason it appears different here is because we’re extracting chars using a loop instead of a std::string.

  • jonas

    int main()
    {
        char ch;
        while (cin >> ch)
            cout << ch;

        return 0;
    }
      How to stop this loop? I inputted  0,’\0′ but that didn’t help.

  • cei

    There is a typo: "The **insertion** (should be extraction) operator skips the spaces and the newline."

  • SJ

    I think there is something I’m still not understanding about getline(). Referring to this example:

    if I type something greater than 10 characters, like "I am a banana", it only outputs "I am a ban" to the screen? I thought that the second call of cin.getline() would put the remaining characters up until the newline into buffer and then print them to the screen, but this is clearly not the case. So what specifically is going on?

    • Alex

      I’m not sure why, but if getline(buffer, 11) extracts enough characters to fill the whole buffer, cin goes into “failure mode”.

      You can test for this and clear it using:

  • Darren

    unget?! UNGET?! Who does the naming for these functions? Understandably, there’s already a putback(char) function which replaces a specific char so you can’t use that, but unget!! What’s wrong with replace? Perhaps I should unstart getting so worked up about this kind of thing.

    • Alex

      Replace usually means “replace X with Y”, not put X back into the stream.

      I agree, it’s a bit weird, but hardly egregious (like the misuse of the term size is).

  • Sheeplie

    One important thing to note about get() is that it does not read in a newline character! This can cause some unexpected results:

    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.
    ====================================================================
    I don’t seem to understand. What newline character is cin reading?

    • Alex

      When you type “Hello!” and then hit enter, you’re actually entering “Hello!\n” as input (the ‘\n’ character is the enter character you typed).

  • Bhushan

    Hi Alex,
    Thanks for your amazing tutorials. The book mentioned in the above tutorial is about Standard library and not about standard template Library Can please refer me any book for standard template library.
    PS - "(such as the excellent “The C++ Standard Template Library” by Nicolai M. Josuttis)."

    Thanks

  • Matthieu B.

    Nicolai Josuttis’ book has been updated for c++11 in 2012 (http://www.cppstdlib.com/). Here’s a link to its amazon page: https://www.amazon.com/Standard-Library-Tutorial-Reference-2nd/dp/0321623215/ref=sr_1_2?s=books&ie=UTF8&qid=1470408618&sr=1-2&keywords=c+standard+library. Since it’s more recent it’s way more expensive than the 1999 edition though.

  • Connor

    Alex, in the code

    why doesn’t this go into a continuous loop? From what I understand get() extracts everything but leaves a "\n" in the buffer, so when cin.get() is executed a consecutive time, should it not see the "\n" and execute again, and again, and again…?

    Also, I am trying to use cin following getline():

    The program won’t give me time to enter anything into x or y, it runs as though I’ve already hit enter for those variables. Why does this happen?

    • Connor

      I forgot to include that it happens if you enter more than 10 chars for

    • Alex

      cin.get(ch) will extract ‘\n’. So here’s what happens: the first time you hit cin.get(ch), it waits for you to enter input, so you enter a string, like “abcd\n”. These then get extracted one by one, including the ‘\n’. Then it waits for more input.

      In the second case, the first 10 characters you enter will get extracted into strBuf. The rest stay in the stream, awaiting extraction. Those get extracted into x and y respectively, without asking.

      Remember, C++ streams only wait for input if the buffer of extractable characters is empty.

  • DeNiSkA

    Probably a dumb question , but how  do you know

    will always return true?

    You have used this in the example

    • Alex

      Not really a dumb question, the answer is somewhat complicated. First off, that snippet doesn’t always return true -- if you send it an EOF (ctrl-c on Windows, ctrl-d on Unix I think) it will terminate. Similarly, if ch were an integer instead of a char, it would loop as long as you entered an integer, but would stop looping if you entered a non-integer value.

      Here’s what’s actually happening: operator>> returns a reference to a basic_istream object. However, a basic_istream has an implicit conversion to bool which returns true if the stream has no error, and false if the stream has an error.

      So the above loop essentially reads, “as long as the stream isn’t in error, keep extracting characters to ch”

  • ju-in-love

    hello alex. thanks for your excelent tutorial. after reading the other posts , i think with typing two getline(strbuf,11) we should and expect to see all the string in the screen, but it does not happen, right?( do i understand it correct?) and you said there is an error that you dont know about it?
    i think when we call getline for the second time and enter our string, it show again the first 10 character right?
    then why you write two getline in the code?

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter