Return to tutorial index

Tips and tricks for using C++ I/O (input/output)

Table of Contents

  1. There are three header files to include when using C++ I/O
  2. How to set the width of a printing field
  3. By default, leading whitespace (carriage returns, tabs, spaces) is ignored by cin.
  4. std::getline() can run into problems when used after cin >> var.
  5. Reading in numbers directly is problematic
  6. Using getline to input numbers is a more robust alternate to reading numbers directly
  7. Once a file is opened, it may be used exactly as cin is used.
  8. When reading an entire file, embed the file input inside of the loop condition
  9. Getline can be told to stop grabbing input at any designated character
  10. Delimited files can easily be read using a while loop and getline.
  11. How to prepare the output stream to print fixed precision numbers (3.40 instead of 3.4)

There are three header files to include when using C++ I/O

#include<iostream>
Include this file whenever using C++ I/O
#include<iomanip>
This file must be included for most C++ manipulators. If you don't know what a manipulator is, don't worry. Just include this file along with iostream and you can't go wrong
#include<fstream>
Include this file whenever working with files.

By default, leading whitespace (carriage returns, tabs, spaces) is ignored by cin.

Given:
int i;
float fl;
std::cin >> fl;
std::cin >> i;
  
And you type: 3.14<enter>42<enter>
  • 3.14 is read into fl . The newline (enter key) following the 3.14 is still sitting on the input buffer.
  • Since std::cin ignores whitespace, the first newline is "eaten" by std::cin >> i . Then the integer 42 is read into i and the second newline is left on the input buffer.
  • std::getline() can run into problems when used before std::cin >> var.

    Given:
      float fl;
      std::cin >> fl;
      std::string str;
      std::getline(std::cin, str);
      
    1. And keyboard input: 3.14<enter>
    2. 3.14 is read into fl . The newline following the 3.14 is still sitting on the input buffer.
    3. std::getline(std::cin, str) immediately processes the newline that is still on the input buffer. str becomes an empty string.
    4. The illusion is that the application "skipped" the std::getline() statement.

    The solution is to add std::cin.ignore(); immediately after the first std::cin statement. This will grab a character off of the input buffer (in this case, newline) and discard it.

    std::cin.ignore() can be called three different ways:

    1. No arguments: A single character is taken from the input buffer and discarded:
      std::cin.ignore(); //discard 1 character
    2. One argument: The number of characters specified are taken from the input buffer and discarded:
      std::cin.ignore(33); //discard 33 characters
    3. Two arguments: discard the number of characters specified, or discard characters up to and including the specified delimiter (whichever comes first):
      std::cin.ignore(26, '\n'); //ignore 26 characters or to a newline, whichever comes first

    Reading in numbers directly is problematic

    Inputing numbers directly, version 1:
      #include<limits> //for numeric_limits
      float fl;
      int bad_input;
      do{
        bad_input=0;
        std::cin >> fl;
        if(!std::cin)
        {
          bad_input=1;
          std::cin.clear();
          std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
        }
    
      }while(bad_input);
      
    Inputing numbers directly, version 2:
      #include<limits> //for numeric_limits
      float fl;
      while(!(std::cin >> fl))
      {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
      }
      

    A note on limits. If your compiler doesn't support std::numeric_limits<streamsize>::max(), an alternative is to use the c-style method for determining the maximum integer allowed:

    #include<climits>
    ...
    std::cin.ignore(INT_MAX, '\n');
      

    Using getline to input numbers is a more robust alternate to reading numbers directly

    #include <string>
    ...
    int i;
    float fl;
    std::string temp;
    
    std::getline(std::cin, temp);
    fl=std::stof(temp);
    std::getline(std::cin, temp);
    i=std::stoi(temp);
      

    Once a file is opened, it may be used exactly as std::cin is used.

    std::ifstream someVarName("data.txt");
    float fl;
    std::string temp;
    std::getline(someVarName, temp);
    fl=std::stof(temp);
    int i;
    someVarName >> i;
      

    When reading an entire file, embed the file input inside of the loop condition

    std::ifstream inf("data.txt");
    std::string line;
    while(!getline(inf, line).eof())
    {
      //process the line
    }
      
    More information on the while() loop above can be found here:
    UnderstandingComplexExpressions.pdf.

    Getline can be told to stop grabbing input at any designated character

    std::string temp;
    std::getline(std::cin, temp, '|');
      

    Delimited files can easily be read using a while loop and getline.

    Given data file:
      John|83|52.2
      swimming|Jefferson
      Jane|26|10.09
      sprinting|San Marin
      
    Process using:
    std::ifstream inf("data.txt");
    std::string name;
    while(!std::getline(std::inf, name, '|').eof())
    {
      Athlete* ap;
      std::string jersey_number;
      std::string best_time;
      std::string sport;
      std::string high_school;
      std::getline(inf, jersey_number, '|'); //read thru pipe
      std::getline(inf, best_time);          //read thru newline
      std::getline(inf, sport, '|');         //read thru pipe
      std::getline(inf, high_school);        //read thru newline
      ap = new Athlete(name, stoi(number), stof(best_time), sport, high_school);
      //do something with ap
    
    }
      

    How to prepare the output stream to print fixed precision numbers (3.40 instead of 3.4)

      std::cout.setf(std::ios::fixed, std::ios::floatfield);
      std::cout.setf(std::ios::showpoint);
      std::cout.precision(2);
      

    How to set the width of a printing field

    Given: int one=4, two=44;
      std::cout << one << std::endl.;
      //output:  "4"
    
      std::cout << setw(2) << one << std::endl.;
      //output:  " 4"
    
      std::cout.fill('X');
      std::cout << setw(2) << one << std::endl.;
      //output:  "X4"
    
      std::cout.fill('X');
      std::cout << setw(2) << two << std::endl.;
      //output:  "44"
      
    Return to tutorial index

    Revision History

    2018 January 11 Updated to C++11 conventions
    2012 May 02 Added a link to a 2-page PDF document: "Understanding Complex Expressions".
    2012 April 18 Added std:: to ios flags
    2007 March 1 Corrected spelling error
    2010 February 18 Corrected HTML error