Mike
Mike

Reputation: 11

Receiving Error "member function must be called or its address taken in function" in C++

I am trying to write a program to do various things with a struct array, and I'm having trouble with the functions. I keep getting error E2235 "Member function must be called or its address taken in function read(student *, int)" and I'm not really sure what's causing this error. My code is as follows:

#include <iostream.h>
#include <fstream>
struct student{
    string first;
    string last;
    string id;
    double GPA;
    int age;
};
void menu();
void read(student* data, int x);
int main(){

bool quit=false;
char choice;
student data[20];
cout<<"Welcome!"<<endl;
//the program is menu driven, so a switch statement allows for many choices
while(!quit){
    menu();
    cin>>choice;
    switch(choice){
        case '1': read(data, 20); break;
        case '2': break;
        case '3': break;
        case '4': break;
        case '5': break;
        case '6': break;
        case '7': break;
        case '8': cout<<endl<<"Goodbye!\n"; quit=true; break;
        default: cout<<"I think you're doing it wrong. Please try again.";
        }
    }
} 

//menu output so the user knows what they're doing
void menu(){
    cout<<endl;
    cout<<"What would you like to do?"<<endl;
    cout<<"(1) - Read data into the database"<<endl;
    cout<<"(2) - Add a student"<<endl;
    cout<<"(3) - Remove a student"<<endl;
    cout<<"(4) - List all students"<<endl;
    cout<<"(5) - Compute the average GPA and SD of the database"<<endl;
    cout<<"(6) - View Student Information"<<endl;
    cout<<"(7) - Save the database"<<endl;
    cout<<"(8) - Exit"<<endl;
}

//the problem function
void read(student* data, int x){
    ifstream infile;
    infile.open("StudentStruct.txt");
    int k=0;
    string first, last, id;
    double GPA;
    int age;
    while(!infile.eof&&k<x){
        infile>>first;
        data[k].first;
        infile>>last;
        data[k].last;
        infile>>id;
        data[k].id;
        infile>>GPA;
        data[k].GPA;
        infile>>id;
        data[k].age;
        k++;
    }
    cout<<"The database now contains "<<k<<" data entries from 'StudentStruct.txt'"<<endl;
}

What could be causing this error, and how should I fix it?

Upvotes: 1

Views: 3662

Answers (2)

Nik Bougalis
Nik Bougalis

Reputation: 10613

I think that is an awkwardly worded error message related to the code inside the while condition, with the infile.eof. You are not using the function-call convention (i.e. infile.eof()) and so the compiler doesn't know what you are trying to do with that code: call the member function or take the its address. So it throws up a warning.

There's also another issue with the way you read student data from the file:

string first, last, id;
double GPA;
int age;

while(!infile.eof&&k<x){
    // Here you read a string into the local variable 'first'
    infile>>first;

    // And here you do... what? referencing the 'first' member variable of the k'th student.
    data[k].first;

    // Rinse, lather repeat
    infile>>last;
    data[k].last;
    infile>>id;
    data[k].id;
    infile>>GPA;
    data[k].GPA;
    infile>>id;
    data[k].age;
    k++;
}

Look carefully at what you are doing: your data is never populated with students. You read values into local variables and then throw the results away, never using them. Integrating chris' suggestion about eliminating the use of infile.eof() try this instead:

while((k < x) && (infile >> data[k].first)) 
{
    infile >> data[k].last;
    infile >> data[k].id;
    infile >> data[k].GPA;
    infile >> data[k].age;

    k++;
}

Upvotes: 1

Jerry Coffin
Jerry Coffin

Reputation: 490048

I would break the problem function into a couple of separate pieces. One would just read a single "record" from the file. The other would use that to read all the records. The first, by convention, is named operator>> (aka a "stream extractor):

std::istream &operator>>(std::istream &infile, student &d) { 
    infile >> d.first;
    infile >> d.last;
    infile >> d.id;
    infile >> d.GPA;
    infile >> d.age;
    return infile;
}

The second function uses that one to read all the data from the file. For it, you do not want to use while (!whatever.eof()) -- that's pretty much guaranteed to fail. There are a couple of alternatives. One is like:

while (infile >> some_student)
    students.push_back(some_student);

Another possibility is to use an istream_iterator, which can pretty much automate the whole loop:

std::vector<student> students((std::istream_iterator<student>(infile)),
                                std::istream_iterator<student>());

That defines the students vector, and initializes it from the pair of istream_iterators, which implicitly loops through the file, reading all the data (using the stream extractor from up above.

As that implies, I'd also use std::vector<student> (if possible) instead of student *, so it can be resized when/if needed to accommodate the data. Using those, the function becomes something like this:

std::vector<student> read() { 
    std::ifstream infile("StudentStruct.txt");
    std::vector<student> students((std::istream_iterator<student>(infile)),
                                    std::istream_iterator<student>());
    return students;
}

Upvotes: 2

Related Questions