stuck in very basic file stream function

this is a simple family record program. there is some problem in function void read(). i cant figure it out, when the function gets executed it stucks in infinite loop where eof() is not reached i think. pls help

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
#include <iostream>
#include<fstream>
#include<stdlib.h>
#include<conio.h>

using namespace std;

struct person
{
    char name[80];
    int age;
    char dob[50];
    char occu[50];
    char son[50];
    char dau[50];
    char grandf[50];
    char grandm[50];
    char grands[50];
    char grandd[50];
};

class family
{
    person p1;
    person p2[10];
    int l=0; int b=0;   // b= number of entries. which is assigned to this variable in countline()
    string str;
    public:


    void write()     //function to write the record in a txt file
    {
        char ch='y';
        while(ch=='y' || ch=='Y')
        {
        system("cls");
        cout<<"\nenter name: "; cin.ignore(); cin.getline(p1.name,80);
        cout<<"\nenter age: "; cin>>p1.age;
        cout<<"\nenter date of birth dd/mm/yy: "; cin.ignore(); cin.getline(p1.dob,50);
        ofstream outfile;
        outfile.open("record.txt",ios::out|ios::app);
        outfile<<p1.name<<endl;
        outfile<<p1.age<<endl;
        outfile<<p1.dob<<endl;
        outfile.close();
        cout<<"\nRecord updated. Do you want to enter another record? ";
        cin>>ch;
        }
    }

    void read()       //function reads from txt file and assign values to struct objects
    {
        ifstream infile;
        infile.open("record.txt",ios::in);
        infile.seekg(0,ios::beg);
        while(!infile.eof())
        {
          for(int i=0;i<b;i++)
            {
                infile.getline(p2[i].name,80);
                infile>>p2[i].age;
                infile>>p2[i].dob;

            }
        }



        infile.close();
    }
    void show()   // function displays the entire record
    {
        system("cls");
        for(int i=0;i<b;i++)
        {
            cout<<"\nname: "<<p2[i].name<<"\tage: "<<p2[i].age<<"\tdate of birth: "<<p2[i].dob;
        }
        cout<<"\npress any key to continue";
        getch();

    }

    void countline()  //function to count number of lines in  txt file
    {
        ifstream infile("record.txt");
        while(getline(infile,str))
        {
            l++;

        }
        infile.close();
        b=l/3;


    }
};







int main()
{

family fm;
while(1)
{
    int choice;
    cout<<"---------Family record-----------"<<endl;
    cout<<"\n\n1. Enter a new record"<<endl<<"2. Show all records"<<endl<<"3. exit"<<endl;
    cin>>choice;
    switch(choice)
    {
    case 1:
       fm.write();
       break;

    case 2:
        fm.countline();
        fm.read();
        fm.show();
        break;

    case 3:
        exit(1);
        break;

    }

    system("cls");

}
    return 0;
}
In your main function, your while loop never ends.
Last edited on
Based upon your design, consider:

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
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>

using namespace std;

struct person {
	char name[80];
	int age;
	char dob[50];
	char occu[50];
	char son[50];
	char dau[50];
	char grandf[50];
	char grandm[50];
	char grands[50];
	char grandd[50];
};

class family {
	person p1;
	person p2[10];
	int b = 0;   // b= number of entries. which is assigned to this variable in countline()

public:
	void write()     //function to write the record in a txt file
	{
		char ch = 'y';
		while (ch == 'y' || ch == 'Y')
		{
			//system("cls");
			cout << "\nenter name: ";
			cin.ignore();
			cin.getline(p1.name, 80);

			cout << "\nenter age: ";
			cin >> p1.age;

			cout << "\nenter date of birth dd/mm/yy: ";
			cin.ignore();
			cin.getline(p1.dob, 50);

			ofstream outfile("record.txt", ios::out | ios::app);

			outfile << p1.name << '\n' << p1.age << '\n' << p1.dob << '\n';
			outfile.close();

			cout << "\nRecord updated. Do you want to enter another record? ";
			cin >> ch;
		}
	}

	void read()       //function reads from txt file and assign values to struct objects
	{
		countline();

		ifstream infile("record.txt", ios::in);

			for (int i = 0; i < b; ++i) {
				infile.getline(p2[i].name, 80);
				infile >> p2[i].age >> p2[i].dob >> ws;
			}

		infile.close();
	}

	void show()   // function displays the entire record
	{
		//system("cls");
		for (int i = 0; i < b; ++i)
			cout << "\nname: " << p2[i].name << "\tage: " << p2[i].age << "\tdate of birth: " << p2[i].dob;

		cout << "\npress any key to continue";
		_getch();
	}

	void countline()  //function to count number of lines in  txt file
	{
		ifstream infile("record.txt");
		b = 0;

		for (string str; getline(infile, str); )
			b++;

		infile.close();
		b /= 3;
		if (b > 10) b = 10;
	}
};

int main()
{
	family fm;

	while (1) {
		int choice;

		cout << "---------Family record-----------" << endl;
		cout << "\n\n1. Enter a new record" << endl << "2. Show all records" << endl << "3. exit" << endl;
		cin >> choice;

		switch (choice)
		{
			case 1:
				fm.write();
				break;

			case 2:
				//fm.countline();
				fm.read();
				fm.show();
				break;

			case 3:
				exit(1);
				break;

		}

		//system("cls");

	}
	return 0;
}


Why not use std::string rather than c-style char arrays? Also, you're not checking that the file is opened OK. You don't really need countline() - the number of entries can be determined in read().

1
2
3
4
5
6
7
8
9
10
11
12
13
void read()       //function reads from txt file and assign values to struct objects
	{
		ifstream infile("record.txt", ios::in);

		if (infile) {
			b = 0;

			for (; b < 10 && infile.getline(p2[b].name, 80) && infile >> p2[b].age >> p2[b].dob >> ws; ++b);

			infile.close();
		} else
			cout << "Cannot open file\n";
	}


Last edited on
@seeplus thanks mate. actually i was missing cin>>ws;
yeah i have done some silly mistakes in the code like checking whether the file is opened.
But basically my purpose with this program is to clear basic concepts, of class and structs.
i used char arrays just to get used to it. But its better and easier to use std::string ??
and this piece of code is a brilliance from you->

for (; b < 10 && infile.getline(p2[b].name, 80) && infile >> p2[b].age >> p2[b].dob >> ws; ++b);

never knew for loop could be used in this way..
Unless it's a requirement, using string you're not got to deal with potential string overflow etc. It's also much easier to do operations on string (ie compare, find etc) than a char array. Using string rather than c-style string - and also using a vector instead of an array for p2, consider:

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
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <conio.h>

using namespace std;

struct Person {
	string name;
	int age {};
	string dob;
	string occu;
	string son;
	string dau;
	string grandf;
	string grandmstring;
	string grands;
	string grandd;
};

class Family {
	Person p1;
	vector<Person> p2;

public:
	void write()     //function to write the record in a txt file
	{
		for (char ch {'y'}; ch == 'y' || ch == 'Y'; ) {
			//system("cls");
			cout << "\nenter name: ";
			cin.ignore();
			getline(cin, p1.name);

			cout << "\nenter age: ";
			cin >> p1.age;

			cout << "\nenter date of birth dd/mm/yy: ";
			cin.ignore();
			getline(cin, p1.dob);

			ofstream outfile("record.txt", ios::out | ios::app);

			outfile << p1.name << '\n' << p1.age << '\n' << p1.dob << '\n';
			outfile.close();

			cout << "\nRecord updated. Do you want to enter another record (y/n)? ";
			cin >> ch;
		}
	}

	void read()       //function reads from txt file and assign values to struct objects
	{
		ifstream infile("record.txt", ios::in);

		if (infile)
			for (Person p; getline(infile, p.name) && infile >> p.age >> p.dob >> ws; p2.emplace_back(p));
		else
			cout << "Cannot open file\n";
	}

	void show()   // function displays the entire record
	{
		//system("cls");
		for (const auto& p : p2)
			cout << "\nname: " << p.name << "\tage: " << p.age << "\tdate of birth: " << p.dob;

		cout << "\npress any key to continue";
		_getch();
	}
};

int main()
{
	Family fm;

	while (1) {
		int choice {};

		cout << "\n---------Family record-----------";
		cout << "\n\n1. Enter a new record\n" << "2. Show all records\n" << "3. exit\n";
		cout << "Enter option: ";
		cin >> choice;

		switch (choice)
		{
			case 1:
				fm.write();
				break;

			case 2:
				fm.read();
				fm.show();
				break;

			case 3:
				exit(1);
				break;

		}

		//system("cls");
	}
	return 0;
}


re for statement. You have 3 elements - initial statement (executed once) which can specify a type, conditional for when the loop is terminated, loop statement which is executed after the for loop body is executed. There's no stipulation as to what these 3 parts consist. Often the initial defines a counter, condition tests the counter and the loop statement increments the counter - but can be what you want - including the , operator.
@seeplus . thankx mate for pointing out the use of vector. i used it practically for the first time in a program. in your above code had to use one 1 extra line of code in read()->
if (infile) {
p2.clear();
for (person p;getline(infile,p.name) && infile >> p.age >> p.dob >> ws; p2.emplace_back(p));

infile.close();

just one thing whats the difference this makes in show() - for (const auto& p : p2)

if use this instead- for(person p3 : p2)
person p3 : p2 does a by-value copy to p3 and you have the know that the underlying type of p2 is person

const auto& p gets the data by ref and automatically determines the type - no copy done and you don't need to know the underlying type of p2
@seeplus here i added a couple of functions in program. i would like to use pointers in the code- like passing them as arguments, dynamic memory allocater etc... i have read tutorials on pointers but never used them in a practical code. thanx

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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <iostream>
#include<fstream>
#include<stdlib.h>
#include<conio.h>
#include<vector>


using namespace std;

struct person
{
    string name;
    int age;
    string dob;

};

class family
{
    person p1;
    vector<person> p2;
    int l=0; int b=0;   // b= number of entries. which is assigned to this variable in countline()
    string str;
    public:


    void write()     //function to write the record in a txt file
    {
        char ch='y';
        while(ch=='y' || ch=='Y')           // alternate:  for(char ch{'y'};ch=='y' || ch=="Y");
        {
        system("cls");
        cout<<"\nenter name: "; cin.ignore();getline(cin,p1.name);
        cout<<"\nenter age: "; cin>>p1.age;
        cout<<"\nenter date of birth dd/mm/yy: "; cin.ignore();getline(cin,p1.dob);
        ofstream outfile;
        outfile.open("record.txt",ios::out|ios::app);
        outfile<<p1.name<<endl;
        outfile<<p1.age<<endl;
        outfile<<p1.dob<<endl;
        outfile.close();
        cout<<"\nRecord updated. Do you want to enter another record? ";
        cin>>ch;
        }
    }

    void read()       //function reads from txt file and assign values to struct objects
	{
		ifstream infile("record.txt", ios::in);

		if (infile) {
            p2.clear();
			for (person p;getline(infile,p.name) && infile >> p.age >> p.dob >> ws; p2.emplace_back(p));

			infile.close();
		} else
			cout << "Cannot open file\n";
	}


    void showall()   // function displays the entire record
    {
        system("cls");
        for(person p3 : p2)
        {
            cout<<"\n\nname: "<<p3.name<<"\t\tage: "<<p3.age<<"\t\tdate of birth: "<<p3.dob;
        }
        cout<<"\n\npress any key to continue";
        getch();

    }



    void countline()  //function to count number of lines in  txt file
    {
        ifstream infile("record.txt");
        while(getline(infile,str))
        {
            l++;

        }
        infile.close();
        b=l/3;
    }
    void modify(string n)    // function  to change the record of a member
    {
        system("cls");
        ifstream file("record.txt",ios::in);
        ofstream outfile("temp.txt",ios::out|ios::app);
        if(file)
        {
            for(person p4;getline(file,p4.name)&&file>>p4.age>>p4.dob>>ws;)
            {
                if(p4.name==n)
                {
                    cout<<"\nname: "<<p4.name<<"\tage: "<<p4.age<<"\tdate of birth: "<<p4.dob<<endl;
                    cout<<"\Modify: ";
                    cout<<"\nenter name: ";getline(cin,p4.name);
                    cout<<"\nenter age: "; cin>>p4.age;
                    cout<<"\nenter date of birth dd/mm/yy: "; cin.ignore();getline(cin,p4.dob);
                    outfile<<p4.name<<endl;
                    outfile<<p4.age<<endl;
                    outfile<<p4.dob<<endl;
                    cout<<"\nrecord updated!!";
                    cout<<"\nPress any key to continue";
                    _getch();

                }
                else
                {
                    outfile<<p4.name<<endl;
                    outfile<<p4.age<<endl;
                    outfile<<p4.dob<<endl;
                }
            }
            file.close();
            outfile.close();
            remove("record.txt");
            rename("temp.txt","record.txt");
        }
        else
            cout<<"file does not exist!!!";
    }

    void show(string n1)           // function to show record of a particular member
    {
        system("cls");
        ifstream infile("record.txt",ios::in);
        infile.seekg(0,ios::beg);
        if(infile)
        {
        for(const auto& p:p2)
        {
            if(p.name==n1)
            {
                cout<<"\nname: "<<p.name<<"\nage: "<<p.age<<"\ndate of birth: "<<p.dob<<endl;
                cout<<"\n\npress any key to continue";
                _getch();
            }
            else
                continue;

        }
        infile.close();
        }
        else {
            cout<<"file doesnot exist!!! press any key to continue.....";
            _getch();
        }

    }
};







int main()
{

family fm;
string mod;
while(1)
{
    int choice;
    cout<<"---------Family record-----------"<<endl;
    cout<<"\n\n1. Enter a new record"<<endl<<"2. Show all records"<<endl<<"3. Modify a record"<<endl<<"4. Show record of a member"<<endl<<"5. exit"<<endl;
    cin>>choice;
    switch(choice)
    {
    case 1:
       fm.write();
       break;

    case 2:
        fm.read();
        fm.showall();
        break;

    case 3:
        cout<<"Enter the name of family member: "; cin.ignore(); getline(cin,mod);
        fm.modify(mod);
        break;
    case 4:
        cout<<"Enter the name of family member: "; cin.ignore(); getline(cin,mod);
        fm.read();
        fm.show(mod);
        break;

    case 5:
        exit(1);
        break;

    }

    system("cls");

}
    return 0;
}
Why is show() opening the file when it's not using it?

L141/142 are not needed as if the if statement condition is false the for loop is continued.

Why are you reading/writing the file for the options? Why not read the fie once, use this data for the operations and then write the data back to the file when exit or option to save data?

This type of data processing program IMO doesn't lend itself to using pointers. When you're happy with this program then do another that would use pointers (eg a tree data structure or..)
got it corrected show(). file operation was useless in this , i didnt noticed.
"Why are you reading/writing the file for the options?" u mean why the function read() is being executed multiple times on different switch options!!. while i can just execute it once at start and use vector p2 for different options..
Topic archived. No new replies allowed.