C++ reading a text file with conditional statements

≯℡__Kan透↙ 提交于 2019-12-21 21:37:12

问题


I am trying to read lines in a text file, tokenize the line and then go on and do the same to the next line in a switch and break block, but after my program reaches the first break, it exits the loop and ignores the rest of the file.

ifstream in("test.txt");
    string line,buffer;
    unsigned int firstLetter = 0;
    //istringstream iss;

    if( in.is_open() )
        {
            istringstream iss;
            while(getline(in,line))
            {
                iss.str(line);
                char firstChar = line.at( firstLetter );
                switch ( firstChar )
                {
                    case 'D':
                    while (getline(iss,buffer,'-'))
                    {//print each token, one per line
                        cout<<"buffer: "<<buffer<<" "<<endl;
                    }
                    break;
                    case 'R':
                    while ( getline(iss,buffer,'-') )
                    {cout<<"buffer: "<<buffer<<" "<<endl;}
                    break;
                }
            }               
        }

this is the content of the text file:

D-Rise of the Titans-25.50-2009-12
D-23 Jump Street-20.00-2013-5
D-Home Alone-24.00-1995-16
D-Twin Warriors-24.00-2011-14
R-XXX-Pierce-Hawthorne-11-13
R-Forbidden Kingdom-Pierce-Hawthorne-13-31
R-23 Jump Street-Troy-Barnes-1-3
R-Home Alone-Shirley-Bennett-1-3
R-Modern Family-Abed-Nadir-10-66

but when i run my code i get this:

buffer: D 
buffer: Rise of the Titans 
buffer: 25.50 
buffer: 2009 
buffer: 12

which is the content of line 1 in the text file, how can i go to the next line and keep doing that till the end of the file?


回答1:


You're changing your content of your std::istringstream object, but the state flags remain as prior (i.e., your eof bit is lit). An example, modified using your input data via stdin:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
    istream& in = std::cin;
    string line,buffer;

    istringstream iss;
    while(getline(in,line))
    {
        if (!line.empty())
        {
            iss.str(line);
            std::cout << "line at eof: " << iss.eof() << '\n';

            char firstChar = line.at(0);
            switch ( firstChar )
            {
                case 'D':
                    while (getline(iss,buffer,'-'))
                        cout<<"buffer: "<<buffer<<" "<<endl;
                    break;

                case 'R':
                    while ( getline(iss,buffer,'-') )
                        cout<<"buffer: "<<buffer<<" "<<endl;
                    break;
            }
        }
    }
}

Output

line at eof: 0
buffer: D 
buffer: Rise of the Titans 
buffer: 25.50 
buffer: 2009 
buffer: 12 
line at eof: 1
line at eof: 1
line at eof: 1
line at eof: 1
line at eof: 1
line at eof: 1
line at eof: 1
line at eof: 1

To fix this, either clear the state of the stream before each iteration, or just move the stringstream inside the while-loop, initialized with the line. The former is done below; I leave the latter as an exercise for you:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
    istream& in = std::cin;
    string line,buffer;

    istringstream iss;
    while(getline(in,line))
    {
        if (!line.empty())
        {
            iss.clear(); // <<=== ADDED HERE
            iss.str(line);
            std::cout << "line at eof: " << iss.eof() << '\n';

            char firstChar = line.at(0);
            switch ( firstChar )
            {
                case 'D':
                    while (getline(iss,buffer,'-'))
                        cout<<"buffer: "<<buffer<<" "<<endl;
                    break;

                case 'R':
                    while ( getline(iss,buffer,'-') )
                        cout<<"buffer: "<<buffer<<" "<<endl;
                    break;
            }
        }
    }
}

Output

line at eof: 0
buffer: D 
buffer: Rise of the Titans 
buffer: 25.50 
buffer: 2009 
buffer: 12 
line at eof: 0
buffer: D 
buffer: 23 Jump Street 
buffer: 20.00 
buffer: 2013 
buffer: 5 
line at eof: 0
buffer: D 
buffer: Home Alone 
buffer: 24.00 
buffer: 1995 
buffer: 16 
line at eof: 0
buffer: D 
buffer: Twin Warriors 
buffer: 24.00 
buffer: 2011 
buffer: 14 
line at eof: 0
buffer: R 
buffer: XXX 
buffer: Pierce 
buffer: Hawthorne 
buffer: 11 
buffer: 13 
line at eof: 0
buffer: R 
buffer: Forbidden Kingdom 
buffer: Pierce 
buffer: Hawthorne 
buffer: 13 
buffer: 31 
line at eof: 0
buffer: R 
buffer: 23 Jump Street 
buffer: Troy 
buffer: Barnes 
buffer: 1 
buffer: 3 
line at eof: 0
buffer: R 
buffer: Home Alone 
buffer: Shirley 
buffer: Bennett 
buffer: 1 
buffer: 3 
line at eof: 0
buffer: R 
buffer: Modern Family 
buffer: Abed 
buffer: Nadir 
buffer: 10 
buffer: 66 



回答2:


The problem is that you iterate through the contents of the istringstream until it fails. You then reuse the same istringstream in the rest of your lines. You need to clear the fail/eof bits in it.

Use iss.clear() to do this.

#include <iostream>
#include <sstream>
#include <fstream>

int main(){
  ifstream in('test.txt');
  if (in.is_open()){
    string line, buffer;
    istringstream iss;
    while (getline(in, line)){
      iss.str(line);
      iss.clear();
      char c = line[0];
      switch (c){
        case 'D':
          while (getline(iss, buffer, '-')){
            cout << "buffer: " << buffer << endl;
          }
          break;
        case 'R':
          while (getline(iss, buffer, '-')){
            cout << "buffer: " << buffer << endl;
          }
          break;
      }
   }
   return 0;
}


来源:https://stackoverflow.com/questions/31444137/c-reading-a-text-file-with-conditional-statements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!