a big problem reading from a file

Hi, I have to make a program that includes two classes - CBirthDate keeps the information about the date of birth of a person and the second class - CStudent keeps the name of a student and their date of birth, which is an object of class CBirthDate.The program reads some data about the students from a file, then sorts the data and shows the student with the needed birth date on screen.

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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<functional>
#include<fstream>
#include<iterator>
#include<string>

using namespace std;


class CBirthDate 
{
	unsigned day, month, year;
public:
	CBirthDate();
	CBirthDate(unsigned d, unsigned m, unsigned y);
	CBirthDate(const CBirthDate &);
	void set_day(unsigned &d);
	void set_month(unsigned &m);
	void set_year(unsigned &y);
	unsigned get_day();
	unsigned get_month();
	unsigned get_year();
	bool operator== (const CBirthDate &ob);
	bool operator< (const CBirthDate &ob);
	bool operator> (const CBirthDate &ob);
	friend ostream& operator<<(ostream& toStream, CBirthDate &izv);
	friend istream& operator>>(istream& fromStream, CBirthDate &vyv);
};


CBirthDate::CBirthDate()
{
	day=0;
	month=0;
	year=0;
}


CBirthDate::CBirthDate(unsigned d, unsigned m, unsigned y)
{
	day=d;
	month=m;
	year=y;
}


CBirthDate::CBirthDate(const CBirthDate &ob)
{
	day=ob.day;
	month=ob.month;
	year=ob.year;
}


void CBirthDate::set_day(unsigned &d)
{
	day=d; }


void CBirthDate::set_month(unsigned &m)
{
	month=m; }


void CBirthDate::set_year(unsigned &y)
{
	year=y; }


unsigned CBirthDate::get_day()
{
	return day; }


unsigned CBirthDate::get_month()
{
	return month; }


unsigned CBirthDate::get_year()
{
	return year; }


bool CBirthDate::operator== (const CBirthDate &ob)
{
	return((day==ob.day)&&(month==ob.month)&&(year==ob.year)); }


bool CBirthDate::operator< (const CBirthDate &ob)
{
	return ((year<ob.year) || ((year==ob.year)&&(month<ob.month)) || ((year==ob.year)&&(month==ob.month)&&(day<ob.day))); }


bool CBirthDate::operator> (const CBirthDate &ob)
{
	return ((year>ob.year) || ((year==ob.year)&&(month>ob.month)) || ((year==ob.year)&&(month==ob.month)&&(day>ob.day))); }


ostream& operator<<(ostream& toStream, CBirthDate &izv)
{
	toStream<<izv.get_day()<<" - "<<izv.get_month()<<" - "<<izv.get_year()<<endl;
	return toStream;
}


istream& operator>>(istream& fromStream, CBirthDate &vyv)
{
	unsigned a,b,c;

	fromStream>>a>>b>>c;
	vyv=CBirthDate(a,b,c);

	return fromStream;
}






class CStudent : public CBirthDate
{
	string m_strName;
	CBirthDate data;
public:
	CStudent();
	CStudent(string &n,unsigned &d, unsigned &m, unsigned &y);
	CStudent(const CStudent &ob);
	bool operator< (CStudent &ob);
	bool operator> (CStudent &ob);
	bool operator==(CStudent &ob);
	void set_ime(string &name);
	void set_data(unsigned &d,unsigned &m,unsigned &y);
	string get_name();
	void get_data();
	friend ostream& operator<<(ostream& toStream1, CStudent &izv1);
	friend istream& operator>>(istream& fromStream1, CStudent &vyv1);
};



CStudent::CStudent() : CBirthDate()
{
	m_strName=" "; }
	


CStudent::CStudent(string &n, unsigned &d, unsigned &m, unsigned &y) : CBirthDate(d,m,y)
{
	m_strName=n; }



CStudent::CStudent(const CStudent &ob)
{
	m_strName=ob.m_strName;
	data=ob.data;
}


bool CStudent::operator< ( CStudent &ob)
{
	return ((data.get_year()< ob.data.get_year()) || 
		   ((data.get_year()== ob.data.get_year())&&(data.get_month()<ob.data.get_month()))||
		   ((data.get_year()== ob.data.get_year())&&(data.get_month()==ob.data.get_month())&&(data.get_day()<ob.data.get_day())) );
}



bool CStudent::operator> ( CStudent &ob)
{
	return ((data.get_year()> ob.data.get_year()) || 
		   ((data.get_year()== ob.data.get_year())&&(data.get_month()> ob.data.get_month()))||
		   ((data.get_year()== ob.data.get_year())&&(data.get_month()==ob.data.get_month())&&(data.get_day()> ob.data.get_day())) );
}



bool CStudent::operator==( CStudent &ob)
{
	return((data.get_year()== ob.data.get_year())&&(data.get_month()==ob.data.get_month())&&(data.get_day()==ob.data.get_day()));
}


void CStudent::set_ime(string &name)
{
	m_strName=name; }


void CStudent::set_data(unsigned &d,unsigned &m,unsigned &y)
{
	set_day(d);
	set_month(m);
	set_year(y);
}


string CStudent::get_name()
{ 
	return m_strName;  }


void CStudent::get_data()
{
	cout<<" "<<data.get_day()<<" ";
	cout<<data.get_month()<<" ";
	cout<<data.get_year()<<" "; 

}



ostream& operator<<(ostream& toStream1, CStudent &izv1)
{
	toStream1<<izv1.get_name();
	izv1.get_data();
	toStream1<<endl;

	return toStream1;
}



istream& operator>>(istream& fromStream1, CStudent &vyv1)
{
	string a;
	unsigned b,c,d;

	fromStream1>>a>>b>>c>>d;

	vyv1.set_ime(a);
	vyv1.set_data(b,c,d);

	return fromStream1;
}


bool sravnenie(CStudent ob, CStudent ob1)
{
	return(ob<ob1); }


void main()
{
	cout<<"works"<<endl;

	vector <CStudent> v(3);
	string name;

	const char* strFileName = "my_file.txt";

   ifstream iStream(strFileName);

	copy (istream_iterator<CStudent>(iStream), istream_iterator<CStudent> (),back_inserter(v) );
	copy(v.begin(), v.end(),ostream_iterator<CStudent>(cout, "\n"));


	 sort(v.begin(),v.end(),sravnenie);  



	 name="Radeva";
	 unsigned a=0,b=222,c=333;

	 CStudent obekt=CStudent(name,a,b,c);
	 v.push_back(obekt);

	 vector<CStudent>::iterator i;

	 for(i=v.begin(); i!=v.end(); i++)
	 {
		 if((*i).get_month()==obekt.get_month()) cout<<(*i); 
		 else continue;
	 }





}


I've been trying to run it for 2 days and still can't :( .It shows this error:

1
2
3
4
:\program files\microsoft visual studio\vc98\include\iterator(203) : error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'const class CStudent' (or there is no acceptable conversion)
        c:\program files\microsoft visual studio\vc98\include\iterator(203) : while compiling class-template member function 'class std::ostream_iterator<class CStudent,char,struct std::char_traits<char> > &__thiscall std::ostream_iterator<class CSt
udent,char,struct std::char_traits<char> >::operator =(const class CStudent &)'
Error executing cl.exe.



I'll be really really happy if someone shows me how to fix that , becouse I have an exam on monday and need to know how to make a program read from files correctly...
Last edited on
Due to my narrow knowledge of std libraries I can't tell you why exactly this happens.
I can, however, tell you how to prevent this.
Declare your operator << as ostream& operator<<(ostream& toStream1, CStudent izv1); rather than CStudent&.
I have a feeling that this is because both arguments are references, but I can't say for sure.
It's still the same, thanks anyway
ostream& operator<<(ostream& toStream1, CStudent &izv1)

This operator should take CStudent& as a const reference:

ostream& operator<<(ostream& toStream1, CStudent const& izv1)

However, that means that you need to make your classes "const correct" by defining your constant methods, get_name() and get_data() as "const".

Your other option is not to copy the output using an ostream_iterator, but use a for() loop and operator<<() directly.
This is a const correctness problem.

You need to rework your classes to be const correct. Here are a few basic rules:

1) When passing references to functions, pass by const reference unless the function intends to change the passed variable.
2) When a function does not change 'this' (ie: it does not change the state of the object), make the function const. Get() members and comparison operators (like <, ==, !=, etc) are typically const functions.

For an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool operator< (CStudent &ob);

// above is bad
//  the < operator does not change the object being compared
//  therefore the function should be declared as const
//
// also, 'ob' will not be changed by the < operator, so it should be passed
// by const reference as well
//
//  this is the right way to do it:

bool operator < (const CStudent& ob) const;
//                 ^                   ^
//                 |                   |
//                 |         makes the function const
//                 |
//             pass by const reference 


You have a dozen or so functions that need this change. Pretty much all of your operator overloads and all of your get() functions.


The one that's giving you trouble is your CStudent << operator:

1
2
3
4
5
friend ostream& operator<<(ostream& toStream1, CStudent &izv1);  // bad

// izv1 should be passed by const reference:

friend ostream& operator<<(ostream& toStream1, const CStudent &izv1); // good 


But of course if you make ONLY that change, you'll have a bunch of other errors pop up because your other functions are not const correct. So really the solution here is to make the entire program const correct.


A few other things to note:

3) You can't have void main(), you must have int main(). Main cannot return a void, it has to return an int. Some compilers let you get away with having void main, but don't do it.

4) When passing types like unsigned, pass by value. There's no benefit to passing by reference. Stuff like this is dreadful:

1
2
3
4
5
void set_data(unsigned &d,unsigned &m,unsigned &y);  // bad
// above is bad because d,m,y shouldn't be passed by reference in this case
// for small basic types like 'unsigned' you're generally better off passing by value:

void set_data(unsigned d,unsigned m,unsigned y);  // good 



EDIT: doh... PanGalactic beat me to the punch.

Oh well
Last edited on
Don't pass non-const references where you don't need to (only if you want to modify it). Either pass by value (if the object is small), or by const reference (if the object is big).
Make all your member functions const which doesn't modify internal data (getters, comparison operators, etc.).
And there is no such thing as void main().
Thanks a lot!!! It really works now but only when I initialize the vector by myself and not when I try to read from some file. And even when I don't use the file to initialize the container, it only displays the string variable, the rest is 0 0 0 .
Topic archived. No new replies allowed.