Dealing with Objects

The program is supposed to read a formatted .txt file and store the data into their respective [Class] Members. It will then output the data collected onto screen.

I overloaded ifstream and istream. When I call for file>>ptr[i] to read the data, something goes wrong. It prompts me to input data (which is in istream overload). Why is this happening, this is my code:

The Data in .txt file is as follows;

3
Jenny Hermana    \t  2  \t    21 12
Freddy Lopez	 \t  1	\t    31
Ricky Francisco  \t  1	\t    51


Everything you need to run the program and see output is here. Only need to change file location and create the .txt itself.

-----------Header .h:

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
#ifndef STUDENTTESTSCORES_H
#define STUDENTTESTSCORES_H
#include <string>
#include <iostream>
#include <fstream>
using namespace std;

class StudentTestScores;
const double NA= 0;



class StudentTestScores
{
	private:
		string studentName;
		double *testScores;
		int numTestScores;
		char LetterGrade;
		void createTestScoresArray(int size)
		{
			numTestScores=size;
			testScores=new double[size];
			for (int i=0; i<size; i++)
			{	
				testScores[i]=NA;
			}
		}
    public:
		// class constructor
		StudentTestScores()
		{
			studentName=("");
			numTestScores=0;
			LetterGrade='N';
		}
		StudentTestScores(string name, int numScores ) 
		{ 
			studentName=name;
			createTestScoresArray(numScores);
		}

		// class copy constructor
		StudentTestScores(const StudentTestScores &other) 
		{
			studentName = other.studentName;
			numTestScores = other.numTestScores;
			testScores = new double[numTestScores];
			for (int i = 0; i < numTestScores; i++)
			{
				testScores[i] = other.testScores[i];
			}
		}
		
		// class destructor
		~StudentTestScores()
		{	delete [] testScores;}
	
		// accessors & mutators 
		void setLetterGrade(char x)
		{ LetterGrade=x;}

		char getLetterGrade()
		{ return LetterGrade;}

		void setName(string x)
		{	studentName=x;}
	
		string getName() const
		{	return studentName;}
		
		void setTestScore(double score, int index)
		{	testScores[index] = score;}

		double getTestScore(int index)const
		{	return testScores[index];}

		void setNumTestScores(int x)
		{ numTestScores=x;}
	
		int getNumTestScores() const
		{	return numTestScores;}
				
		//Assignment operator overload
		void operator=(const StudentTestScores &other)
		{
			delete [] testScores;
			studentName = other.studentName;
			numTestScores =other.numTestScores;
			testScores = new double[numTestScores];
			for(int i = 0; i < numTestScores; i++)
			{
				testScores[i] = other.testScores[i];
			}

		}
		
		friend ostream& operator <<(ostream &, StudentTestScores &);
		friend istream& operator >>(istream &, StudentTestScores &);

		friend ifstream& operator >>(ifstream &, StudentTestScores &);
		
		//displayInfo prototype
		void displayInfo(StudentTestScores);

};

//Overload the Stream I/O operators. 
ostream& operator <<(ostream &os, StudentTestScores &x)
	{	
			os<< x.getName() << "\t" << x.getNumTestScores() << "\t" << x.getLetterGrade()<<"\t";

		
	for (int i = 0; i < x.getNumTestScores(); i++)
	{
			os<< x.getTestScore(i)<<", ";
	}
	cout<<".\n";
		return os;
	}

istream& operator >>(istream &is, StudentTestScores &object)
	{
		
		cin.get();
		cout<<"Enter student name : ";	
		getline(is,object.studentName);
			
		cout<<"Enter number of test scores : ";
		is>>object.numTestScores;
		
		object.testScores=new double[object.numTestScores];
				
		for(int i=0; i<object.numTestScores;i++)
		{
			
			cout<<"Enter score for test"<<(i+1)<<" : ";
			is>>object.testScores[i];
		
		}

		return is;
	}

ifstream& operator >>(ifstream &file, StudentTestScores &obj)
{
    int numTestScores=0;
	double sum=0;
	string Name;
	

	getline(file, Name, '\t');
	file>>numTestScores;
	
	StudentTestScores(Name, numTestScores);
	
	for(int i=0; i<obj.numTestScores;i++)
		{
			file>>obj.testScores[i];
			sum=sum+obj.testScores[i];		
		}

	if (sum>=90 && sum<=110)
		obj.setLetterGrade('A');
	else if (sum>=80 && sum<=89)
		obj.setLetterGrade('B');
	else if (sum>=70 && sum<=79)
		obj.setLetterGrade('C');
	else if (sum<=69&& sum>=1)
		obj.setLetterGrade('D');
	else
		obj.setLetterGrade('N');

	return file;

}



#endif  


----------Source .cpp

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
#include "STUDENTTESTSCORES 5.h"
#include <string>
#include <iostream>
#include <fstream>
using namespace std;

void showContent(fstream&);

int main()
{	
	//Pointer to DataType/Class
	StudentTestScores *ptr;
	fstream file;
	//Array Size
	int numOfStudents;
		
	file.open("C:\\Users\\Raggulddon\\Desktop\\tests.txt", ios::app || ios::in);
	
	if(!file)
	{ cout<<"file not found\n";}
	else if (file) 
	{cout<<"File found \n";}
		
	//file input number of students
	file>>numOfStudents;
	cout<<numOfStudents;

	//create array of objects
	ptr=new StudentTestScores[numOfStudents];
	
	//file input for pointer to each object
	for(int i=0; i<numOfStudents;i++)
	{
		file>>ptr[i];
	}

	//output 
	for( int i =0; i < numOfStudents; ++i)
	{ cout << ptr[i] << endl;}		
	
	//showContent(file);
	
	file.close();

	cin.get();cin.get();
	return 0;
}

void showContent(fstream &file)
{
	string line;

	while(getline(file,line))
	{
		cout<<line<<endl;
	}
	
}
You must only have one version of the >> operator that works the same for all streams. In your case, you need to remove the version that works with the file and modify the first one to use the stream given to it rather than std::cin.
So I did what you said, I still can't seem to output any data aside from the data in the default constructor. Meaning, default constructor worked and the array for objects was created.

When I run the program the output is just instances of the default constructor. Why is it not reading to the newly created objects.

*Bonus(Not needed): Should the parameter for overloaded ostream have const keyword? #GoodProgrammingPractice?

----changes: removed duplicate >> overload. Changed parameter to deal with fstream.
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
istream& operator >>(fstream &file, StudentTestScores &obj)
{
    int numTestScores=0;
	double sum=0,temp;
	string Name,strng;
	

	getline(file, Name, '\t');
	file>>numTestScores;
	
	obj.testScores=new double[obj.numTestScores];

	for(int i=0; i<obj.numTestScores;i++)
		{
			file>>obj.testScores[i];
			temp=temp+obj.testScores[i];	
			sum=temp;
		}

	if (sum>=90 && sum<=110)
		obj.setLetterGrade('A');
	else if (sum>=80 && sum<=89)
		obj.setLetterGrade('B');
	else if (sum>=70 && sum<=79)
		obj.setLetterGrade('C');
	else if (sum<=69&& sum>=1)
		obj.setLetterGrade('D');
	else
		obj.setLetterGrade('N');

	return file;

}
Last edited on
You misunderstood - I meant remove the fstream version and keep the istream version.

To answer the bonus question, does the ostream overloaded operator change the second parameter?
To answer question, no it doesn't so const should be written. Yet when I do that, I can't use os<<x.getLetterGrade(); x gets error of : object has type qualifiers that are not compatible with the member function.

Okay, I changed it to istream instead of fstream.
istream& operator >>(istream &file, StudentTestScores &obj)

I still cannot get the correct output. The data is just not being written to the object I think. It still sends the default information.

I appreciate the patience and generosity :)
The error you get when you make it const is because you did not make certain member functions const as you should. If a member function does not need to change the state of the object, it should be marked const.

As for your problem, you're reading in the test scores to your own array instead of the array in the object.
Solved all my problems.

Thanks once again for all your help. Keep doing what you do, because you're great at it. World needs more people like you :)
Topic archived. No new replies allowed.