在没有特殊库的情况下验证C ++中的浮点

时间:2015-12-05 16:43:26

标签: c++ floating

我知道之前已经问过这个问题,但答案并没有解决我的问题因此我问这个问题

我有一个简单的程序来查找三个最大的数字,它们只能接受浮点数。如果输入了字符或字符串,则需要显示错误,用户需要再次输入。

我有一个函数来获取有效的浮动输入

float validInput()
    {
        float x;
        cout<< flush;
        cin >> x;
        while(cin.fail())
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(),'\n');
            cout << "Not a numeric value please enter again\n";
            cin >> x;
        }
        return x;
    }

所以我使用validInput(如

)在main函数中输入
int main()
{
   float x = validInput();
   float y = validInput();
   float z = validInput();
   findGreatest(x,y,z);
   return 0;
}

此方法适用于大多数输入。当我输入一个数字后跟一个字符时,它失败了,因为validInput函数很奇怪地失败了。在给出这样的输入时,它显示错误消息&#34;不是数字值,请再次输入&#34; 但不接受另一个输入,而是考虑字符前的数值作为输入和存储它。我的要求是忽略整个输入并要求新的输入

从我的理解

cin.ignore(numeric_limits<streamsize>::max(),'\n');

不会忽略在输入开头输入的数字,但只会清除流中的字符,即使cin.fail()为true。

有什么方法可以解决这个问题吗?它可能需要不同的参数cin.ignore不确定。

提前致谢

来源: https://stackoverflow.com/a/16934374/5236575

PS:我不能使用像boost这样的特殊库。该代码用于实现软件测试的测试用例,因此需要正确处理任何类型的输入。

2 个答案:

答案 0 :(得分:1)

std::cin将从流中顺序读取,因此如果第一个字符代表有效数字,则认为它没问题。如果你想确保你所读的内容确实只是一个数字(后面没有一些额外的字符),一个选项是使用std::getline读取到std::string,然后使用std::stof(C ++ 11)将字符串转换为浮点数。后者将第二个参数作为指向无法转换的第一个字符位置的指针。如果该位置小于字符串的长度,那么您的行包含的不仅仅是数字,因此输入无效。

示例:

#include <iostream>

int main()
{
    float x;
    std::size_t pos;
    std::string str;
    while (std::getline(std::cin, str))
    {
        try
        {
            x = std::stof(str, &pos);
        }
        catch(...)
        {
            std::cout << "Not a numeric value please enter again\n";
            continue;
        }
        if(pos != str.length())
        {
            std::cout << "Not a numeric value please enter again\n";
            continue;
        }
        break;
    }
    std::cout << x;
}

答案 1 :(得分:1)

您可能希望查看实际发生的情况,因为行为根本不奇怪:当您输入一个浮点数后跟一行上的非数字时,浮点值就会被提取出来。 validInput()功能失败的情况是点击 - 通过该通话!但是,由于当函数再次调用时,有些东西无法解析为浮点数,第二次调用会触发失败!

通过在validInput()次调用之间添加输出,您可以看到这确实是行为。通过这种方式,您可以确定哪些调用实际产生了错误。在没有错误时存储值是预期的行为!

您可以通过读取一行来确保一行不包含无效输入,并确认您可以从该行读取并且此行上只有空格。例如:

float validInput()
{
    float x;
    // cout<< flush; There is *NO* reason to flush cout: it is flushed when using cin
    for (std::string line; std::getline(std::cin, line); ) {
        std::istringstream lin(line);
        if (lin >> x && (lin >> std::ws).eof()) {
            break;
        }
        cout << "Not a numeric value please enter again\n";
    }
    throw std::runtime_error("reached end of input before getting a valid value!");
    return x;
}

使用lin >> std::ws会在此行上跳过所有潜在的尾随空格(新行已被std::getline()删除)。之后,如果确实没有进一步的输入(这是eof() ......的少数有效用途之一),则应该使用流并设置eof()标志。

相关问题