【问题标题】:How to check if argv[count] is an integer如何检查 argv[count] 是否为整数
【发布时间】:2015-05-20 11:39:44
【问题描述】:

我正在尝试在 C++ 中创建一个命令行应用程序,并且我想确保输入是某个命令参数之后的整数。

对于这个例子,我想检查“-p”命令参数之后的下一个参数是否是一个整数。这是我现在的代码的 sn-p。

while (count < argc){
    if (strcmp("-p", argv[count]) == 0){
        has_p = true; //Boolean
        pid = atoi(argv[count + 1]);
        if (pid == 0 && argv[count + 1] != "0" ){
            err = 1;
            cout << "pid argument is not a valid input" << endl;
            pid = -1;
        }
        count++;
    }
...
}

现在这段代码正确地捕捉到了这个输入中的错误:

  • -p 1777
  • -p sss
  • -p sss17
  • -p [空格] -U

但在这种输入格式下失败

  • -p 17sss

我试图通过使用 sprintf 进行比较来解决这个问题。不幸的是,为 sprintf 提供 char 数组指针仅在 buffer2 中输出 1 个字符。

while (count < argc){
    if (strcmp("-p", argv[count]) == 0){
        has_p = true; //Boolean
        pid = atoi(argv[count + 1]);
        sprintf(buffer, "%d", pid);
        sprintf(buffer2, "%d", *argv[count + 1]);
        if (pid == 0 && argv[count + 1] != "0" || (buffer != buffer2) ){
            err = 1;
            cout << "pid argument is not a valid input" << endl;
            pid = -1;
        }
        count++;
    }
...
}

有没有办法让 sprintf 读取整个 char 数组?如果没有,除了循环指针直到我点击“\0”

之外,还有更好的解决方案吗?

【问题讨论】:

  • 选择一种语言。你说的是 C++,但你使用的是 C 习语,问题是用两者来标记的。
  • 使用strcmp 比较两个字符串,而不是!=。您可以使用if( isdigit(argv[count]) ) 来检查参数是否为数字。
  • 哦,我的错。我在 Visual Studio 2013 中编程,所以我将它标记为 c++。但我也希望它在 c 中编译。
  • 更新“我也希望它在 c 中编译” - 然后删除 C++ 标签。 // 对于 C++,boost 的 lexical_cast&lt;int&gt;(argv[count + 1]) 是一个不错的选择 - 如果无法从文本中解析出 int,或者之后有垃圾文本,它会抛出异常......

标签: c pointers printf


【解决方案1】:

atoi() 不能做你想做的事。您需要使用strtol() 来实现这一点。它大大提高了错误检查能力。

签名:

long int strtol(const char *nptr, char **endptr, int base);

此函数将转换后的整数作为 long int 值返回,否则返回零值。 转换后,您可以查看endptr的内容并决定。

【讨论】:

  • 附注:endptr 将被设置为指向数字后的第一个字符,因此如果数字是有效整数,它应该指向一个结束字符串的空终止符.也就是说,要检查转换是否成功,请执行if (*endptr == 0)
  • 你可以使用函数的返回值来决定。
  • @ANjaNA - 不,您不能使用返回值来确定转换是否失败,因为转换失败时的返回值也可能是转换成功的结果。您必须使用endptr的值。
  • @AndrewHenle 这就是为什么atoi 如此迟钝。说真的,我很想见见将atoiatofgets 引入标准的人,并询问他们当时的想法。
【解决方案2】:

下面是一个方便的单行...

sscanf(argv[count + 1], "%d%*c", &n) == 1

...如果可以读入 int n 并且之后没有尾随字符,则评估结果为 true。 %*c 中的 '*' 禁止赋值,因此无需传递指向虚拟 char 变量的指针。见scanf docs here

【讨论】:

  • 我试过了,和上面的问题一样。适用于以下输入,但无法捕获“-p 17ss”输入的错误
  • @MDuh:它是如何“失败”的? - 你可以看到here sscanf 如何返回0... 根据上面的== 1 测试,这确实意味着它捕获了错误。当它准确返回 1 时,输入有效,n 将被设置为其数值。
  • 更明确地说,对于您想要的特定用例 if (sscanf(argv[count + 1], "%d%*c", &amp;pid) != 1) { err = 1; cout &lt;&lt; "pid argument is not a valid input" &lt;&lt; endl; pid = -1; } 等...
  • 哦,是的。错过了那部分,忘记替换我的if条件>。>。是的,现在也确实有效。
【解决方案3】:

您还可以使用 c++11 替代方案,这些替代方案是根据 strtol 实现的(请参阅stol)。

【讨论】:

  • 这不值得被否决,因为它是在问题也被标记为 C++ 时发布的......
【解决方案4】:

在 C 中,您可以简单地通过 char* 并检查是否只有数字。

char c = '0';
int i = 0;
int err = 0
while ( c != '\0'){
    if (arg[i] < 47 || arg[i] > 57){
        err = 1;
        break;
    }

【讨论】:

    猜你喜欢
    • 2015-01-09
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 2015-02-25
    • 1970-01-01
    相关资源
    最近更新 更多