You are here:

C++/i/o file streams


My program needs to read in a series of data points from an input file, then generate an output file that contains a histogram of the data points. The input file will contain the following items:  Comment lines indicated by a # in the first column, line to be ignored (only allowed
at start of file, before data points), and an 'S' character on the next line following the comment lines.  The letter 'S' will be followed by a character of the user's choice, which will be the symbol used for displaying the histogram
( S + ) for example.

I am reading in the integers fine and the histogram prints accurately.  My problem is that I do not know how to neglect the characters(comment lines) at the beginning of the input file and skip straight to reading in the 'S', the symbol following the 'S', then the integers.  Any help will be greatly appreciated.


I suspect your problem is that you are probably looking at this is too small chunks. Look at the file as a set of lines. Some you need to process, some you do not.

You do not say how ISO compliant your C++ compiler and library are and whether or not you are using a hosted or standalone implementation. I shall therefore assume a reasonably up to date ISO C++ standard compliant hosted compiler and library implementation.

You can read lines by using the std::getline functions that take a std::istream and read data into a std::string (include <string>):

   std::ifstream inFile("filename.txt");
   std::string line;
   if ( std::getline(inFile, line).good() )
   // process line...

You can then of course examine the first character in the line string and if it is a # skip to reading the next line, if it is an S, extract the following character otherwise assume it is an integer value as before - pass it to your existing integer reading logic but with the data in a std::istringstream ( include <sstream> ):

   std::istringstream inString(line);
   ProcessIntegerData( inString );

Where hopefully ProcessIntegerData would take a reference to a base std::istream.

So if not done already I would then first try to refactor your existing code to process reading the data point integers into a form that places the processing of one line's worth of data into a function such as ProcessIntegerData, which takes the input stream by reference to a std::istream, plus any other required contextual parameters your code may require. Make sure the new form works just as the original.

Next expand on my examples above to process each line in the file (i.e. replace the if with a suitable loop construct). Add in the code to handle comments and display character lines. You could also use a flag to indicate when these become illegal - i.e. the first time you drop through to call your ProcessIntegerData function, indicating the end of the header section. The body of the loop might look something like so:

   if ( line[0]=='#' )
       if ( !processingHeader )
         throw std::domain_error("Comment found outside of data file header");
       continue; // skip to next line
   else if ( line[0]=='S' )
       if ( !processingHeader )
         throw std::domain_error("Display character definition found outside of data file header");
   // code to extract and save display character
       processingHeader = false;
       std::istringstream inString(line);
       ProcessIntegerData( inString );

Of course you could quite easily relax the constraint on comments being allowed only in the header section using such a scheme even if it is undesirable to allow defining the histogram display characters throughout the file. You could also make the initial location of the # and S characters less strict - e.g. you could locate the position of the first non-whitespace character by using the find_first_not_of operation of std::string:

   std::string const SpaceCharacters(" \t");
   char const CommentToken('#');
   char const DisplayCharToken('S');

   // ...

   std::string::size_type firstNonSpacePosition( line.find_first_no_of(SpaceCharacters) );
   if ( std::string::npos == firstNonSpacePosition )
       continue; // no non-whitespace characters found - skip to reading next line
   else if ( line[firstNonSpacePosition]==CommentToken )
In the above example snippet of code I also created and used named constants for the magic character values of # and S -always a good idea.

Please note that the examples only show code snippets to help expand on the points made in answer text. They are _not_ meant to be complete and compilable examples and I have not tried to compile them - so they may contain mistakes, typos etc. If so I apologise and hope you get the idea in any case.

If you need to parse more complex data file formats then you might like to consider using a full on parser. This is made easier in modern C++ by the libraries such as the Boost ( Spirit parser library ( (in fact I have used it to parse things as simple as command line strings...).

Even if you do not feel that a full on parser is required you might find some of the other Boost (or C++ TR1 library extensions) libraries useful such as the regular expression library (part of Boost, Boost's TR1 support and the C++ TR1 C++ library extensions).

Hope this helps.  


All Answers

Answers by Expert:

Ask Experts


Ralph McArdell


I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.


My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at


©2017 All rights reserved.