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

How do i check argv[1] doesn't have any alphabetical characters?

这让我的整个 C++ class 发疯,我们中的 none 已经找到了解决这个问题的可靠方法。 我们正在通过终端通过 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.
    }

尽管标题如此,但听起来您真正想做的是检查输入参数中的每个字符是否都是数字。您可以通过遍历它来实现这一点,使用 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' 添加额外检查。

如果要将字符串转换为数字 验证整个字符串是否为数字,可以使用 strtol 而不是 atoi。作为额外的好处,strtol 正确检查溢出并为您提供指定是否需要 hexadecimal/octal 转换的选项。

这是一个简单的实现,其中记录了所有错误(从这样的函数打印错误消息不是一个好主意;我这样做只是为了简洁)。更好的选择可能是 return 一个错误枚举而不是 bool,但是这个函数 return 是一个 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 != '[=10=]')
     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 时,它将检查错误并拒绝请求发生错误,编程风格 "try and then check the error return" 比 "attempt to predict an error and only try if it looks ok" 更好。第二种策略 "check before use" 充满了错误,包括安全漏洞(当然,在这种情况下不是,但请参阅 TOCTOU 进行讨论)。它也没有真正帮助你,因为无论如何你都必须检查错误 returns,以防你的预测器不够精确。

当然,您需要确信所讨论的 API 在错误输入时没有未定义的行为,因此 阅读官方文档 。在这种情况下,atoi 确实 有错误输入的 UB,但 strtol 没有。 (atoi: "If the value cannot be represented, the behavior is undefined."; contrast with strtol)