简体   繁体   中英

C++ streams and iterators: Why does this only print once?

I was just messing around with some streams and iterators and all was fine until I tried the code below. I am expecting the output to be all the words from the input file printed line by line. I know I could just use the >> operator on the ifstream but I was just writing this code to get a better grasp of streams and iterators. The current output that I'm getting is all the words of line one printed on their own line.

#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <iterator>

int main (int argc, char* argv[]) {
   if (argc < 3) {
      std::cerr << "Usage: " << argv[0] << " INPUT_FILE OUTPUT_FILE" << std::endl;
   }
   std::string line;
   std::istringstream iss;
   std::ifstream ifs;

   ifs.open(argv[1]);

   while ( getline(ifs, line) ) {
      iss.str(line);
      std::cout << iss.str(); //debug
      std::copy(std::istream_iterator<std::string>(iss),
            std::istream_iterator<std::string>(),
            std::ostream_iterator<std::string>(std::cout, "\n"));
   }

   ifs.close();
   return 0;
}

Reset the error flags for your std::istringstream :

while ( getline(ifs, line) ) {
      iss.clear();
      iss.str(line);
      ...
}

Your call to std::copy exhausts the underlying buffer and your std::istringstream object is in a fail state (eofbit set).

You should define iss in the loop. You need a new, clean one each time through the loop:

while ( std::getline( ifs, line ) ) {
    std::istringstream iss( line );
    //  ...
}

Otherwise, iss retains state from it's previous uses, which you don't want.

If you read eg this reference of std::istream_iterator you will see that it uses operator>> to get the input, and operator>> reads only white-space delimited entries. That's why you get each word on separate lines.

And you won't be able to read the input string stream more than once because once it's done it's EOF flag is set. Either clear the flags, or declare the string stream object inside the loop.

   while ( getline(ifs, line) ) {
      iss.str(line);
      std::cout << iss.str(); //debug
      std::copy(std::istream_iterator<std::string>(iss),
            std::istream_iterator<std::string>(),
            std::ostream_iterator<std::string>(std::cout, "\n"));
            iss.clear(); // celar the iss to reset flags
   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM