重载>> c ++中Date类的运算符会导致无限循环

时间:2012-05-23 16:28:37

标签: c++ date overloading infinite istream

我正在尝试使用c ++中的Date类重载>>运算符,但是当运行进入第一个if语句时,它会进入无限循环,你能帮助我吗?

//operator
    istream& operator >>(istream& is,CustomDate& d){
        int day,month,year; 
        char ch1,ch2;
        string test;
        is>>skipws>>day>>ch1>>month>>ch2>>year;
        if(!is){
            is.clear(ios_base::failbit);
            return is;
        }
        if(ch1!='/' || ch2!='/')
            error("invalid date input");
        d = CustomDate(day,month,year);
        return is;
    }

这是调用它的函数

CustomDate Menu::inputDate(){
    CustomDate date;
    cout<<"Input your departure date"<<endl;
    cin>>date;
    if(!cin){
        error("invalid date format");
    }
    return date;
}

这是调用函数的循环

do{
    try{
        date = inputDate();
        validDate = true;
    }
    catch(runtime_error& e){
        cout<<"Date format not valid! must input as dd/mm/yyyy!"<<endl;
        validDate = false;
    }
}while(!validDate);

//customdate constructor
CustomDate::CustomDate()
    :day(1),month(1),year(2012){}

CustomDate::CustomDate(int day, int month, int year)
    :day(day),month(month),year(year){

    if(day<0 || day>30)
        error("Error: Date constructor");
    if(month<0 || month>12)
        error("Error: Date constructor");
    if(year<0)
        error("Error: Date constructor");
}

3 个答案:

答案 0 :(得分:1)

正如我在评论中所说:

  

你是什么意思&#34; clear()函数应该清除流&#34; ?它不会丢弃流内容,所以如果流中存在垃圾(例如字符“无法解析为int”),它将永远不会&#34;清除&#34;那个垃圾,只会继续重试。我认为问题在于,明确的做法并不像你认为的那样。

如果它不能提取整数或者分隔符字符错误(也尝试使用更多的空格来帮助使代码更具可读性),而不是从流提取操作符中抛出异常而不是failbit:

istream& operator >>(istream& is, CustomDate& d){
    int day, month, year;
    char ch1, ch2;
    if (is >> day >> ch1 >> month >> ch2 >> year)
    {
        if (ch1 == '/' && ch2 == '/')
            d = CustomDate(day, month, year);
        else
            is.setstate(ios::failbit);
    }
    return is;
}

然后在inputDate

中处理失败的提取
CustomDate inputDate(){
    CustomDate date;
    cout << "Input your departure date" << endl;
    if (cin >> date)
      return date;

    // something went wrong
    if (cin.eof())
        error("No more data in stream");
    else // cin.fail() is true, probably invalid date format
    {
        // clear error and discard input up to next newline
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        error("invalid date format");
    }
}

答案 1 :(得分:1)

您的代码有很多错误。 <{1}}循环可能是一个无限循环,也可能是错误的。

如果您在输入流上启用了异常,并且流提取语句中的解析在重载do ... try ... catch中失败,您将获得无限循环。您的代码永远不会重置流,因此一旦您收到解析错误,您的代码就会陷入循环。永远。

如果您没有启用异常并且输入损坏到足以使流提取语句以某种方式将流标记为“坏”,该怎么办?未启用异常,因此不会抛出异常。您的代码(如果在流提取调用之后立即执行if语句,则为then分支)将执行。这也不会引发异常。 operator>>将成功。在这里,您的代码错误地接受错误输入为有效。

答案 2 :(得分:0)

我会重做你的例子,因为它依赖于能够输入多个项目,即int char int char int。我会输入一个字符串。然后使用stringstream解析日期并检查其格式。

所以它可能是这样的:

istream& operator >>(istream& is,CustomDate& d){
    string dateStr;
    is>>dateStr;
    istringstream iss(dateStr);
    int day,month,year; 
    char ch1,ch2;
    if(!(iss>>day>>ch1>>month>>ch2>>year)){
        error("invalid date input");
        return is;
    }
    if(ch1!='/' || ch2!='/'){
        error("invalid date format use m/d/y");
        return is;
    }
    d = CustomDate(day,month,year);
    return is;
}

我不确定这是否会修复任何无限循环,但这可能是检查输入的更好方法。