问题
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