检查以确保argv [1]是一个整数c ++

时间:2013-04-22 21:17:05

标签: c++ integer argv argc

对于我的程序,我必须确保用户只输入一个正整数。例如,如果用户输入12hi,则不应运行程序并打印到std错误。我不太清楚如何实现这个。

int main(int argc, char *argv[])   
{ 
    if(atoi(argv[1]) < 1)
    {
        cerr << "ERROR!"<< endl;
        return 1;
    }
    return 0;
}

5 个答案:

答案 0 :(得分:4)

将其传递给std::istringstream并确保处理完所有数据:

if (a_argc > 1)
{
    std::istringstream in(a_argv[1]);
    int i;
    if (in >> i && in.eof())
    {
        std::cout << "Valid integer\n";
    }
}

请参阅http://ideone.com/8bEYJq的在线演示。

答案 1 :(得分:1)

好的,我修改了答案。 sscanf没有表现出我的想法,strtol提供了非常便携的最佳C类解决方案。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  for (int i=1; i < argc; i++){
      char* end;
      long val = strtol(argv[i], &end, 10);
      if (argc >= 2 && !end[0] && val >= 0){
          printf("%s is valid\n", argv[i]);
      } else {
          printf("%s is invalid\n", argv[i]);
      }
  }
  return 0;
}

示例输出:   ./a.out 10 -1 32 1000 f -12347 +4 --10 10rubbish

10 is valid
-1 is valid
32 is valid
1000 is valid
f is invalid
-12347 is valid
+4 is invalid
--10 is invalid
10rubbish is invalid

这是有效的,因为strtol会将参数转换为long int。然后如果end [0]不在字符串的末尾那么它将是非零意味着它会为10rubbish抛出一个错误但是对于像10这样的值是可以的。那么当然我们只想要正整数而且我已经包含该集合中的值0。

atoi()本身并不够好,因为失败会返回零。 0可能是有效的输入。

sscanf()本身也不够好,因为它会成功转换10rubbish之类的字符串并返回值10.

我意识到op只想要argv [1],这个答案会扫描所有提供的args,只是为了显示许多有效和无效条目的输出。

答案 2 :(得分:1)

由于您显然不反对使用标准C库, 功能

long strtol (const char* str, char** endptr, int base)
来自<cstdlib>

足以确保。{1}} commandline参数是一个(长)整数,带有一个可选项 “ - ”或“+”前缀,仅此而已。你只需要 检查char *存储在endptr的返回地址'\ 0', 它告诉你函数已经消耗了整个参数。

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])   
{
    if (argc < 2) {
        return 1;
    }

    char * endp;
    long i = strtol(argv[1],&endp,10);
    if (!*endp) {
        cout << "The value of \"" << argv[1] << "\" is " << i << endl;
        return 0;
    }
    cerr << "\"" << argv[1] << "\" is not an integer" << endl;
    return 1;
}

以后 ......或者为Steve Jessop的评论提供服务:

#include <cstdlib>
#include <iostream>
#include <climits>

using namespace std;

int main(int argc, char *argv[])   
{
    if (argc < 2) {
        return 1;
    }

    char * endp;
    long i = strtol(argv[1],&endp,10);

    if (*endp) {
        cerr << "\"" << argv[1] << "\" is not an integer :(" << endl;
        return 1;
    }
    if (endp == argv[1]) {
        cerr << "Empty string passed :(" << endl;
        return 1;
    }
    if (i < 0) {
        cerr << "Negative " << i << " passed :(" << endl;
        return 1;
    }
    if (i <= INT_MAX) {
        cout << "Non-negative int " << i << " passed :)" << endl;
    } else {
        cout << "Non-negative long " << i << " passed :)" << endl;
    }
    return 0;

}

包装函数将是为了这种程度的歧视。那里 仍然是非常极端的情况,即ULONG_MAX的输入将被接受 为LONG_MAX

答案 3 :(得分:0)

您可以尝试检查argv[1]中的所有字符是否都是数字(可能带有前导减号)。可以使用标准库函数isdigit()执行检查。

http://www.cplusplus.com/reference/cctype/isdigit/

基于OP实际代码的完整解决方案(也可在http://codepad.org/SUzcfZYp获得):

#include <stdio.h>          // printf()
#include <stdlib.h>         // atoi()
#include <ctype.h>          // isdigit()

int main(int argc, char *argv[])   
{ 
    if( argc != 2 ) {
        return 0;
    }

    char * pWord = argv[ 1 ];
    char c = 0;
    for( int i = 0; c = pWord[ i ], c ; ++i ) {
        if( ! isdigit( c ) ) {
            return 0;
        }
    }

    int argvNum = atoi( argv[ 1 ] );
    printf( "argc = %d, argv[ 1 ] = %s, argvNum = %d\n",
        argc, argv[ 1 ], argvNum );
}

答案 4 :(得分:-1)

我是C ++的新手,所以如果这是错误的话请不要激怒我,但是你不能抛出异常并让用户重新纠正输入吗?

我已经学会了一些处理错误的方法:

  1. 如果/其他处理
  2. 断言
  3. 抛出异常
  4. 1.如果/ ELSE     #include

    int main(int argc, int **argv) {
        if (!isdigit(argv[1])) {
            // handle code if it's not a digit.
            return 0;
        }
    }
    

    这可能是确保

    的最简单方法

    2.ASSERT     #include

    int main(int argc, int *argv[]) {
        assert(isdigit(argv[1]));
    }
    

    *如果argv [1]不是数字

    ,则断言将终止程序

    3.THROW     #include

    using namespace std;
    
    class Except {};
    
    int main(int argc, int **argv) {
        try {
            isdigit(argv[1]);
            throw Except();
            // this code will not be executed
            // if argv[1] is not a digit
        }
        catch (Except) {
            cout << "argv[1] is not a digit.";
            // handle exception or rethrow
        } 
    }
    

    绝对值得注意的是,抛出异常将创建堆栈跟踪,并且抛出的异常和捕获异常的块之间的所有代码都不会被执行。