Question

Working on a project for a C++ class I have run into a wall. We are practicing file i/o with a fixed length Employee record. I am creating the Employees fine, storing them into a vector of unique_ptr, and then attempting to loop through these, writing to a file, clearing the vector, and then reading them back into the vector from the file.

The problem appears to be with how I attempt to read them back in. Everything looks correct in the file after writing that I can tell. Below is what I am attempting to do. However, after reading in the Employee records, it loops one extra time and does not recognize the end of the file, filling members with junk data. I can't figure out why, though, since I am writing out an exact number of bytes and then reading back the same number.

When reading the employee records back into the vector from the file, is it wrong to do:

while (emprecs.good())

I suspect that is what is getting me into trouble here, but cant figure out how to test/debug it. Here is the applicable code:

Employee.h

class Employee{
    int id;
    std::string name;
    std::string address;
    std::string city;
    std::string state;
    std::string country;
    std::string phone;
    double salary;

    struct EmployeeRec{ // Employee file for transfers
        int id; 
        char name[31];
        char address[26];
        char city[21];
        char state[21];
        char country[21];
        char phone[21];
        double salary;
};

    void write(std::ostream&) const;
    static std::unique_ptr<Employee> read(std::istream&);
};

Employee.cpp

// Write a fixed-length record to current file position
void Employee::write(ostream& os) const{
    EmployeeRec outbuf;
    outbuf.id = id;
    strncpy(outbuf.name, name.c_str(), 30)[30] = '\0';
    strncpy(outbuf.address, address.c_str(), 25)[25] = '\0';
    strncpy(outbuf.city, city.c_str(), 20)[20] = '\0';
    strncpy(outbuf.state, state.c_str(), 20)[20] = '\0';
    strncpy(outbuf.country, country.c_str(), 20)[20] = '\0';
    strncpy(outbuf.phone, phone.c_str(), 20)[20] = '\0';
    outbuf.salary = salary;
    os.write(reinterpret_cast<const char*>(&outbuf), sizeof outbuf);
}

// Read record from current file position
std::unique_ptr<Employee> Employee::read(std::istream& is){
    EmployeeRec inbuf;
    is.read(reinterpret_cast<char*>(&inbuf), sizeof inbuf);
    unique_ptr<Employee> emp(new Employee());
    if (is.good()) {
        emp->id = inbuf.id;
        emp->name = inbuf.name;
        emp->address = inbuf.address;
        emp->city = inbuf.city;
        emp->state = inbuf.state;
        emp->country = inbuf.country;
        emp->phone = inbuf.phone;
        emp->salary = inbuf.salary;
    }
    return emp;
}

Driver.cpp

// employee.bin is a new file that I will be writing to and then reading from
// Write all employee's currently in the vector to the file
fstream emprecs("employee.bin", ios::in | ios::out | ios::binary | ios::trunc); 
    _ASSERT(emprecs.is_open()); 
    for (size_t i = 0; i < EmpVect.size(); ++i){
                // EmpVect is a vector of unique_ptr<Employee>
        (EmpVect[i])->write(emprecs);
    }

// Clear the vector in preparation to read the employees back in from the file
EmpVect.clear();

// Move back to beginning of stream
emprecs.seekp(0, ios::beg);

// Read employees back in from the file
// This loops an extra time with junk data... can't figure out why, though
// Shouldn't the failbit be set once I reach end of file? I am missing something here.
while (emprecs.good()){
    EmpVect.push_back(std::move(Employee::read(emprecs)));
}
Était-ce utile?

La solution

On std::unique_ptr<Employee> Employee::read(std::istream& is)

When is.good() return false, the emp still returned which is a struct and would not be initialized with constucter(so with junk data).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top