Trying to input a file and storing the data in a vector

Hello everyone! I am trying to store the data of a file into a vector of type Ingredients*. I would really appreciate it if you could help me. The project has a three-level hierarchy of classes with a base class Ingredients. I can paste the constructors and the source of them too. Thank you in advance! Sorry for my English :)
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
  bool readFile(vector<Ingredients*> inventory) {
	ifstream inFile("Data.txt");
	if (!inFile)
		return false; // If the object was unable to open the file
	else {
		Ingredients* temp;
		/*string id;
		string line;
		string name;*/
		//int quantity;
		while (inFile >> temp->quantity) {
			inFile.ignore();
			getline(inFile, temp->name);
			getline(inFile, temp->id);
			inventory.push_back(temp);
		}

		inFile.close();
		return true;
	}
}

int main() {
	vector<Ingredients*> v;
	readFile(v);
	if (!readFile(v))
		return 1;
	else {
		for (int i = 0; i < v.size(); ++i) {
			cout << v[i]->getType() << " - " << v[i]->getId() << " - " << v[i]->getFoodType() << " - " << v[i]->getName()
				<< " - " << v[i]->getQuantity() << " - " << v[i]->getExpirationDate() << endl;
		}
	}


	return 0;
}
Last edited on
First why the Ingredients*? Why not just an Ingredient?

Second where are you allocating/de-allocating memory for that pointer?

Third do you realize that the vector<> in the readFile() function is a copy and all changes made to that vector inside the function is lost when the function returns? Perhaps you should be passing the vector by reference?

Hi, thank you for the reply! I am now passing it as a reference but I am not sure how to get the code to output the vector. I saw a similar code on another post here and tried to change it for my purpose. I would appreciate it if you could help a bit. It currently starts but doesn't output anything.



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
bool readFile(vector<Ingredients> &inventory) {
	ifstream inFile("Data.txt");
	if (!inFile)
		return false; // If the object was unable to open the file
	else {
		Ingredients temp;
		while (inFile >> temp.quantity) {
			inFile.ignore();
			getline(inFile, temp.name);
			getline(inFile, temp.id);
			inventory.push_back(temp);
		}

		inFile.close();
		return true;
	}
}

int main() {
	vector<Ingredients> v;
	if (!readFile(v))
		return 1;
	else {
		for (int i = 0; i < v.size(); ++i) {
			cout << v[i].getType() << " - " << v[i].getId() << " - " << v[i].getFoodType() << " - " << v[i].getName()
				<< " - " << v[i].getQuantity() << " - " << v[i].getExpirationDate() << endl;
		}
	}


	return 0;
}
Last edited on
It would help if you posted a complete program and the contents of your input file.

Have you tried to run the program with your debugger? With the debugger you should be able to single step through the program and watching the variables as you single step.
I will try with the debugger now but here is the program if you like to take a look.


txt file:
AF
1
Pork
Meat
5
14/05/2020
PB
2
banana
4
fruit
15/06/2020
yes
AF
3
Veal
Meat
5
13/04/2021



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
#pragma once
#include <iostream>
using namespace std;

class Ingredients {
public:
	int quantity;
//protected:
	string type;
	string id;
	string name;
	string foodType;
	string expirationDate;
public:
	string getFoodType();
	int getQuantity();
	string getId();
	string getName();
	string getType();
	string getExpirationDate();

	Ingredients() {}

	Ingredients(string type, string id, string name, int quantity, string foodType, string expirationDate);

};


#include <iostream>
#include "Ingredients.h"
using namespace std;

Ingredients::Ingredients(string type, string id, string name, int quantity, string foodType, string expirationDate) :
	type(type),
	id(id),
	name(name),
	quantity(quantity),
	foodType(foodType),
	expirationDate(expirationDate) 
{
}

string Ingredients::getType() {
	return type;
}

string Ingredients::getExpirationDate() {
	return expirationDate;
}

string Ingredients::getId() {
	return id;
}

string Ingredients::getName() {
	return name;
}

int Ingredients::getQuantity() {
	return quantity;
}


string Ingredients::getFoodType() {
	return foodType;
}

#pragma once
#include <iostream>
#include "Ingredients.h"
using namespace std;

class AnimalFoods : public Ingredients {
public:
	string animal;
	string getAnimal();

	AnimalFoods(string type, string id, string name, int quantity, string foodType, string expirationDate, string animal);
};


#include <iostream>
#include "AnimalFoods.h"
using namespace std;

string AnimalFoods::getAnimal() {
	return animal;
}

AnimalFoods::AnimalFoods(string type, string id, string name, int quantity, string foodType, string expirationDate, string animal) :
	Ingredients( type,  id,  name,  quantity,  foodType,  expirationDate),
	animal(animal)
{
	
}


#pragma once
#include <iostream>
#include "Ingredients.h"
using namespace std;

class PlantBasedFoods : public Ingredients {
public:
	string seasonal;
	string isSeasonal();

	PlantBasedFoods(string type, string id, string name, int quantity, string foodType, string expirationDate, string seasonal);
};

#include <iostream>
#include "PlantBasedFoods.h"
using namespace std;

string PlantBasedFoods::isSeasonal() {
	if (seasonal == "Y") {
		return "seasonal";
	}
	return "not seasonal";
}

PlantBasedFoods::PlantBasedFoods(string type, string id, string name, int quantity, string foodType, string expirationDate, string seasonal) :
	Ingredients(type, id, name, quantity, foodType, expirationDate),
	seasonal(seasonal)
{

}

#pragma once
#include <iostream>
using namespace std;

class Inventory {
public:
	string number;
	string getInventoryNum();
};

#include <iostream>
#include <vector>
#include "Inventory.h"
#include "Ingredients.h"
#include "PlantBasedFoods.h"
#include "AnimalFoods.h"
#include "Fruits.h"
#include "Vegetables.h"
#include "Meat.h"
#include "Dairy.h"
#include <iterator>
#include <algorithm>
#include <fstream>
#include <string>
using namespace std;

string Inventory::getInventoryNum() {
	return number;
}

//merge function
void merge(vector<Ingredients*>& a, vector<Ingredients*>& tmpArr, int l, int r, int rEnd) {
	int lEnd = r - 1;
	int tmpPos = l;
	int numElements = rEnd - l + 1;

	while (l <= lEnd && r <= rEnd)
		if (a[l]->quantity <= a[r]->quantity)
			tmpArr[tmpPos++] = a[l++];
		else
			tmpArr[tmpPos++] = a[r++];

	while (l <= lEnd)
		tmpArr[tmpPos++] = a[l++];

	while (r <= rEnd)
		tmpArr[tmpPos++] = a[r++];

	for (int i = 0; i < numElements; i++, rEnd--)
		a[rEnd] = tmpArr[rEnd];
}

//mergesort function
void mergeSort(vector<Ingredients*>& a, vector<Ingredients*>& tmpArr, int l, int r)
{
	if (l < r) {
		int center = (l + r) / 2;
		mergeSort(a, tmpArr, l, center);
		mergeSort(a, tmpArr, center + 1, r);
		merge(a, tmpArr, l, center + 1, r);
	}
}

void mergeSort(vector<Ingredients*>& a)
{
	vector<Ingredients*> tmpArr(a.size());
	mergeSort(a, tmpArr, 0, a.size() - 1);
}


void PrintVector(vector<Ingredients*> v) {

	for (int i = 0; i < v.size(); ++i) {
		cout << v[i]->getType() << " - " << v[i]->getId() << " - " << v[i]->getFoodType() << " - " << v[i]->getName()
			<< " - " << v[i]->getQuantity() << " - " << v[i]->getExpirationDate() << endl;
	}
}
bool readFile(vector<Ingredients> &inventory) {
	ifstream inFile("Data.txt");
	if (!inFile)
		return false; // If the object was unable to open the file
	else {
		string type, id, name, foodtype, expirationdate;
		int quantity;	
		while (inFile >> quantity) {
			inFile.ignore();
			getline(inFile, type);
			getline(inFile, id);
			getline(inFile, name);
			getline(inFile, foodtype);
			getline(inFile, expirationdate);
			
			Ingredients foo;
			foo.getId();
			foo.getName();
			foo.getFoodType();
			foo.getExpirationDate();
			foo.getQuantity();
			inventory.push_back(foo);
		}
		inFile.close();
		return true;
	}
}

int main() {
	vector<Ingredients> v;
	if (!readFile(v))
		return 1;
	else {
		for (int i = 0; i < v.size(); ++i) {
			cout << v[i].getType() << " - " << v[i].getId() << " - " << v[i].getFoodType() << " - " << v[i].getName()
				<< " - " << v[i].getQuantity() << " - " << v[i].getExpirationDate() << endl;
		}
	}


	return 0;
}
The first thing you try to read is the quantity, an int, but the first row contains "AF" which is not an integer value (unless you interpret it as hex).
Last edited on
after I changed the input to start with a int I managed to get output but it is not human-readable

- - - - -858993460 -
- - - - -858993460 -

AF
1
Pork
Meat
5
14/05/2020
PB
2
banana
4
fruit
15/06/2020
yes
AF
3
Veal
Meat
5
13/04/2021


That format is inconsistent. Sometimes there is a number between name and foodtype and sometimes there isn't. The format of the data file needs to be consistent for each entry - otherwise the file read will not work properly.


Last edited on
I have changed the txt to be consistent

12
AF
3445
Pork
Meat
12/02/2019
14
PB
1221
Apple
Fruit
13/03/2020
15
AF
2342
Veal
Meat
13/12/2020

But now the output is not human-readable:
- - - - -858993460 -
- - - - -858993460 -
- - - - -858993460 -

At least now the rows are three as supposed to
When coding, it's better to code in small parts and compile/test before moving on to code the next part. This means that you don't write a lot of code then comer to compile/test and find loads of problems.

As starter code to read and display the file 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
#include <string>
#include <iostream>
#include <fstream>
#include <vector>

class Ingredients {
private:
	int quantity {};
	std::string type;
	std::string id;
	std::string name;
	std::string foodType;
	std::string expirationDate;

public:
	std::string getFoodType() const;
	int getQuantity()const ;
	std::string getId() const;
	std::string getName() const;
	std::string getType() const;
	std::string getExpirationDate() const;

	Ingredients() {}

	Ingredients(const std::string& type, const std::string& id, const std::string& name, int quantity, const std::string& foodType, const std::string& expirationDate);

	friend std::istream& operator>>(std::istream& inFile, Ingredients& i);
};

std::istream& operator>>(std::istream& inFile, Ingredients& i) {
	if (inFile) {
		inFile >> i.quantity >> std::ws;
		std::getline(inFile, i.type);
		std::getline(inFile, i.id);
		std::getline(inFile, i.name);
		std::getline(inFile, i.foodType);
		std::getline(inFile, i.expirationDate);
	}

	return inFile;
}

std::ostream& operator<<(std::ostream& os, const Ingredients& e) {
		os << e.getType() << " - " << e.getId() << " - " << e.getFoodType() << " - " << e.getName()
		<< " - " << e.getQuantity() << " - " << e.getExpirationDate();
}

Ingredients::Ingredients(const std::string& type, const std::string& id, const std::string& name, int quantity, const std::string& foodType, const std::string& expirationDate) :
	type(type), id(id), name(name), quantity(quantity), foodType(foodType), expirationDate(expirationDate) { }

std::string Ingredients::getType() const {
	return type;
}

std::string Ingredients::getExpirationDate() const {
	return expirationDate;
}

std::string Ingredients::getId() const {
	return id;
}

std::string Ingredients::getName() const {
	return name;
}

int Ingredients::getQuantity() const {
	return quantity;
}

std::string Ingredients::getFoodType() const {
	return foodType;
}

bool readFile(std::vector<Ingredients>& inventory) {
	std::ifstream inFile("Data.txt");

	if (!inFile)
		return false;

	for (Ingredients ing; inFile >> ing; inventory.push_back(ing));
	return true;
}

void printVector(const std::vector<Ingredients>& inventory) {
	for (const auto& e : inventory)
		std::cout << e << '\n';
}

int main() {
	std::vector<Ingredients> v;

	if (!readFile(v))
		return (std::cout << "Cannot open file\n"), 1;

	printVector(v);
}



AF - 3445 - Meat - Pork - 12 - 12/02/2019
PB - 1221 - Fruit - Apple - 14 - 13/03/2020
AF - 2342 - Meat - Veal - 15 - 13/12/2020

Those unreadable numbers are probably the result of using the default constructor when creating foo which leaves all the member variables uninitialized. Either pass the values to the constructor or read the values directly into the member variables like you did earlier and like seeplus did in his latest post (if you want the member variables to be private or protected you will have to go with the pass-values-to-constructor approach).
Last edited on
Thank you! I really appreciate your help. I have now added the other classes as well.
Topic archived. No new replies allowed.