Reading data from .txt to a struct vector

Hello, first post here, but frequenter of the forum...

I need to open a file that has 3 pieces of data on each line, with an unknown number of lines. Here is my code so far:

cost.h
1
2
3
4
5
6
7
8
9
10
11
#ifndef COST_H
#define COST_H

struct Cost 
{
	std::string descr;
	double amount;
	int itemNum;
};

#endif 


main:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main() {

	const int SIZE = 20;
	vector <Cost> allData;
	string desc;
	double amount;
	int inum;

	ifstream costFile;
	costFile.open("costfile.txt", ios::in);
	while (costFile.is_open() && !costFile.eof()) {
		costFile >> desc >> amount >> inum;
		allData.push_back(desc, amount, inum);
	}
	costFile.close();

	ofstream outFile;
	outFile.open("outfile.txt", ios::out);
	for (int index = 0; index < SIZE; index++)
		outFile << allData[index].descr << " " << allData[index].amount << " " << allData[index].itemNum << endl;
}


costfile.txt
1
2
3
4
Pass_Go 200.00 135
Reading_RR 50.00 136
Connecticut 120.00 137
Chance 25.00 138



Not really sure how to do this; push_back() seems like the right function to be using but I don't really understand how to use it with structures. The above code throws an error (C2661 in MSVS), looks like I overloaded push_back(), it doesn't like the 3 arguments.
Last edited on
First off, welcome :)
push_back needs an object of whatever type the vector itself is, in this case Cost. It doesn't know what to do with the individual components, how could it?
Make a temporary object before you push_back. This is where constructors are nice.

But seeing that you don't have one, do something like this:
1
2
3
4
5
Cost tempCost;
tempCost.descr = desc;
tempCost.amount = amount;
tempCost.itemNum = inum;
allData.push_back(tempCost);

Last edited on
push_back needs an object of whatever type the vector itself is, in this case Cost. It doesn't know what to do with the individual components, how could it?


See emplace_back(). Argument forwarding ftw!
It still needs the struct to have a different constructor.
That seems to have done the trick!
I got the program to work as the instructor intended. Here's what I came up with:

cost.h:
1
2
3
4
5
6
7
8
9
10
11
12
//Structure for the program
#ifndef COST_H
#define COST_H

struct Cost 
{
	std::string descr;
	double amount;
	int itemNum;
};

#endif 


main():
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
//This program will read/write data to file.  The data will be structured, and manipulated
//by functions.  A header file will be included with the struct information.
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <vector>

#include "cost.h"		//Structure File
using namespace std;

//Functions
//Cost parse_account(ifstream &source, vector <Cost>& data);
Cost parse_account(ifstream &source);
double sum_accounts(vector <Cost>& data);

int main() {
	//Variables
	vector <Cost> allData;
	string desc;
	double amount, sum = 0.0;
	int inum;
	Cost tempCost;

	//Importing data from file with verification.
	ifstream costFile;
	costFile.open("costfile.txt", ios::in);
	//This loop will call the parse_account() function (until the EOF is reached) and push_back() the data into the main vector, allData.
	while (!costFile.eof() && costFile.is_open()) {
		allData.push_back(parse_account(costFile));
	}
	costFile.close();  //Closing "costfile.txt"
	
	//Message output of sum
	sum = sum_accounts(allData);
	cout << "The sum of all items is: " << sum << endl << endl;

	//Output File
	ofstream outFile;
	outFile.open("outfile.dat", ios::out | ios::binary);   //Saving as a binary file.
	for (int index = 0; index < allData.size(); index++)   //Basic loop to write all data to the file.
		outFile << setw(12) << allData[index].descr << setw(10) << allData[index].amount << setw(10) << allData[index].itemNum << endl;
	outFile.close();

	system("pause");
	return 0;
}
//parse_account() will take a ifstream object as an argument, scan a line from the file
//and save the data to tempCost, of type Cost.  tempCost is then returned.
Cost parse_account(ifstream &source) {
	string desc;
	double amount;
	int inum;
	Cost tempCost;

	//Scanning a line from the file
	source >> desc >> amount >> inum;

	//Assigning the data to the tempCost variable
	tempCost.descr = desc;
	tempCost.amount = amount;
	tempCost.itemNum = inum;

	return tempCost;
}
//sum_accounts() will step through a vector of type Cost and add all the amounts, then
//return the sum as a double.
double sum_accounts(vector <Cost>& data) {
	double sum = 0;
	for (int index = 0; index < data.size(); index++)
		sum += data[index].amount;
	return sum;
}


This was the assignment, probably should have mentioned this earlier, haha

Write a program that opens a file, reads records into a container of data structures, and prints out the sum in order.
You can use Vectors to contain the data structures.

1. Create a data structure to represent the record ==> struct Cost in cost.h
2. Write a function called ==> parse_account, that parses one (string) record from a file, and 
populates a data structure with that data.
3. Write a function called sum_accounts, that when passed a container of structures, returns 
a double representing the sum of the amounts in those structures.
4. Create a main program
     a) Create an appropriate container of data structures
     b) Open the accounts file (costfile.txt)
     c) While you can read a line from the file without error
•          Call parse_account, which returns a data structure.
•          Add the returned data structure to the container (using, pushToV)
    d) Call sum_accounts to determine the amount of money represented
    e) Print a message and the result.

Try this with some sample data, such as the following lines in costfile.dat
You may add or create your own data file to test the program with: 
You can start with the data in a text file and then write the data in a binary file, this
way you practice with both file types.

Description      Amount    Item number
Pass_Go          200.00          135
Reading_RR       50.00          136
Connecticut     120.00          137
Chance              25.00          138
Last edited on
Protip: Put indented raw text (such as your assignments) in [ output] tags.
Also, you can edit an old (not TOO old) post to play with the forum tags and see how they work.
Edit: In line 57 you can also use tempCost.descr and the other members individually, avoiding the extra variable declarations and the post-read copies to the struct.

Also, system() is evil.
http://www.cplusplus.com/forum/articles/11153/
If your teacher told you to use it, do use it.
But forget it whenever it's not for an assignment.
Last edited on
Protip: Put indented raw text (such as your assignments) in [ output] tags.
Also, you can edit an old (not TOO old) post to play with the forum tags and see how they work.
Edit: In line 57 you can also use tempCost.descr and the other members individually, avoiding the extra variable declarations and the post-read copies to the struct.

Also, system() is evil.
http://www.cplusplus.com/forum/articles/11153/
If your teacher told you to use it, do use it.
But forget it whenever it's not for an assignment.


Great suggestions, I've made the necessary changes.

In regards to system(), I use it mostly for debugging purposes. My professor didn't explicitly state that it needs to be in the code, but it does help me when debugging. The final version, to be submitted, won't have system().
Topic archived. No new replies allowed.