将cin与>混合;一个班级的操作员

时间:2018-06-13 22:23:29

标签: c++

以下代码中的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;

}

可能我的操作员非常糟糕,但我无法理解在哪里和如何?

1 个答案:

答案 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将为brandcategory将为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;
}