How to index vectors with data stored in a text file.

I have a text file that has information about different cars.
1 2019 Honda Civic Sedan 23000
2 2019 Honda Pilot SUV 32000
3 2019 Honda Odyssey Sedan 27000

I want to display this file and then have the user be able to pick which car they would like, and that cars information should store in the variables.Currently I've only been able to get the file to run and display and the variables store in the last line of the text file. So it stores in 2019 Honda Odyssey Sedan 27000. Any help is appreciated. Im new to using both files and vectors. I need the user to be able to pick which car so I can then do calculations with that cars information. I would think i should ask user for i, but even when I have tried manually doing it like cars[2] it doesnt work.

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
#include<iostream>
#include <string>
#include <fstream>
#include<sstream>
#include<vector> 


using namespace std;

vector<vehicleTransactionAgreement> cars;
vehicleTransactionAgreement c1;
//Lease d1;

int select = 0;

int main()
{
	ifstream myFile("cardata.txt");
	myFile.is_open();

	if (!myFile) //Always test the file open.
	{
		cerr << "Error opening output file" << endl;
		system("pause");
		return -1;
	}

	while (myFile >> c1.carIndex >> c1.carYear >> c1.carBrand >> c1.carModel >> c1.carName >> c1.carMsrp)
	{

		cars.push_back(c1);
	}

	
	for (size_t i = 0; i < cars.size(); i++)
	{
		c1 = cars[i];
		cout << c1.carIndex << ' ' << c1.carYear << ' ' << c1.carBrand << ' ' << c1.carModel << ' ' << c1.carName << " $" << c1.carMsrp << endl;
	}
	myFile.close();

	cout << " Which car would you like to buy or lease? \n Use the index to pick: \n";
	//cin >> select;

//vehicleTransactionsAgreement.cpp--------------------------------------------------------------

#include "vehicleTransactionAgreement.h"
#include<iostream>
#include <string>
#include <vector>
using namespace std;

vehicleTransactionAgreement::vehicleTransactionAgreement(const string& name, const string& model, const string& color, const string& brand, double msrp, double year, double vin, int yrlyplan, double downpaymnt, double creditscor): 
	carModel(model), carColor(color), carName(name), carBrand(brand),carMsrp(msrp), carYear(year), carVIN(vin), yearlyPlan(yrlyplan), downPayment(downpaymnt), creditScore(creditscor)
{
	
}
vehicleTransactionAgreement::vehicleTransactionAgreement()
{
}
void vehicleTransactionAgreement::setcarModel(const string &model)
{
	 carModel = model;
}

string vehicleTransactionAgreement::getcarModel() const
{
	return carModel;
}

void vehicleTransactionAgreement::setcarName(const string &name)
{
	carName = name;
}

string vehicleTransactionAgreement::getcarName() const
{
	return carName;
}

void vehicleTransactionAgreement::setcarColor(const string &color)
{
	carColor = color;
}

string vehicleTransactionAgreement::getcarColor() const
{
	return carColor;
}

void vehicleTransactionAgreement::setcarMsrp(double msrp)
{
	carMsrp = msrp;
}

double vehicleTransactionAgreement::getcarMsrp() const
{
	return carMsrp;
}

void vehicleTransactionAgreement::setcarYear(double year)
{
	carYear = year; 
}

double vehicleTransactionAgreement::getcarYear() const
{
	return carYear;
}
void vehicleTransactionAgreement::setcarVIN(double vin)
{
	carVIN = vin;
}

double vehicleTransactionAgreement::getcarVIN() const
{
	return carVIN;
}
void vehicleTransactionAgreement::setcarBrand(const string &brand)
{
	carBrand = brand;
}

string vehicleTransactionAgreement::getcarBrand() const
{
	return carBrand;
}
void vehicleTransactionAgreement::setyearlyPlan(int yrlyplan)
{
	yearlyPlan = yrlyplan;
}
int vehicleTransactionAgreement::getyearlyPlan() const
{
	return yearlyPlan;
}
void vehicleTransactionAgreement::setdownPayment(double downpaymnt)
{
	downPayment = downpaymnt;
}

double vehicleTransactionAgreement::getdownPayment() const
{
	return downPayment;
}
void vehicleTransactionAgreement::setcreditScore(double creditscor)
{
	creditScore = creditscor;
}

double vehicleTransactionAgreement::getcreditScore() const
{
	return creditScore;
}
void vehicleTransactionAgreement::print()const
{
	cout << "Car Model: " << getcarYear() << " " << getcarBrand() << " " << getcarModel() << "  " << getcarName() <<endl;
	cout << "Car Color: " << getcarColor() << endl;
	cout << "Car MSRP:  $" << getcarMsrp() << endl;
	
}
double vehicleTransactionAgreement::calculateCost()
{
	return (getcarMsrp() - getdownPayment()) * 0.01;

}
Last edited on
So what is vehicleTransactionAgreement?

And read this before posting more code.
http://www.cplusplus.com/articles/jEywvCM9/
Hello liayag,

salem c wrote:
So what is vehicleTransactionAgreement

Good point. What is it and where is it. Your code does not compile or work with out it.

What I did notice in "main" is that you did not include "vehicleTransactionAgreement.h".

Lines 10 and 11 may make the code easier to work with, but it looks like the main file has only one function, "main", and these variables are better defined in "main" and passed to any function that needs them.

It may have been a copy and paste problem, but "main" is missing the closing }.

Line 19 has no real use because it is the return value of the function that you are not using. Also the "!myFile" on line 21 is a better use than this.

Line 25 returning "-1" will work if that is what you want. "return 0;" means that the program ended with no problems , or a normal ending. Any number greater than (0) zero means that there is a problem. If you have multiple return or exit statements you can use different numbers.

The while loop to read the file looks OK for now, but I have no way of testing it yet.

If you are going to use myFile.close(); I would move it up to line 34 .

The for loop looks like it should work, but I have no way to test it yet. I would more likely write the "cout" statement as cout << cars[i].getCarIndex() ..., but I did not see this function in the other ".cpp" file. I may missed it .

I do not know how you defined your class, so I am only guessing for now.

In the "vehicleTransactionAgreement::print" function you do not need the "get" functions. As a member function of the class it has access to the private variables of the class.

There is a start for now.

Hope that helps,

Andy
I changed the data file name and simplified a lot of stuff like variable names and cut out all the BS you haven't got data for (yet).

It appears you need to read up on classes, even where they go in relation to main (even as an #include as separate file(s), and also understand indexing in the vector.

[I don't think any of this contradicts what Andy has written.

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
#include<iostream>
#include <string>
#include <fstream>
#include<vector>

using namespace std;

class Car
{
private:
    int ref_No;
    int year;
    string make;
    string model;
    string type;
    int price;
    
public:
    Car(){}
    
    Car(int aRef_No, int aYear, string aMake, string aModel, string aType, int aPrice)
    {
        ref_No = aRef_No;
        year = aYear;
        make = aMake;
        model = aModel;
        type = aType;
        price = aPrice;
    }
    
    ~Car(){}
    
    void setRefNo( int aRefNo){ ref_No = aRefNo; }
    void setYear( int aYear){ year = aYear; }
    void setMake( string aMake){ make = aMake; }
    void setModel( string aModel){ model = aModel; }
    void setType( string aType){ type = aType; }
    void setPrice( int aPrice){ price = aPrice; }
    
    void print()
    {
        cout << "Car: "
        << ref_No << " " << year << " " << make << " " << model
        << " " << type << " $" << price << '\n';
    }
};



int main()
{
vector<Car> stock;
Car temp;
    int ref = 0;
    int year = 0;
    string make;
    string model;
    string type;
    int price = 0;
    
    ifstream myFile("car_data.txt");
    
    if ( myFile.is_open() ) //Always test the file open.
    {
        while (myFile >> ref >> year >> make >> model >> type >> price)
        {
            temp.setRefNo(ref);
            temp.setYear(year);
            temp.setMake(make);
            temp.setModel(model);
            temp.setType(type);
            temp.setPrice(price);
            
            stock.push_back(temp);
        }
        myFile.close();
    }
    else
    {
        cout << "Unable to open file\n";
        return -1;
    }
    
    // Display all stock
    for (size_t i = 0; i < stock.size(); i++)
    {
        temp = stock[i];
        cout << "Vector index: " << i << "  ";
        temp.print();
    }
    
    int selection; // NOTE: This is not the car reference number!!
    cout << " Which car would you like to buy or lease? \n Use the index to pick: \n";
    cin >> selection;
    
    temp = stock[selection];
    temp.print();
    
    return 0;
}



Vector index: 0  Car: 1 2019 Honda Civic Sedan $23000
Vector index: 1  Car: 2 2019 Honda Pilot SUV $32000
Vector index: 2  Car: 3 2019 Honda Odyssey Sedan $27000
 Which car would you like to buy or lease? 
 Use the index to pick: 
1
Car: 2 2019 Honda Pilot SUV $32000
Program ended with exit code: 0
Last edited on
I usually ask programming questions on reddit, and they get kind of mad over there about posting whole files, which is why I left some stuff out. I got the program working though, also took into account what you guys said . thanks so much!!
Hello liayag,

Sorry I had to do this in two parts.

I am not familiar with "reddit", but here most times it is better to post code that will compile. It saves a lot of time this way. Also sometimes in the code that you do not post may contain a problem that you do not see.

Since you say it is working now this is what I did to get it to read the 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
#include <iostream>
#include <iomanip>  // <--- Added.
#include <limits>   // <--- Added.
#include <string>
//#include<sstream> // <--- Not used yet.
#include <vector> 

#include <fstream>

#include "vehicleTransactionAgreement.h"

//using namespace std;  // <--- Best not to use.
// A recent post that is worth reading. http://www.cplusplus.com/forum/beginner/258335/

int main()
{
	size_t index{}, year{}, creditScr{};
	int select{};
	double msrp{}, dwnPayment{};
	std::string name, model, colour, brand, vin;

	std::vector<vehicleTransactionAgreement> cars;

	//vehicleTransactionAgreement c1;
	//Lease d1;

	std::ifstream myFile("cardata.txt");
	//myFile.is_open(); // <--- Not needed or properly used. Also covered by the next line.

	if (!myFile) //Always test the file open.
	{
		std::cerr << "\n    Error opening intput file " << std::quoted("cardata.txt") << std::endl;  // <--- Changed.

		// A fair C++ replacement for "system("pause")". Or a way to pause the program.
		// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
		//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
		std::cout << "\n\n Press Enter to continue: ";
		std::cin.get();

		return 1;
	}

	std::cout << std::fixed << std::setprecision(2); // <--- Only needs done once.

	while (myFile >> index >> year >> brand >> model >> name >> msrp)
	{
		cars.emplace_back(index, year, brand, model, name, msrp);

		//std::cout << std::endl; // <--- Used as a break point for testing.
	}

	myFile.close();

	for (auto& car : cars)
		car.print();

	//for (size_t i = 0; i < cars.size(); i++)
	//	cars[i].print();

	std::cout << "\n Which car would you like to buy or lease?\n Use the index to pick: ";
	std::cin >> select;

	while (!std::cin)
	{
		std::cerr << "\n    Invalid choice! Try again.\n";

		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

		std::cout << "\n Which car would you like to buy or lease?\n Use the index to pick: ";
		std::cin >> select;
	}

	return 0;
}


The comments should explain most of what I did,

I changed some of the variables based on what they are used for.

I used "size_t", AKA "unsigned int", for the variables "index", "year" and "creditScr" because these are all variables the should have only a positive number.

In line 20 "colour" is the only variable that has no use at the moment with the code that you have.

In the if statement using "system" anything is not a good idea. The code I put in place of "system" is what I use.

Line 43 comes from the "<iomanip>" header file and if you are going to use a "double" for a money value then you will need the "std::setprecision". Also in the other ".cpp" file I used "std::setw()".

When I first looked at the while loop I saw the right idea, but later realized it is the wrong way to go about it. What I did here is use regular variables to read the file then inside the while loop I used "emplace_back" to make use of these variables. By putting the variables in the () this will first create an object of the class using the overloaded ctor of the class then put this into the vector.

After the while loop I closed the file stream because it is no longer needed and it is a better place for this line. But still may be considered an optional line.

The range based for loop is handy because you are using a vector, but I also fixed the for loop that you started with so you can see what should be done.

std::cin >> select; is formatted input which means the "cin" expects that a number should be entered. If not the "cin" will be in a failed state and no longer usable until dealt with. Not as robust as it could be, but will catch a non numeric entry.

The "return 0;" at the end of "main" is not needed, but makes a good break point when debugging the code.

Not having your header file I came up with this to get the program to work.
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
#ifndef VEHICLE_TRANCATION_AGGREMENT_H
#define VEHICLE_TRANCATION_AGGREMENT_H

class vehicleTransactionAgreement
{
	public:
		vehicleTransactionAgreement();
		//~vehicleTransactionAgreement();

		vehicleTransactionAgreement(size_t index, size_t year, std::string brand, std::string model, 
                    std::string name, double msrp) : carIndex(index), carYear(year), carBrand(brand),
                    carModel(model), carName(name), carMsrp(msrp) {}
	
		// Get functions.
		std::string getcarName() const;
		std::string getcarColor() const;
		double getcarMsrp() const;
		double getcarYear() const;
		std::string getcarModel() const;
		std::string getcarVIN() const;
		std::string getcarBrand() const;
		int getyearlyPlan() const;
		double getdownPayment() const;
		double getcreditScore() const;

		// Set functions.
		void setcarModel(const std::string& model);
		void setcarName(const std::string& name);
		void setcarColor(const std::string& color);
		void setcarMsrp(double msrp);
		void setcarYear(size_t year);
		void setcarVIN(std::string vin);
		void setcarBrand(const std::string& brand);
		void setyearlyPlan(int yrlyplan);
		void setdownPayment(double downpaymnt);
		void setcreditScore(size_t creditscor);

		void print() const;
		double calculateCost();

	private:
		size_t carIndex{};
		size_t carYear{};
		size_t creditScore{};
		int yearlyPlan{};
		double carMsrp{};
		double downPayment{};
		std::string carModel;
		std::string carColor;
		std::string carName;
		std::string carBrand;
		std::string carVIN;
};
#endif // !VEHICLE_TRANCATION_AGGREMENT_H  



Lines 1, 2 and 52 is called a header guard and I believe is consider a more portable way of including this file only once.

Breaking up line 10 as I did should not be a problem, but does make it easier to read.

Line 7 is required, but line 8 is not. Also you did not define a function for line 8 in the ".cpp" file. By leaving out line 8 the compiler will still generate a default dtor for you.

The reason for changing line 10 is so that it will work with the "emplace_back" in main.

Not necessary , but I grouped the "get" and "set" function in separate sections. What you did is fine and if that works for you then use it.

I changes some of the variable types in the private section. Order of the variables makes no real difference. I like to put the variables with the smallest storage space first and the largest storage space last. Personal preference, but you are free to do what works for you.

In the "vehicleTransactionsAgreement.cpp" I made these changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include <iomanip>
#include <string>
#include <vector>

#include "vehicleTransactionAgreement.h"

constexpr double MULTIPLIER{ 0.01 };

// The get and set functions are OK, as is they compile with no problems, but untested.

void vehicleTransactionAgreement::print() const
{
	std::cout << std::setw(2) << carIndex << ". Car Model: " << carYear << " " << carBrand
		<< " " << carModel << " " << carName << '\n' << "    Car Color: " << carColor << '\n'
		<< "    Car MSRP:  $" << carMsrp << '\n' << std::endl;
}

double vehicleTransactionAgreement::calculateCost()
{
	return (carMsrp - downPayment) * MULTIPLIER;

}
  1. Car Model: 2019 Honda Civic Sedan
    Car Color:
    Car MSRP:  $23000.00

  2. Car Model: 2019 Honda Pilot SUV
    Car Color:
    Car MSRP:  $32000.00

  3. Car Model: 2019 Honda Odyssey Sedan
    Car Color:
    Car MSRP:  $27000.00


 Which car would you like to buy or lease?
 Use the index to pick: 2


end part 1.
Part 2.

The "setw()" allows for the numbers to line up to the right side of the space given (3). This is good from 1 to 99. Anthing larger and you will need to change the number from (3) to (4).

The other thing about the "print" function is that you do not need three separate "cout" statement. It can all be put into one and if it is long just put it on separate lines a sI did. Also the use of "endl" is not necessary to end every line. The "\n" works well for clearing the output buffer. I save the "endl" for the very end of a "cout" statement.

The use of "MULTIPLIER" is a suggestion to avoid using a magic number, that can be hard to find and change, and gives you one place to make a change that is easier to fine. The name can be your choice. As a constant the use of capital is the most often preferred way of naming this type of variable, but again it is your choice.

Hope that helps,

Andy
This definitely helped a lot. Thank you so much!!
Topic archived. No new replies allowed.