以下代码中的Hello
int main()
{
//intialize variables
while(true)
{
menu.display();
char choice;
cin>>choice;
switch(choice)
{
case 'A':
Car c;
cin>>c;
break;
}
}
return 0;
}
当我输入'A'并使用覆盖的operator >>
用于Car类时,menu.display()
被调用3次,但我想它应该被调用一次,哪里可能是问题?这是>> operator
:
istream& operator>>(istream &is , Car &car)
{
double price;
is>>price;
car.setPrice(price);
int miles;
is>>miles;
car.setMiles(miles);
char brand[50];
is.getline(brand,50);
is.ignore();
car.setBrand(brand);
char model[50];
is.getline(model,50);
is.ignore();
car.setModel(model);
char category[50];
is.getline(category,50);
is.ignore();
car.setCategory(category);
return is;
}
可能我的操作员非常糟糕,但我无法理解在哪里和如何?
答案 0 :(得分:0)
您最大的问题是您没有验证您的输入 因此,您可能将输入流设置为错误状态,导致所有进一步的读取操作失败。
您的读取操作应该成功并更新汽车对象,否则它应该失败并且不会改变汽车的状态(希望做某事以便错误传播)。
首先检查您的用户选择是否有效:
if (cin>>choice) {
switch(choice)
...
}
在read运算符内部,您需要确保在从流中读取整个对象之前不更新对象。
我会这样做:
// 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;
}
既然我已经重构了你的代码,我可以打赌这个错误是在读完里程之后。我打赌你有一个看起来像这样的输入文件:
price
miles
brand
model
category
每个值用新行分隔。问题是operator>>
没有读取尾随的新行。因此,在阅读miles
后,您仍然会在流上添加换行符。这意味着,当您阅读brand
时,它将为空,model
将为brand
,category
将为model
。这会在流上留下类别,下次您阅读汽车时它会失败,因为Category
与价格不匹配会导致流进入错误状态。
假设我猜错了,可以修改如下:
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;
}