0

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.

Audun Olsen
  • 491
  • 5
  • 14
  • 3
    Are you sure it's `Letter::writeData()` etc and not `Garbage::writeData()` ? – Suhaib Ahmad Dec 07 '17 at 04:56
  • Helpful reading (because if it doesn't get you here, it will get you eventually): [Why is iostream::eof inside a loop condition considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – user4581301 Dec 07 '17 at 06:29
  • 3
    Careful here: `sizeof(garbages)` will get you the size in bytes of the array, not the number of `Garbage`s in the array. You want `sizeof(garbages)/sizeof(garbages[0])` (size of the array divided by the size of an element in the array). A better option in modern C++ is to use `std::array` which has a `size` method to return the number of elements in the array. – user4581301 Dec 07 '17 at 06:33
  • You're using `cout`, which is a stream, but you don't seem to notice that `file` is also a stream and can also work similarly. Check out [operator>>()](gRZ=uUrZJ28EPQXMcNocpd). – user1118321 Dec 07 '17 at 06:37
  • Expanding on @user1118321 's comment, mostly because it looks like their link got lunched, you can `file >> num1`. With a [bit of `file.ignore`](http://en.cppreference.com/w/cpp/io/basic_istream/ignore) and you can do what you want, but also look at Option 2 of [this linked answer](https://stackoverflow.com/a/7868998/4581301) for a somewhat more robust approach – user4581301 Dec 07 '17 at 06:55
  • @user4581301 Also, in C++17, `std::size()` is specialised for raw C-style arrays, *finally*. – underscore_d Dec 07 '17 at 12:54

1 Answers1

1

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.

Caleth
  • 35,377
  • 2
  • 31
  • 53
  • 1
    You also need to fix whether the class is named `Letter` or `Garbage` and the other problems with it, like [here](https://wandbox.org/permlink/PmccWIhTd0DUtIt0) – Caleth Dec 07 '17 at 09:39
  • Sorry for the inconsistencies, it was meant to say Garbage, not letter. – Audun Olsen Dec 07 '17 at 12:11
  • And I should have specified, in the data structure file, the name value may include whitespaces (multiple words on one line). So I'm guessing I need to combine getline and the >> operator? How would I do that? – Audun Olsen Dec 07 '17 at 12:22
  • Works like a charm now! Not knowing of `ws` or `file.ignore();` was the one detail I was missing, thank you! – Audun Olsen Dec 07 '17 at 13:20
  • One caveat: `file >> num1 >> num2 >> ws;` reading of `ws` will fail and set the stream state if the file ends without that final linefeed. You won't notice unless you check the stream state to make sure you successfully read data before using it, but if you are *not* checking, well, that'll get you sooner or later, too. – user4581301 Dec 07 '17 at 16:57