我如何检查argv [1]没有任何字母字符?

时间:2016-02-17 05:24:06

标签: c++ validation input argv

这一直在推动我的整个C ++类坚果,我们都没有能够找到解决这个问题的可靠方案。 我们通过终端通过argv* [1]将信息传递给我们的计划。我们会调用我们的程序./main 3,程序将运行3次。

问题出现在我们验证输入时,我们试图覆盖我们所有的基础,对于大多数我们都很好,就像输入的字母字符,负数,0等等。但是什么不断传递是int,后跟str,例如./main 3e./main 1.3。我试过this (Ashwin的回答引起了我的注意)但它似乎没有用,或者至少我无法在我的代码中实现它。

这是我现在的代码:

int main(int argc, char * argv[]){
    if (!argv[1]) exit(0);

    int x = atoi(argv[1]);

    if (!x or x <= 0) exit(0); 

    // I would like to add another exit(0); for when the input mixes numbers and letters or doubles.

    for (int i = 0; i < x; i++){
        // rest of the main func.
    }

2 个答案:

答案 0 :(得分:2)

尽管有标题,听起来你真正想做的是检查输入参数中的每个字符是否都是数字。您可以通过迭代来实现这一点,使用std::isdigit检查每个元素是否为数字。

这是使用std::all_of算法的草图:

size_t len = strlen(argv[1]);
bool ok = std::all_of(argv[1], argv[1] + len,
                      [](unsigned char c) { return std::isdigit(c); } );

如果需要,您可以为'0'的第一个元素添加额外的检查。

答案 1 :(得分:0)

如果要将字符串转换为数字验证整个字符串是否为数字,则可以使用strtol代替atoi。作为额外的奖励,strtol正确检查溢出,并为您提供指定是否需要十六进制/八进制转换的选项。

这是一个简单的实现,记录了所有错误(来自这样的函数的打印错误消息不是一个好主意;我只是为了紧凑而做了)。更好的选择可能是返回错误枚举而不是bool,但此函数返回std::pair<bool, int>(false, <undefined>)(true, value)

std::pair<bool, int> safe_get_int(const char* s) {
  char* endptr;
  bool ok = false;
  errno = 0; /* So we can check ERANGE later */
  long val = strtol(s, &endptr, 10); /* Don't allow hex or octal. */
  if (endptr == s) /* Includes the case where s is just whitespace */
     std::cout << "You must specify some value." << '\n';
  if (*endptr != '\0')
     std::cout << "Argument must be an integer: " << s << '\n';
  else if (val < 0)
     std::cout << "Argument must not be negative: " << s << '\n';
  else if (errno == ERANGE || val > std::numeric_limits<int>:max())
     std::cout << "Argument is too large: " << s << '\n';
  else
     ok = true;
  return std::make_pair(ok, ok ? int(val) : 0);
}

一般来说,哲学术语,当你有一个像strtol(或者,就此而言,fopen)这样的API来检查错误并在发生错误时拒绝请求时,它会更好编程样式“尝试然后检查错误返回”,而不是“尝试预测错误,只有尝试看起来没问题”。第二种策略“使用前检查”受到漏洞的困扰,包括安全漏洞(当然不是这种情况,但请参阅TOCTOU进行讨论)。它也没有真正帮助你,因为你必须检查错误返回,以防你的预测器不够准确。

当然,您需要确信有问题的API在输入错误时没有未定义的行为,因此阅读官方文档。在这种情况下,atoi 确实在输入错误时有UB,但strtol没有。 (atoi:“如果无法表示该值,则行为未定义。”;与strtol对比