【问题标题】:A way to not accept float as input c++一种不接受浮点数作为输入c ++的方法
【发布时间】:2015-11-29 18:51:03
【问题描述】:

我正在做一个项目,我需要检查正确的输入 (n),我目前有一些代码不允许输入字符串,因为它会再次要求输入正确的数量。我在编写不允许浮点数通过的代码时遇到问题,因为它目前只是忽略了输入的浮点部分。如果这是一个简单的问题,我很抱歉,但我还没有找到解决这个问题的方法。

  for(int i=0; i<1; ++i)
    {
        string b1;
        int e;
        do
        {
            getline(cin,b1);
            e=atoi(b1.c_str());
        }
        while(e==0 && b1!="0");
        n=e; // where n is the user input
    }

【问题讨论】:

  • 那么你的问题在哪里?您是否尝试输入浮点数并使用 atoi 将其放入 integer e ?或者你正在做其他事情?
  • 您可以使用strtol。它需要一个额外的参数来告诉您它停止解析的位置。如果遇到非数字字符,则该额外参数最终将指向该字符;否则,它将指向终止的 NUL。
  • 正如我在原始问题中所写,这部分仅处理字符串,因为它会拒绝任何字符串输入。我试图找出一种对浮动做同样的方法。我只想要 int 输入,我想拒绝 float 输入。
  • Also look at std::stoi.strtol 稍微麻烦一点,但是会捕捉到值太大而不能适应少一点体操的情况。
  • @user4581301 - 更多的体操。您需要使用std::stoistd::strtol 进行“try ... catch”,并且使用任何一个都可以轻松检查最后是否有垃圾。

标签: c++ input floating-point int


【解决方案1】:

假设您考虑任何带有小数点 ('.') 或使用带有负指数的科学记数法作为不可接受的浮点数,只需检查输入的字符串是否包含其中之一:

std::string::iterator it;
if (b1.end() != std::find(b1.begin(), b1.end(), '.')
    || (b1.end() != (it = std::find_if(b1.begin(), b1.end(),
                                       [](char c){ return c == 'e' || c == 'E'; })
        && it + 1 != b1.end()
        && '-' == it[1])) {
    // deal with the string being a floating point number with a fractional part
}

请注意,这将认为,例如,"10e-1" 是一个错误的值,尽管它实际上只是 "1" 的一个花哨拼写。

【讨论】:

    【解决方案2】:

    如果您输入一个float 值,那么它将有一个decimal point (.)。由于您的输入是string,因此您可以进行以下检查:-

    do
    {
         getline(cin,b1);
         if(bi.find(".")!=b1.npos); // search if a decimal point is present or not
         cout<<"wrong input";
         else
         e = stoi(b1);  // stoi works similar to atoi but on strings
    }
    

    【讨论】:

    • 只需使用stoi的第二个参数来检测解析失败,这样就无需单独调用find
    • 如果用户输入1e-1怎么办?没有小数点,但那不是整数。
    • @DavidHammen 说实话,即使std::stoi 在您使用此类表达式时也无法给出正确的输出。所以我很无奈
    • 第二个参数区分整数和尾随垃圾的整数(包括1e-1
    【解决方案3】:

    您要做的第一件事就是不要一遍又一遍地重复要读取整数的代码。做一个函数:

    int getInt(std::istream & in)
    

    这将接受任何输入流,cin,一个文件,一个std::stringstream,等等。接下来我们设置一些我们需要的局部变量。

    {
        std::string b1;
        int e;
    

    现在我们构建输入循环

        while (std::getline(in, b1))
    

    这将循环直到输入流失败。如果它永远不会失败并且用户无法一起行动,我们将在这里待很长时间。与吉利根。船长也是。或许我们可以从 Howell 先生身上烧掉一些钱作为启动种子资金,嗯?

        {
            size_t pos;
    

    捕获字符串到整数转换引发的任何异常

            try
            {
    

    转换为intpos 将更新为结束转换的字符。如果它不是字符串的结尾,则字符串不包含int。如果它确实包含int,我们退出函数并返回int

                e = std::stoi(b1, &pos);
                if (pos == b1.length())
                {
                    return e;
                }
            }
    

    我们真的不需要在 catch 块中做任何事情。如果您愿意,您可以输出一条消息来指示或模拟用户。

            catch (...)
            {
    
            }
        }
    

    如果我们到达这里,IO 流失败了,我们需要让人们知道。抛出异常。

        // IO failure. throw exception
    }
    

    用法很简单:

    int value = getInt(cin);
    

    您可能希望将调用包装在 try-catch 块中以捕获 IO 失败异常。 cin 的失败案例非常奇怪,而且通常是致命的。

    在对文件调用getInt 时,您需要更加小心地处理事情,因为文件结束是很常见的情况。

    所有在一起,没有运行评论:

    int getInt(std::istream & in)
    {
        std::string b1;
        int e;
        while (std::getline(in, b1))
        {
            size_t pos;
            try
            {
                e = std::stoi(b1, &pos);
                if (pos == b1.length())
                {
                    return e;
                }
            }
            catch (...)
            {
    
            }
        }
        // IO failure. throw exception
    }
    

    【讨论】:

    • 一个问题:pos == b1.npos 不是正确的测试。你应该使用pos &gt; 0 &amp;&amp; b1[pos] == 0
    • 射击。我知道我应该运行它。谢谢@BenVoigt
    • 嗯,如果您嵌入了 NULL(从流中读取时应该不可能),那就更好了,但您仍然在错误处理空输入。你需要我提到的pos &gt; 0 测试。
    • @BenVoigt - 不需要pos&gt;0 测试。如果无法进行转换(例如,空字符串或"junk"),std::stoi 将抛出异常。通过调用std::stoi 意味着pos 中的值必须是正数。
    • @DavidHammen:谢谢你提醒我为什么我总是使用乖巧的版本 (strtol)
    【解决方案4】:

    您可以为此目的使用std::stringstream:-

    for(int i=0; i<1; ++i)
        {
            string b1;
            char c=' ';
            int e=0, check=0;
            do
            {
                getline (cin, b1);
                stringstream ss(b1);
                ss >> check;
                if(ss>>c)
                cout << "bad input";
                else
                e=check;
            }
            while(e==0 && b1!="0");
            n=e;
        }
    

    【讨论】:

    • 无法捕获浮点数,OP 询问的确切情况。
    • 它检测到浮动不是吗?
    • 如果你输入 3.14,它会输出 3 而不会因为不是int 而拒绝它。你所做的只是输出一条消息说输入错误,你仍然让它通过。
    • @user4581301 我想你现在应该没有问题了
    • 只有一个。 e 现在在输入错误后未初始化使用。上面的快速e=0; 会处理它。
    猜你喜欢
    • 2021-01-22
    • 1970-01-01
    • 2020-09-18
    • 2020-03-31
    • 2016-02-06
    • 1970-01-01
    • 2012-06-02
    • 2018-09-19
    • 1970-01-01
    相关资源
    最近更新 更多