0

我正在尝试在 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");
}
4

3 回答 3

1

您的代码有许多错误。该do ... try ... catch循环可能是一个无限循环,它也可能是不正确的。

如果您在输入流上启用了异常并且流提取语句中的解析在重载的operator>>. 您的代码永远不会重置流,因此一旦出现解析错误,您的代码就会陷入循环。永远。

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

于 2012-05-23T18:31:18.397 回答
1

正如我在评论中所说:

“clear() 函数应该清除流”是什么意思?它不会丢弃流内容,因此如果流中有垃圾(例如无法解析为 int 的字符 'a'),它将永远不会“清除”该垃圾,只会继续重试。我认为问题在于 clear 不会像您认为的那样做。

如果它无法提取整数或分隔符错误,则不要从流提取运算符中抛出异常(也尝试使用更多空格以帮助使代码更具可读性):

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");
    }
}
于 2012-05-23T17:42:05.287 回答
0

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

所以它可能是这样的:

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;
}

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

于 2012-05-23T16:55:43.113 回答