0

I need to read this txt file but I don't understand what I'm doing wrong? http://pastebin.com/gPVbuvhb Here's my reading function

void Read(School & snew){
    string school, name, group;
    Student S;
    ifstream fd(CD);
    getline(fd, school, ';');

    S.SetSchool(school);
    cout << S.GetSchool() << endl;
    while(!fd.eof()){
        getline(fd, name, ',');
        fd >> ws;
        getline(fd, group, ' ');
        int Paz[Student::M];
        int kiek = 0;
        while(fd.peek()!= '\n' && !fd.eof()){
            fd >> Paz[kiek++];
        }
        fd.ignore();
    }
    fd.close();
}

Here's my Student class

class Student{
public:
    static const int M = 5;
private:
    string school, name, group;
    int *Marks; // dynamic array of student marks
    int nmax; // max size of array
    int n; // current size of array
    void IncreaseCapasity(int kiek);
public:
    Student(int nmax = 0);
    ~Student();

    void SetMarks(int mark);
    void SetSchool(string school);
    void SetName(string name);
    void SetGroup(string group);

    int GetMark(int i){return Marks[i];}
    string GetSchool(){return school;}
    string GetName(){return name;}
    string GetGroup(){return group;}
    int GetN(){return n;}
};

Student::Student(int nmax):Marks(NULL), n(n), nmax(nmax){
    if(nmax > 0){
        Marks = new int[nmax];
    }
}

Student::~Student(){
    if(Marks){
        delete [] Marks;
        Marks = NULL;
    }
}

void Student::IncreaseCapasity(int kiek){ // maybe this function is incorrect?
    if(kiek > nmax){ // if array increasing
        int *SNew = new int [kiek];
        for(int i=0; i<n; i++)
            SNew[i] = Marks[i];
        delete [] Marks;
        Marks = SNew;
        nmax = kiek;
    }if(kiek < nmax){ // if array decreasing
        int *SNew = new int [kiek];
        for(int i=0; i<kiek; i++)
            SNew[i] = Marks[i];
        delete [] Marks;
        Marks = SNew;
        n = nmax = kiek;
    }
}

void Student::SetMarks(int mark){
    if(n == nmax) IncreaseCapasity(n + M);
    Marks[n] = mark;
    n++;
}

void Student::SetSchool(string school){
    this->school = school;
}

void Student::SetName(string name){
    this->name = name;
}

void Student::SetGroup(string group){
    this->group = group;
}

when I'm reading int values fd >> Paz[kiek++]; I get this error Unhandled exception at 0x571121F8 (msvcp110d.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation reading location 0x0000000D.

DrYap
  • 6,097
  • 2
  • 26
  • 54
David
  • 2,812
  • 3
  • 21
  • 63
  • 1
    If you follow "normal" coding conventions we'll all find it much easier to read your code. Use descriptive variable names and start them with a lowercase letter. e.g. `student` instead of `S`. Also: what is `CD`? – John3136 Mar 01 '14 at 10:02
  • For one, you're checking for success or failure on exactly *zero* of your IO operations. [And your usage of `eof()` as your loop conditional is wrong](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – WhozCraig Mar 01 '14 at 10:04
  • 1
    You use `getline` with the delimiter argument of `';'`. There's no `;` character in the file, so the very first `getline` sees it as one big line and reads it all. There's nothing left for subsequent `getline`s. – n. 'pronouns' m. Mar 01 '14 at 10:04
  • Thanks! Working now :) – David Mar 01 '14 at 10:16
  • I just have edited my code. I dont understand why I get Access violation reading location error. I think with my function IncreaseCapasity is something wrong (but I'm not sure). I checked all my code, and still I can't understand why I get this silly error? – David Mar 01 '14 at 10:36
  • Is there are any solutions? – David Mar 01 '14 at 13:05

1 Answers1

1
getline(fd, school, ';');

reads from the fd stream, stopping at first occurence of ';'. Since there is no ';' in your file, it reads whole file into school string.

What you actually want to do is to parse your file line by line, constructing instance of istringstream using each line:

std::string line;
while (std::getline(fd, line)) {

    if (line.empty())
        continue;                      

    std::istringstream is(line);
    std::string name, group;
    if (std::getline(is, name, ',') && std::getline(is, group, ',')) {
        std::cout << "Name: " << name << " Group: " << group << std::endl;
    }

}

just don't forget to #include <sstream>.


Also note that:

while (!fd.eof()) {
    std::getline(...);
    // relying on getline call being successful here
}

is not safe, just use its return value directly.

LihO
  • 37,789
  • 9
  • 89
  • 156