Connor Black
Connor Black

Reputation: 7181

C++ Reading Through File

If I open a new file for input, and I call input >> listSize; outside of a while loop and then continue calling input >> anothervariable will it automatically progress through the file or will it read the first line again?

Example:

input >> listSize;
BaseStudent* studentlist = new BaseStudent[listSize.atoi()];
while (!input.eof())
{
         input >> anothervariable; // I want this to start on the second line, not the first

}

The input file looks like this and we can code to the pattern (ignore the extra blank lines):

12

Bunny, Bugs

Math 90 86 80 95 100 99 96 93

Schmuckatelli, Joe

History 88 75 90

Dipwart, Marvin

English 95 76 72 88

Crack Corn, Jimmy

Math 44 58 23 76 50 59 77 68

Kirk, James T. 

English 40 100 68 88

Lewinsky, Monica

History 60 72 78

Nixon, Richard

English 35 99 70 70

Lincoln, Abraham

History 59 71 75

Clinton, William

Math 43 55 25 76 50 58 65

Duck, Donald

English 34 100 65 65

Duck, Daffy

History 55 70 70

Bush, George

Math 44 54 29 75 50 55 60

Upvotes: 1

Views: 1043

Answers (3)

Jerry Coffin
Jerry Coffin

Reputation: 490623

Others have already pointed out that the answer to your question is "yes", so I won't worry about that part.

As for the rest, I think I'd write it a bit differently. Your file obviously represents structured data, and I'd write the code to reflect that fact reasonably directly. I'd start by defining a structure reflecting the data in the file:

struct test_scores {   // maybe not tests. Change if appropriate
    std::string student;
    std::string course;
    std::vector<int>
};

Then, I'd write a function to read one of those items from the file:

std::istream &operator>>(std::istream &is, test_scores &ts) { 
    // for the moment assuming there are no blank lines in the file.
    std::getline(is, ts.student);
    std::string temp;
    std::istringstream buffer(temp);
    buffer >> ts.course;
    int score;
    while (buffer>>score)
        ts.scores.push_back(score);
    return is;
}

In C++, however, it's really easier to just read whatever amount of data is there, than to prefix the data with the count. Given that count is present, the easiest thing to do is probably to just read and ignore it:

std::string ignore;
std::getline(infile, ignore);

Then we can read the real data pretty easily:

std::vector<test_scores> student_scores;
test_scores tmp;

while (infile >> tmp)
    student_scores.push_back(tmp);

...or, we can use C++'s handy-dandy istream_iterators to simplify the code even more:

std::vector<test_scores> student_scores((std::istream_iterator<test_scores>(infile)),
                                         std::istream_iterator<test_scores>());

That's it -- it defines the vector and initializes it from the input file, all in one (fairly) simple operation.

Upvotes: 2

Loki Astari
Loki Astari

Reputation: 264669

When you read from a stream the data is used.
Next time will read from the last point read "up-to"

Though stream operator >> will skip proceeding white space but will not read the white space after the object (which can be a pain if your input is line orientated, as you don't see new lines easily).

The best way to get around this is to explicitly read lines at a time then parse the line:

std::string    line;
std::getline(input, line);   // Read a line

// Now look what is in the line.
std::stringstream  linestream(line);
linestream >> dataItem1 >> dataItem2 >> dataItem3; /// etc.

Also note:

 // This is not good. If there are any errors in your file it will loop forever.
 while (!input.eof())

It is normal to loop over the input using:

 while(input >> data)
 {
      // If you get in here then the read worked.
 }
 // You will fall out of the loop when
 //   1) EOF
 //   2) There is an error.

So if we combine both techniques:

 std::string line1;  // Name,
 std::string line2;  // Scores
 std::string empty;  // Empty line in data file.

 while(std::getline(input, line1) && std::getline(line, empty) && std::getline(input, line2))
 { 
       //  line1 => Bunny, Bugs
       //  empty => 
       //  line2 => Math 90 86 80 95 100 99 96 93

       // Enter the loop only if we get a name and a score line
      std::getline(line, empty); // Optionally read a trailing line (there may not be a last one);

      // dataStream   => Math 90 86 80 95 100 99 96 93
      std::stringstream dataStream(line2);
      std::string   subject;
      int score;

      dataStream >> subject;   // subject => Math
      while(dataStream >> score)
      {
          // We read another score from the data line;

          // score is 90 first time 86 second time etc.
      }
 }

Upvotes: 3

stark
stark

Reputation: 13189

Thew file pointer is always advanced past what you have already read.

Upvotes: 0

Related Questions