如何验证数字输入C ++

时间:2021-09-13 00:05:30

I'd like to know how to limit an input value to signed decimals using std::cin.

我想知道如何使用std :: cin将输入值限制为带符号的小数。

7 个解决方案

#1


If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:

如果cin的后备变量是一个数字,并且提供的字符串不是数字,则返回值为false,因此您需要一个循环:

int someVal;

while(!(cin >> someVal)) {
   cin.reset();
   cout << "Invalid value, try again.";
}

#2


double i;

//Reading the value
cin >> i;

//Numeric input validation
if(!cin.eof())
{
    peeked = cin.peek();
    if(peeked == 10 && cin.good())
    {
             //Good!
             count << "i is a decimal";
        }
        else
        {
             count << "i is not a decimal";
         cin.clear();
         cin >> discard;
        }
}

This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.

这也给出了输入-1a2.0的错误消息,避免了将-1分配给i。

#3


cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char for the second field.

cin的>>运算符通过一次读取一个字符直到它碰到空白来工作。这将淹没整个字符串-1a2.0,这显然不是一个数字,因此操作失败。看起来你实际上有三个字段,-1,a和2.0。如果按空格分隔数据,cin将能够毫无问题地读取每个数据。只记得读第二个字段的字符。

#4


Combining the techniques from the top answer here and this website, I get

结合这里的最佳答案和本网站的技术,我得到了

input.h

#include <ios>  // Provides ios_base::failure
#include <iostream>  // Provides cin

template <typename T>
T getValidatedInput()
{
    // Get input of type T
    T result;
    cin >> result;

    // Check if the failbit has been set, meaning the beginning of the input
    // was not type T. Also make sure the result is the only thing in the input
    // stream, otherwise things like 2b would be a valid int.
    if (cin.fail() || cin.get() != '\n')
    {
        // Set the error state flag back to goodbit. If you need to get the input
        // again (e.g. this is in a while loop), this is essential. Otherwise, the
        // failbit will stay set.
        cin.clear();

        // Clear the input stream using and empty while loop.
        while (cin.get() != '\n')
            ;

        // Throw an exception. Allows the caller to handle it any way you see fit
        // (exit, ask for input again, etc.)
        throw ios_base::failure("Invalid input.");
    }

    return result;
}

Usage

inputtest.cpp

#include <cstdlib>  // Provides EXIT_SUCCESS
#include <iostream>  // Provides cout, cerr, endl

#include "input.h"  // Provides getValidatedInput<T>()

int main()
{
    using namespace std;

    int input;

    while (true)
    {
        cout << "Enter an integer: ";

        try
        {
            input = getValidatedInput<int>();
        }
        catch (exception e)
        {
            cerr << e.what() << endl;
            continue;
        }

        break;
    }

    cout << "You entered: " << input << endl;

    return EXIT_SUCCESS;
}

Sample run

Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.

输入整数:a无效输入。输入整数:2b输入无效。输入一个整数:3您输入了:3。

#5


I'm not trying to be rude. I just wanted to share a solution I provided which I believe is more robust and allows for better input validation.

我不是想要粗鲁。我只想分享我提供的解决方案,我相信它更强大,并允许更好的输入验证。

Please refer to: My Solution to Input Validation

请参阅:我的输入验证解决方案

#6


I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.

我尝试了许多使用>>运算符从用户读取整数输入的技术,但是在某种程度上我的所有实验都失败了。

Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:

现在我认为getline()函数(不是std :: istream上具有相同名称的方法)和include cstdlib中的strtol()函数是此问题唯一可预测的一致解决方案。如果有人证明我错了,我将不胜感激。这是我使用的那个:

#include <iostream>
#include <cstdlib>

// @arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
    using namespace std; // *1
    while(true)
    {
        cout << prompt;
        string s;
        getline(cin,s);
        char *endp = 0;
        int ret = strtol(s.c_str(),&endp,10);
        if(endp!=s.c_str() && !*endp)
            return ret;
    }
}
  • *1: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
  • * 1:使用命名空间放置任何东西;在全球范围内可能导致在大型项目上破坏“统一构建”(google!),因此应该避免。练习不使用这种方式,即使是在较小的项目上!

  • Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
  • 从文件中读取整数是一个非常不同的问题。 RaúlRoa的方法如果得到适当的解决方案可能会有好处。我还建议不应该容忍错误的输入文件,但它实际上取决于应用程序。

  • Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
  • 请注意,在cin上的相同程序中使用>>和getline()会导致一些问题。只使用其中一个,或谷歌知道如何处理问题(不是太难)。

#7


Something like:

double a;
cin >> a;

Should read your signed "decimal" fine.

应该阅读您签署的“十进制”罚款。

You'll need a loop and some code to make sure it handles invalid input in a sensible way.

你需要一个循环和一些代码来确保它以合理的方式处理无效输入。

Good luck!

#1


If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:

如果cin的后备变量是一个数字,并且提供的字符串不是数字,则返回值为false,因此您需要一个循环:

int someVal;

while(!(cin >> someVal)) {
   cin.reset();
   cout << "Invalid value, try again.";
}

#2


double i;

//Reading the value
cin >> i;

//Numeric input validation
if(!cin.eof())
{
    peeked = cin.peek();
    if(peeked == 10 && cin.good())
    {
             //Good!
             count << "i is a decimal";
        }
        else
        {
             count << "i is not a decimal";
         cin.clear();
         cin >> discard;
        }
}

This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.

这也给出了输入-1a2.0的错误消息,避免了将-1分配给i。

#3


cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char for the second field.

cin的>>运算符通过一次读取一个字符直到它碰到空白来工作。这将淹没整个字符串-1a2.0,这显然不是一个数字,因此操作失败。看起来你实际上有三个字段,-1,a和2.0。如果按空格分隔数据,cin将能够毫无问题地读取每个数据。只记得读第二个字段的字符。

#4


Combining the techniques from the top answer here and this website, I get

结合这里的最佳答案和本网站的技术,我得到了

input.h

#include <ios>  // Provides ios_base::failure
#include <iostream>  // Provides cin

template <typename T>
T getValidatedInput()
{
    // Get input of type T
    T result;
    cin >> result;

    // Check if the failbit has been set, meaning the beginning of the input
    // was not type T. Also make sure the result is the only thing in the input
    // stream, otherwise things like 2b would be a valid int.
    if (cin.fail() || cin.get() != '\n')
    {
        // Set the error state flag back to goodbit. If you need to get the input
        // again (e.g. this is in a while loop), this is essential. Otherwise, the
        // failbit will stay set.
        cin.clear();

        // Clear the input stream using and empty while loop.
        while (cin.get() != '\n')
            ;

        // Throw an exception. Allows the caller to handle it any way you see fit
        // (exit, ask for input again, etc.)
        throw ios_base::failure("Invalid input.");
    }

    return result;
}

Usage

inputtest.cpp

#include <cstdlib>  // Provides EXIT_SUCCESS
#include <iostream>  // Provides cout, cerr, endl

#include "input.h"  // Provides getValidatedInput<T>()

int main()
{
    using namespace std;

    int input;

    while (true)
    {
        cout << "Enter an integer: ";

        try
        {
            input = getValidatedInput<int>();
        }
        catch (exception e)
        {
            cerr << e.what() << endl;
            continue;
        }

        break;
    }

    cout << "You entered: " << input << endl;

    return EXIT_SUCCESS;
}

Sample run

Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.

输入整数:a无效输入。输入整数:2b输入无效。输入一个整数:3您输入了:3。

#5


I'm not trying to be rude. I just wanted to share a solution I provided which I believe is more robust and allows for better input validation.

我不是想要粗鲁。我只想分享我提供的解决方案,我相信它更强大,并允许更好的输入验证。

Please refer to: My Solution to Input Validation

请参阅:我的输入验证解决方案

#6


I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.

我尝试了许多使用>>运算符从用户读取整数输入的技术,但是在某种程度上我的所有实验都失败了。

Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:

现在我认为getline()函数(不是std :: istream上具有相同名称的方法)和include cstdlib中的strtol()函数是此问题唯一可预测的一致解决方案。如果有人证明我错了,我将不胜感激。这是我使用的那个:

#include <iostream>
#include <cstdlib>

// @arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
    using namespace std; // *1
    while(true)
    {
        cout << prompt;
        string s;
        getline(cin,s);
        char *endp = 0;
        int ret = strtol(s.c_str(),&endp,10);
        if(endp!=s.c_str() && !*endp)
            return ret;
    }
}
  • *1: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
  • * 1:使用命名空间放置任何东西;在全球范围内可能导致在大型项目上破坏“统一构建”(google!),因此应该避免。练习不使用这种方式,即使是在较小的项目上!

  • Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
  • 从文件中读取整数是一个非常不同的问题。 RaúlRoa的方法如果得到适当的解决方案可能会有好处。我还建议不应该容忍错误的输入文件,但它实际上取决于应用程序。

  • Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
  • 请注意,在cin上的相同程序中使用>>和getline()会导致一些问题。只使用其中一个,或谷歌知道如何处理问题(不是太难)。

#7


Something like:

double a;
cin >> a;

Should read your signed "decimal" fine.

应该阅读您签署的“十进制”罚款。

You'll need a loop and some code to make sure it handles invalid input in a sensible way.

你需要一个循环和一些代码来确保它以合理的方式处理无效输入。

Good luck!