Array of Pointers and Objects

Hello good people.
I need help with extracting data from a .txt file and add that to an array pointer/array of Objects.
Im so so lost on what to implement on the Farmer.cpp file.

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
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#ifndef CROP_HPP
#define CROP_HPP
#include <string>
#include <iostream>
using namespace std;

class Crop
{
protected:
	string cropName;
	float numberOfUnits;
	float pricePerUnit;
	float cropExpenses;

public:
	Crop();
	Crop(string, float, float, float);
	string getCropName();
	float getNumberOfUnits();
	float getPricePerUnit();
	float getCropExpense();
};


#endif

#include "Crop.hpp"
#include <string>
#include <iostream>
using namespace std;

Crop::Crop()
{
	cropName = " ";
	numberOfUnits = 0;
	pricePerUnit = 0.0;
	cropExpenses = 0.0;
}

Crop::Crop(string cropName, float numberOfUnits, float pricePerUnit, float cropExpenses)
{
	this->cropName = cropName;
	this->cropExpenses = cropExpenses;
	this->numberOfUnits = numberOfUnits;
	this->pricePerUnit = pricePerUnit;
}

string Crop::getCropName()
{
	return cropName;
}

float Crop::getNumberOfUnits()
{
	return numberOfUnits;
}

float Crop::getPricePerUnit()
{
	return pricePerUnit;
}

float Crop::getCropExpense()
{
	return cropExpenses;
}

#ifndef AdvancedCrop_Hpp
#define AdvancedCrop_Hpp
#include "Crop.hpp"

class AdvancedCrop : public Crop
{
protected:
	float sizeOfCrop;
	float propertyTax;
	
	//Inhereted protected base data members
	string cropName;
	float numberOfUnits;
	float pricePerUnit;
	float cropExpenses;

public:
	AdvancedCrop(string, float, float, float, float,float);
	float getProductProfit();

	float getSizeOfCrop();
	float getPropertyTax();

	string getCropName();
	float getNumberOfUnits();
	float getPricePerUnit();
	float getCropExpenses();
};

#endif

#include "AdvancedCrop.hpp"

AdvancedCrop::AdvancedCrop(string cropName, float numberOfUnits, float pricePerUnit, float cropExpenses, float sizeOfCrop,
	float propertyTax) : Crop(cropName, numberOfUnits, pricePerUnit, cropExpenses)
{
	this->cropName = cropName;
	this->numberOfUnits = numberOfUnits;
	this->pricePerUnit = pricePerUnit;
	this->cropExpenses = cropExpenses;
	this->sizeOfCrop = sizeOfCrop;
	this->propertyTax = propertyTax;
}

float AdvancedCrop::getProductProfit()
{
	return (numberOfUnits * pricePerUnit) - cropExpenses;
}

float AdvancedCrop::getSizeOfCrop()
{
	return sizeOfCrop;
}
float AdvancedCrop::getPropertyTax()
{
	return propertyTax;
}

string AdvancedCrop::getCropName()
{
	return cropName;
}
float AdvancedCrop::getNumberOfUnits()
{
	return numberOfUnits;
}

float AdvancedCrop::getPricePerUnit()
{
	return pricePerUnit;
}

float AdvancedCrop::getCropExpenses()
{
	return cropExpenses;
}

#ifndef FARM_HPP
#define FARM_HPP
#include <string>
#include "AdvancedCrop.hpp"
using namespace std;
int const MAX = 10;
class Farm
{
	AdvancedCrop *crop[MAX];
	int cropCounter;
	string farmName;

public:
	Farm(string);

	string getName();
	void addCrop(AdvancedCrop &advCrop);
	~Farm();
	float getProfit();
};


#endif

#include "Farm.hpp"

Farm::Farm(string farmName)
{
	cropCounter = 0;
	this->farmName = farmName;
}

string Farm::getName()
{
	return farmName;
}

void Farm::addCrop(AdvancedCrop &advCrop)
{
	crop[cropCounter] = &advCrop;
	cropCounter++;
}

Farm::~Farm()
{
	for (int i = 0; i < cropCounter; i++)
	{
		delete crop[i];
	}
}

float Farm::getProfit()
{
	float farmProfit = 0.0;
	return farmProfit += crop[cropCounter]->getProductProfit();
}

#ifndef FARMER_HPP
#define FARMER_HPP
#include "Farm.hpp"
#include <string>
#include <fstream>
int const SIZE = 30;
using namespace std;

class Farmer
{
private:
	string fileName;
	Farm *farms[SIZE];
	int farmCounter;
	AdvancedCrop extractCropFromLine(string); /*Method must receive a line of text as input argument and extract an AdvancedCrop object from it. The format of the line will always be: cropName,numberOfUnits, pricePerUnit,cropExpenses,sizeOfCrop, propertytax*/

public:
	Farmer(string); /*The constructor must read the file denoted by the filename input parameter and add all the farms(and their crops) to the farms[] array*/
	int getNumberOfFarms();
	Farm& getFarmAt(int);
	float getTotalProfit();
	int getProfitLessFarms(string[], float[]);

};

#endif

#include "Farmer.hpp"
#include <string>
#include <fstream>
#include <cstring>
using namespace std;

Farmer::Farmer(string fileName)
{
	ifstream file;
	file.open(fileName.c_str());

	int columnCounter = 0;
	int start = 0;
	string line;
	string data[]{" "};
	while (!file.ios::eof())
	{
		getline(file, line);

		extractCropFromLine(line);
	}

	//Please help with this class implemenatation
	for (int i = 0; i<line.length(); i++)
	{
		if (line[i] == '\n'	)
		{
			data[columnCounter] = line.substr(start, i - start);
			start = i + 1;
			columnCounter++;
		}
		data[columnCounter] = line.substr(start, line.length() - start);
		if (line[i] == ',')
		{
			data[columnCounter] = line.substr(start, i - start);
			start = i + 1;
			columnCounter++;
		}
	}

	file.close();

	//read from the Farm.txt file and store farm names and their crops

}
//////////////////////////////////////////////////////////////////////////////
/*This is the main.cpp
I can't test the program since I don't understand the Farmer class*/

/*Write a main() front-end program in the Run.cpp file to do the following tasks by making use of the classes created above.
I may not duplicate any source code which functionality already exits in the classes.


1.1 Construct a Farmer class by making use of the Farm.txt file
1.2 Print a list of all the farm names as well as their profit followed by the total profit of the farmer
1.3 Print a list of all the farms that are running at a loss as well as their loss*/
////////////////////////////////////////////////////////////////////////////////
#include "Crop.hpp"
#include "AdvancedCrop.hpp"
#include "Farmer.hpp"
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>

using namespace std;

int main()
{
	
	/*Crop crop("banana", 20,12, 45.88);
	cout << crop.getCropName() << " " << crop.getNumberOfUnits() << " "
		<< crop.getPricePerUnit() << " " << crop.getCropExpense() << endl << endl;

	AdvancedCrop acrop("banana", 20, 12, 45.88,300,1.5);
	cout << acrop.getProductProfit() << endl;
*/

	Farmer fm("Farm.txt");

	system("pause");
	return 0;
}
Last edited on
Please post a sample of your input file. A complete program would also be helpful.
Below is the Farm.txt file


#Water Fountain Farm
Carrots,1000,2.6,430.20,300,1.5
Beans,2000,1.6,300.20,200,1.5
Lettuce,500,5.6,230.20,100,1.5
#Soshanguve Nort Farm
Carrots,1000,2.6,430.30,300,1.2
Lettuce,500,5.6,300.10,300,1.2
Beans,3000,1.6,400.00,300,1.2
Last edited on
@jlb, please check the code again, I've edited it.
Last edited on
Where is your extractCropFromLine() function implementation.
Hi,

A few things I noticed:

Don't duplicate names in base and derived classes. CropName should exist in the base class, and use the base class interface to interact with it.

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
class Crop
{
 // don't have protected data
 // make it private and use the class interface
protected:

private:
	std::string cropName;  // leave the class name out of the member name 
	float numberOfUnits;  //prefer double, it's alright for now though
	float pricePerUnit;
	float cropExpenses; // leave the class name out of the member name

public:
	Crop();  // don't need this, now trying to create an empty object will be a compile error, 
                            //which is what you want

         // provide names for the parameters, not strictly necessary, but better. make them const
	Crop(string, float, float, float);
        Crop(const  std::string&,Name  //reference for std::string
                const float  numberOfUnits,
                const float  pricePerUnit,
                const float  Expenses); 

	const std::string& getCropName() const ;  // not changing state of the class so mark const
                            float getNumberOfUnits()  const;
                            float getPricePerUnit()  const;
                            float getCropExpense()  const;
};


You have member initialiser lists in your ctor, use them to call your base class ctor and initialise the class itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Crop::Crop(const string& cropName,  // this format is easier to read
                 const float numberOfUnits,
                 const  float pricePerUnit, 
                 const float cropExpenses)
                :  // initialiser list
                Name(cropName),  //same names OK
                Expenses(cropExpenses),
	        numberOfUnits (numberOfUnits),
	        pricePerUnit (pricePerUnit);
{

        // don't initialse in the ctor body
        // do validation here instead
	this->cropName = cropName;
	this->cropExpenses = cropExpenses;
	this->numberOfUnits = numberOfUnits;
	this->pricePerUnit = pricePerUnit;
}


And in the derived class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
AdvancedCrop::AdvancedCrop(const string& Name,
                                            const float numberOfUnits, 
                                            const float pricePerUnit, 
                                            const float Expenses, 
                                            const float sizeOfCrop
	                                    const float propertyTax)
                        : 

                         Crop(Name, numberOfUnits, pricePerUnit, Expenses), // call to base class ctor
                         sizeOfCrop(sizeOfCrop),   // initialise class members here too
                         propertyTax (propertyTax);
{
	this->cropName = cropName;
	this->numberOfUnits = numberOfUnits;
	this->pricePerUnit = pricePerUnit;
	this->cropExpenses = cropExpenses;
	this->sizeOfCrop = sizeOfCrop;
	this->propertyTax = propertyTax;
}


The Crop base class should have a pure virtual function and a virtual destructor, so that it becomes abstract - that is, we shouldn't be able to make an object out of this class.

Normally, it is a good idea to have another class to hold a collection of objects. Just to reinforce this Idea, i would re-name Farmer to FarmCollection because it contains a collection of Farm , i know this sounds incredibly pedantic, but names are important. Farmer sounds like an individual Farmer.

With Farmer ctor, A ctor initialses it's member data - nothing else.

The processing of the file should not be in Farmer, because it is dealing multiple objects - Farms and Crops. So consider putting it in main() or elsewhere.

Don't loop on eof, Loop on the stream:

while (!file)

The stream will return a 0 if it has problems, so this will work for your end condition.

Lines 252 to 267: Use strings and getline, no need to process char by char. Use std::stringstream to split a string to words, this can be done straight form the file stream.

http://www.cplusplus.com/reference/sstream/stringstream/stringstream/

I hope all of this has been some help :+)

Regards
Topic archived. No new replies allowed.