Your biggest issue is that you don't validate your input.
As a result you are probably setting the input stream into an error state which results in all further read operations failing.
Your read operation should either succeed and update the car object, or it should fail and not change the state of the car (hopefully doing something so the error propagates).
First check that your user choice worked:
if (cin>>choice) {
switch(choice)
...
}
Inside the read operator you need to make sure that you don't update the object until you have read the whole object from the stream.
I would do this:
// Need a helper object to make reading lines easier.
struct Line
{
char* dst;
int max;
Line(char* dst, int max)
: dst(dst)
, max(max)
{}
friend std::istream& operator<<(std::istream& s, Line& line) {
if (s.getline(line.dst, line.max) {
s.ignore();
}
return s;
}
};
istream& operator>>(istream &is , Car &car)
{
double price;
int miles;
char brand[50];
char model[50];
char category[50];
if (is >> price >> miles >> Line(brand, 50) >> Line(model, 50) >> line(category, 50) ) {
car.setPrice(price);
car.setMiles(miles);
car.setBrand(brand);
car.setModel(model);
car.setCategory(category);
// PS I hate all these setters. Leaking the implementation.
// I would have written the above as:
// car = Car(price, miles, brand, model, category);
}
// if there was a read error then `car` is unchanged
// and the stream `is` is in an error state.
return is;
}
Now that I have refactored your code I can bet the error is after reading the miles. I bet you have an input file that looks like this:
price
miles
brand
model
category
Where each value is separated by a new line. The trouble is that operator>>
does not read the trailing new line. So after reading miles
you still have a newline on the stream. This means when you read brand
it will be empty, model
will be brand
and category
will be model
. This leaves category on the stream and the next time you read a car it will fail as Category
will not match a price causing the stream to go into error state.
Assuming I guessed the error correctly this can be fixed as follows:
struct Line
{
char* dst;
int max;
Line(char* dst, int max)
: dst(dst)
, max(max)
{}
friend std::istream& operator<<(std::istream& s, Line& line) {
// Assume there is a proceeding newline that
// must be removed. Do this with s.ignore()
s.ignore() && s.getline(line.dst, line.max);
return s;
}
};
istream& operator>>(istream &is , Car &car)
{
double price;
int miles;
char brand[50];
char model[50];
char category[50];
if (is >> price >> miles >> Line(brand, 50) >> Line(model, 50) >> line(category, 50) ) {
car = Car(price, miles, brand, model, category);
// Remove the newline after the `category`
is.ignore();
}
// if there was a read error then `car` is unchanged
// and the stream `is` is in an error state.
return is;
}