Search code examples
c++fstreamifstreamgetline

Challenging data file format which needs to be read into vars of array containing class objects


I have a program with 5 instances of the class Garbage, garbage has 3 variables I need to update from a data file. The first is a char array, the other two integers. All except the updating the int variables work, and I have no clue of how to achieve that, so any help is greatly appreciated. My code:

#include <iostream>
#include <cctype>
#include <cstring>
#include <fstream>
#include <iomanip>

using namespace std;

class Garbage {
  public:
    void writeData();
    void updateFromFile( ifstream & file );
  private:
    char name[40];
    int num1;
    int num2;
};

void Garbage::writeData() { 
  cout << name << ", " << num1 << ", " << num2 << endl;
}

void Garbage::updateFromFile ( ifstream & file ) {

  if ( !file.eof() ) {

    file.getline(name, STRLEN);

    /*
    Int variables from Garbage class need to be updated here
    */

  }

}

void readFile() {

  ifstream infile("data.txt");

  for(int i = 0; i < sizeof(garbages)/sizeof(garbages[0]); i++) {
    garbages[i].updateFromFile(infile);
  }

}

Garbage garbages[5];

int main() {
  readFile();

  for(int i = 0; i < sizeof(garbages)/sizeof(garbages[0]; i++) {
    garbages[i].writeData();
  }

  return 0;
}

The data structure of "data.txt" is as follows:

lorem A
10 20
ipsum B
20 30
dolor C
30 40
sit D
40 50
amet E
50 60

lorem is the char array (may include whitespaces!), 10 is num1 and 20 is num2 and so on. Due to this being a school assignment, I cannot change the structure of the c++ code nor the data file structure. And If it's possible to achieve this without additional preprocessing directives, that would be preferable.

Any and all input is greatly appreciated!

Edit: fixed class member function naming inconsistencies and poor use of sizeof(). I also added an optional letter in name fields of the data structure showing that name may include whitespaces, and thus I can't rely on the ">>" operator alone and must use getline.


Solution

  • Stream operators consume whitespace. All you need is

    void Letter::updateFromFile ( ifstream & file ) {
      file.getline(name, STRLEN);
      file >> num1 >> num2 >> ws; // eat the end of line
    }
    

    Additional: If you have control over the parameter, I would change it to istream &, because there is nothing file stream specific going on. Strive to use the least specific type that works correctly.

    C style arrays are more quirky, harder to use safely, and less featureful than std::array and std::vector. The only reason to use them today is to share definitions with C code.