0

I have written a simple program in two ways. The program is for getting data from a user, storing it in a txt file, retrieving the data and displaying it. The problem is that one approach works while the other does not. I dont understand why.

The one that works is this:

#include <iostream>
#include <fstream>

using namespace std;

class customer{
    public:

    // Declaring member variables and functions
    string name, address, telNo;
    int age;
    void createCustomer();
    void displayInfo(string inputName);
};

// Member function of customer to enter new customer details
void customer::createCustomer(){
    customer c;
    ofstream file;
    file.open("customers.txt", ios::out);
    cout << "Enter Name: ";
    cin >> c.name;
    cout << "Enter Age: ";
    cin >> c.age;
    cout << "Enter Address: ";
    cin >> c.address;
    cout << "Enter Telephone Number: ";
    cin >> c.telNo;
    file.write((char*)&c, sizeof(c));
    file.close();
    cout << "\n";
}

// Member function of customer to display customer information
void customer::displayInfo(string inputName){
    customer c;
    ifstream file;
    file.open("customers.txt", ios::in);
    if(!file){
        cout << "Could Not Open customers.txt File\n";
        return;
    }
while(!file.eof()){
file.read((char*)&c, sizeof(c));
if (inputName == c.name){
    cout << "\n";
    cout << "Name-------------> " << c.name << endl;
    cout << "Age--------------> " << c.age << endl;
    cout << "Telephone Number-> " << c.telNo << endl;
    cout << "Address----------> " << c.address << endl;
    cout << "\n";
    break;
    }
}
    file.close();
}

int main(){
    customer c;
    c.createCustomer();
    c.displayInfo("name");
    return 0;
}

It gives the following output:

Enter Name: name

Enter Age: 21

Enter Address: add

Enter Telephone Number: telno

Name-------------> name

Age--------------> 21

Telephone Number-> telno

Address----------> add

The one that doesnt work is this:

#include <iostream>
#include <fstream>

using namespace std;

class customer{
    public:

    // Declaring member variables and functions
    string name, address, telNo;
    int age;
    void createCustomer();
    void displayInfo();
};

// Member function of customer to enter new customer details
void customer::createCustomer(){
    customer c;
    ofstream file;
    file.open("customers.txt", ios::out);
    cout << "Enter Name: ";
    cin >> c.name;
    cout << "Enter Age: ";
    cin >> c.age;
    cout << "Enter Address: ";
    cin >> c.address;
    cout << "Enter Telephone Number: ";
    cin >> c.telNo;
    file.write((char*)&c, sizeof(c));
    file.close();
    cout << "\n";
}

// Member function of customer to display customer information
void customer::displayInfo(){
    string inputName = "name";
    customer c;
    ifstream file;
    file.open("customers.txt", ios::in);
    if(!file){
        cout << "Could Not Open customers.txt File\n";
        return;
    }
    while(!file.eof()){
        file.read((char*)&c, sizeof(c));
        if (inputName == c.name){
            cout << "\n";
            cout << "Name-------------> " << c.name << endl;
            cout << "Age--------------> " << c.age << endl;
            cout << "Telephone Number-> " << c.telNo << endl;
            cout << "Address----------> " << c.address << endl;
            cout << "\n";
            break;
        }
    }
    file.close();
}

int main(){
    customer c;
    c.createCustomer();
    c.displayInfo();
    return 0;
}

All I have done is put the string inputName variable inside the function instead of passing it as an argument.

It gives only the following output:

Enter Name: name

Enter Age: 21

Enter Address: add

Enter Telephone Number: telno

If I remove the if condition:

while(!file.eof()){
    file.read((char*)&c, sizeof(c));
    //if (inputName == c.name){
        cout << "\n";
        cout << "Name-------------> " << c.name << endl;
        cout << "Age--------------> " << c.age << endl;
        cout << "Telephone Number-> " << c.telNo << endl;
        cout << "Address----------> " << c.address << endl;
        cout << "\n";
        break;
    //}
}

i get the following output:

Enter Name: name

Enter Age: 21

Enter Address: add

Enter Telephone Number: telno

Name-------------> 0∙⌂┼

Age--------------> 21

Telephone Number-> name

Address----------> §

Why are the name and address fields outputting random symbols and the telephone number field outputting value of the name field?

lazarus v
  • 13
  • 3
  • Who wants the credit for explaining that his binary reading/writing of the structure is drastically wrong, and how he's reading/writing pointer addresses instead of content? It's too early where I am to write out the basics of what he's actually doing when reading/writing the struct and why that's wrong. – Kevin Anderson Jan 04 '23 at 13:05
  • This is the least of your problems but a problem nevertheless: [eof is wrong](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – n. m. could be an AI Jan 04 '23 at 13:11
  • 1
    @KevinAnderson It's a difficult concept to explain to a beginner who has no sense of how things work 'under the hood'. – john Jan 04 '23 at 13:11

1 Answers1

2

Neither program is correct. It's an error use read on a type like customer because it contains sub-objects that need constructing, namely the string members name, address and telNo. Calling read does not call any constructor for the objects you are reading and so this is invalid.

Since read does not work for strings it doesn't make any sense to use write on a class containing a string either because you won't be able to read back what you have written.

If you want to write a customer to a file you can do it something like this

file << c.name << ' ' << c.age << ' ' << c.telNo << ' ' << c.address << '\n';

and then something similar for reading (although you then you would have to be careful of any spaces in your data).

john
  • 85,011
  • 4
  • 57
  • 81
  • One extra thing: you may want to explain the Small String Optimization and how that can *seem* to give the results they want sometimes - https://blogs.msmvps.com/gdicanio/2016/11/17/the-small-string-optimization/ – Kevin Anderson Jan 04 '23 at 13:20
  • @KevinAnderson I'll pass on that. I remember a post with similar program which was working for the poster due to SSO. Despite repeated attempts to explain the problem he point blank refused to believe me and in the end I gave up. But if the OP asks any further questions I'll do my best to explain. – john Jan 04 '23 at 13:27
  • The error (in both cases) should be obvious if OP cuts the program in two: One program creates a customer and writes it to disk, the other program reads from file and displays the read data. That way it should be very unlikely that data wilds up randomly lining up in memory to make it look like it is working. – Frodyne Jan 04 '23 at 14:02