简体   繁体   中英

C++ reading a text file with conditional statements

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?

You're changing your content of your std::istringstream object, but the state flags remain as prior (ie, 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 

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;
}

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