哪种模式最好?

时间:2011-11-04 01:25:11

标签: c++

A

:data_input
    [input code here];
    if ([validation test]) {
        std::cout << "Invalid data. ";
        goto data_input;
    }

do {
    [input code here];
while ([validation test] && std::cout << "Invalid data. ");

C

do {
    [input code here];
}
while ([validation test] && (std::cout << "Invalid data. ") || 1);

您会选择哪种方法跳回代码的输入段?为什么?

3 个答案:

答案 0 :(得分:1)

我使用scanf(在C中)的一个技巧如下:

while (scanf("%d", &myInt)!=1) {
    printf("Invalid Data!\n");
}

这基本上结合了数据输入和验证步骤:scanf尝试读取int,并返回它成功读取的内容的数量。如果它不是1,则出现问题,显示错误消息,并再次运行scanf。

因此,如果您能以某种方式将输入和验证步骤合并到一个语句中。所以,你可以尝试:

int data; // or whatever
while (!validate(data = getData())) {
    [error code]
}

(我不是C ++的专家,所以虽然我知道这是可能的,但我不确定它是否一定是好的风格.C ++众神,如果这不是惯用的,告诉我,我会编辑)

如果无法做到这一点,我会选择这样的事情:

[input data]

while ([validation test fails]) {
    std::cout << "Invalid data."
    [input data again]
}

我不喜欢A,因为goto:)

我不喜欢B或C,因为我认为这是滥用和&amp;&amp;和|| - 利用短路是好的,但这些运算符的输入应该是返回有意义的值的表达式,而不是语句。

答案 1 :(得分:0)

在混合中抛出另一个:

bool validateData([data])
{
   bool valid;

   [validation logic, sets valid true or false]

   if(!valid)
   {
      std::cout << "Invalid data.";
      return false;
   }
   return true;
}

然后

do
{
  [input data]
} while(!validateData([data]));

然后a)它是可读的b)validateData可以是任意的并且是可维护的。

答案 2 :(得分:0)

如果您正在使用C ++流并希望对数据执行某些操作,那么我将这样做:

std::istream& operator<<(std::istream& i, Data& d)
{
    if (!(i >> d.member) || !(i >> d.othermember))
        d.markInvalid(); // the istream is automatically marked invalid
    return i;
}

// In another function:

    Data myData;
    while (std::cout << "Please enter the data:  " &&
           std::cin >> myData) // Or another stream, of course)
    {
        if (!data.isValid())
        {
            std::cout << "Invalid data.\n";
            continue;
        }
        // Operate on data
    }

这为您提供了一个优势,即意外的EOF不会有循环运行且没有任何东西。如果您希望继续输入错误,只需将第二个&&更改为||并进行循环检查myData.isValid(),并在出现故障时显示错误消息continue;

或者,如果您只是编写一个函数来读取和返回数据(在我看来并不那么优雅),您可以使用

Data GetData(std::ostream& o, std::istream& i) {
    Data myData;
    while (o << "Please enter the data: " &&
           i >> myData.member &&
           i >> myData.otherMember &&
           !myData.isValid())
    {
        o << "Invalid data!  Please try again.\n";
    }
    if (!i)
    {
        myData.markInvalid(); // Make sure the caller knows the data is not good.
        // Alternatively, throw an exception.
    }
    return myData;
}

// In another function:
    Data myData = GetData(std::cout, std::cin);
    if (myData.isValid())
    {
        // Operate on data
    }

在任何一种情况下,您可能无法完全创建对象,并且需要某种方式来报告它。您需要检查输入的数据是否格式错误(然后您可能希望忽略无效输入以便获取新输入),或者流是否死亡(在这种情况下您可能需要拯救)。 C ++ FAQ提供了有关此事here的一些信息,包括使用整数类型执行此类操作的函数示例。