File handling in C++

Hello,
Can someone please help me with the file because when I execute it and open the file the format of the data is weird and it doesn't save the data of the people that I input in add_people(). what am I doing wrong?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include<iostream>
#include<fstream>
using namespace std;
    
    const int PERSONS_LIMIT = 50;

    int countPersons = 0;

    class Persons 
{
    public:
        int Id;
        string Name;
        int Age;
        string Dob;
        string Position;
        char Gender;

	void print_info() 
    {
        cout << "\n ID : " << Id
            << "\n Name : " << Name
            << "\t Age: " << Age
            << "\t DOB: " << DOB
            << "\t Position: " << Position
            << "\t Gender: " << Gender;
    }
    };

    Persons obj[PERSONS_LIMIT];

    void add_people() 
	{
 	   if (countPersons < PERSONS_LIMIT)
        {
            cout << "\n Enter id (number): ";
            cin >> obj[countPersons].Id;
            cout << "\n Enter Name (20 characters): ";
            cin >> obj[countPersons].Name;
            cout << "\n Enter Age (number): ";
            cin >> obj[countPersons].Age;
            cout << "\n Enter DOB (dd-mm-yy): ";
            cin >> obj[countPersons].Dob;
            cout << "\n Enter Position : ";
            cin >> obj[countPersons].Position;
            cout << "\n Enter Gender (M/F) : ";
            cin >> obj[countPersons].Gender;
            countPersons++;
        }
        else
        {
            cout << "\n Error : Limit is only " << PERSONS_LIMIT;
        }
    }

    void printAll() {
        cout << "\n **** **** Printing All Records **** ****";
        cout << "\n total number of persons : " << countPersons << endl;
        for (int i = 0; i < countPersons; i++) 
	{
            obj[i].print_info(); 
        }
    }

    void printbyAge() {
        cout << "\n **** **** Printing All Records by Age********";
        int count50plus = 0;
        int count40plus = 0;
        int lessthen40 = 0;

        for (int i = 0; i < countPersons; i++) {
            if (obj[i].Age > 50)
                count50plus++;
            else if (obj[i].Age > 40)
                count40plus++;
            else
                lessthen40++;
        }

        cout << "\n Persons more than 50 : " << count50plus;
        cout << "\n Persons more than 40 : " << count40plus;
        cout << "\n Persons less than 40 : " << lessthen40;
    }


    void printSexCount() {
        cout << "\n **** **** Printing All Records by Sex Count ********";
        int malecount{};
        int femalcount{};

        for (int i = 0; i < countPersons; i++)
	{
            if (obj[i].Gender == 'M')
                malecount++;
            else if (obj[i].Gender == 'F')
                femalcount++;
        }
        cout << "\n Number of Male : " << malecount;
        cout << "\n Number of Female : " << femalcount;
    	}

  	void exp_file()
    	Persons ac;
    	ofstream myfile;
    	myfile.open("File1.txt", ios::app);
    	myfile.write(reinterpret_cast<char*> (&ac), sizeof(Persons));
    	myfile.close();
    	cout << "\n\n\t\t\t Data are saved in file";
	}
  

  int main() {

        int choice = -1;

        while (choice != 0)
{
            cout << "\n\n ============Program Menu==========";
            cout << "\n 1 Input Records ";
            cout << "\n 2 Print All Records";
            cout << "\n 3 Print by Age";
            cout << "\n 4 Print by Sex count";
            cout << "\n 5 Export data to file";
            cout << "\n 0 to exit";

            cout << "\n Enter you choice : ";
            cin >> choice;

            switch (choice) 
	{

            case 1: add_people(); 
	break;
            case 2: printAll(); 
	break;
            case 3: printbyAge(); 
	break;
            case 4: printSexCount(); 
	break;
            case 5: exp_file(); 
	break;
            case 0: cout << "\n thank you for using software !!"; 
	break;
            default: cout << "\n Error: Invalid Selection";
            }

        }

        return 0;

    }
First, your issue is that Persons ac; on line 103 does not have any valid information in it other than what's there by default. You need to put actual information in there before attempting to save it.

But, more importantly, your Persons class (which, by the way, is just a single Person) is NOT a "POD" type. This essentially means it contains pointers, as you have with std::string. Aside from short-string optimization, the actual string data is not stored directly in the std::string's bytes, so you shouldn't directly write a std::string to file as you do on line 106.

Instead, you know how you already have your print_info function?
What you can do is instead of printing it to cout (stdout), you can generalize it to print to any output stream.

1
2
3
4
5
6
7
8
9
    void print_info(ostream& out) 
    {
        out << "\n ID : " << Id
            << "\n Name : " << Name
            << "\t Age: " << Age
            << "\t DOB: " << DOB
            << "\t Position: " << Position
            << "\t Gender: " << Gender;
    }


Then you can:
1
2
3
4
5
6
Person person;

// Fill in information for person

ofstream myfile("File1.txt", ios::app);
person.print_info(myfile);

However, doing it this way will be more complicated if you need to read from the file in the future. Is reading from the file part of the requirements of the assignment?

Enter Name (20 characters): ";
Note that nothing in the program prevents the user from typing in more than 20 characters. I'm wondering if your instructor is assuming that small-string optimization will be used here.
Last edited on
You also have a couple of misspellings, remember C++ is case sensitive "a" is not the same as "A".

There also appears to be some mismatched braces, using consistent indentation should help you locate this type of problem.

Lastly you really should stop using the horrible global variables and learn to pass variables to and from your functions as required.


But, more importantly, your Persons class (which, by the way, is just a single Person) is NOT a "POD" type. This essentially means it contains pointers, as you have with std::string. Aside from short-string optimization, the actual string data is not stored directly in the std::string's bytes, so you shouldn't directly write a std::string to file as you do on line 106.


I am sort of torn when these things come up. At times like this where you have limits already (eg you said 20 chars for a name) in place I am tempted to use a c-string in the class privately and cast/expose that as a string type in the getter/setter code, to allow the class to be written in binary directly. There is no free lunch; doing that is messy, serialize the class is messy.
Last edited on
Unless it is an actual requirement of the assignment to use binary files, I suggest you stick with regular text files as they are more portable and less problematic and much easier to "see" what is being written to the file.


jonnin wrote:
I am sort of torn when these things come up. At times like this where you have limits already (eg you said 20 chars for a name) in place I am tempted to use a c-string in the class privately
In this particular case, I agree, it would actually be simpler to just use a c-string (char array), as long as input is correctly sanitized (e.g. cin.getline(arr, 20) ).

It still has the portability problem that jlb mentioned, but it would do the job.
Last edited on
I copied and pasted this form an older version of my code so the Enter Name: is not limited I just forgot to delete the "20 character" and also reading from the file is not part of the requirement, thank you for that. But what I am trying to do is the Name,Age,Id...etc I write on the "Add Employee" function, to save those data to a file? It seems simple but yet I am stuck!
Then I suggest you stick with plain text files, possibly something like a Comma Separated Values type of file, where you have each Person on one line and the fields separated by a comma. Think about overloading the input and output stream operator<<, operator>> to read and write the data.

If you never plan to "read" the file there is no real reason to "write" the file.


Topic archived. No new replies allowed.