简体   繁体   中英

Reading in from file gives unexpected output

I am working on reading in from a file and parsing through data from command line argument for homework. And I ran in a wall and I do not know what's the problem, and I hope I could get some advice on what I am missing.

The data file is composed thusly; on the first line, it has number of total lines. For each line after that, it is a line of string separated by | character. I need the '|' character because I want to split my string into substrings.

Here is an example of input file.

3
league of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

Here is my code.

int main( int argc, char* const argv[] )
{

 //change string to char* so I can check through each char to see if the 
 //thing I read in is '|' character.
 String Data = (argv[1]);
 ifstream fin (Data.c_str());

 //check whether the file is open.
 if ( !fin.is_open() )
 {
    cout << "Could not open file" << endl;
 }

 else
 {
     int dataLines;
     char dataBuffer[100];

     //The first integer I read in will be how many lines I will loop through
     fin >> dataLines;
     //ignore the new line character and do not include it in the count of
     //dataLines.
     fin.ignore();

     //use noskipws so I can recognize whitespaces.
     fin >> noskipws >> dataBuffer;

     //TEST CODE: COMMENTED OUT FOR NOW.
     //cout<<dataBuffer<<endl;

     //loop for the number of lines
     for(int i = 0; i < dataLines; i++)
     {

         fin.getline(dataBuffer, 100);
         //print the buffer for checking
         cout<<dataBuffer<<endl;
     }
 }
 //close the file.
 fin.close();
 return 0;

}

The result is supposed to look like this.

league of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

The actual result looks like this

of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

The first word that I read in from buffer is gone. "league" is the one that is missing, and I tried to see what the problem is by inserting the test code at the location specified in my code. With the given test code, my output is

league
of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart

So the problem is that between reading in the file with noskipws and the forloop that loops over dataLine. Before the forloop my buffer is league . Yet once I enter the loop it is passed that and goes straight to of .

What am I missing here? What could be a possible solution?

Main problem:

fin >> noskipws >> dataBuffer;

Does two things. 1. >> noskipws turns off automatically skipping whitespace, unnecessary because of how OP is reading the stream. 2. >> dataBuffer reads the first word from the stream, in this case consuming the word "league"

Solution: Don't do this.

Other problems:

fin.ignore();

will ignore exactly one character. But what if someone left a nigh-invisible space after the count? Instead use

fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

to ensure the rest of the line is consumed in its entirity.

char dataBuffer[100];

Why make yourself suffer? Instead use

std::string dataBuffer;

Recommendation:

Use std::stringstream and std::getline to tokenize the lines on '|'

std::stringstream stream(databuffer);
std::string token;
while (std::getline(stream, token, '|')
{
    std::cout << token << ',';
}

You do not need the following line:

fin >> noskipws >> dataBuffer;

Tested with g++ 4.8.3 2 on RHEL 7.1

Thanks User 4581301. It reads in the data correctly and split with '|' character. Now I can work on storing the data into classes.

for anyone who may have same problem, this is the fixed up version of code.

int main( int argc, char* const argv[] )
{

String Data = (argv[1]);
ifstream fin (Data.c_str());

if ( !fin.is_open() )
{
   cout << "Could not open file" << endl;
}

else
{
    int dataLines;
    char dataBuffer[100];

    fin >> dataLines;
    fin.ignore();

    for(int i = 0; i < dataLines; i++)
    {
        while(fin.getline(dataBuffer, 100, '|'))
        {
            cout<<dataBuffer<<endl;// check to see if it reads in correctly.
        }
    }
}
fin.close();
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