【问题标题】:Finding non-integer in a string在字符串中查找非整数
【发布时间】:2021-01-06 12:54:04
【问题描述】:

我正在尝试错误检查命令行参数以确保它们是整数,但令人惊讶的是,这样做很困难。这是我的一个 sn-p 代码,当所有命令行参数都是整数时,它可以工作。

程序可以有无限的值传递给它。
一个例子:./program -p 45 67 3 9 1

for (argCounter = 2; argCounter < argc; argCounter++) 
{
    total = total * atoi(argv[argCounter]);
}

当用户输入5g 时会发生什么? atoi() 将其转换为 5。我需要它返回错误。出于某种原因,我无法让isdigit() 也正常工作。我尝试了很多随机的东西,以至于我的头在这一点上旋转。所以我想做的是:

    for (argCounter = 2; argCounter < argc; argCounter++) 
    {
        //pseudocode
        if (argv[argCounter] != integer)
        {
              printf("Error!");
              return 0;
        } 

        total = total * atoi(argv[argCounter]);
    }

【问题讨论】:

  • 您的问题是“如何检查字符串中的每个字符是否都是数字?”。 strol 的文档可能解释了如何检查整个字符串是否为有效整数。 (见here,如果调用后*endptr==0,则解析整个字符串。)
  • blindside044 请不要在以下 2 个地方用无意义的“无效”发表评论。最好说明使用的输入、看到的输出和预期的输出。更好的是,这个问题应该有一个minimal reproducible example

标签: c command-line-arguments


【解决方案1】:

您可以使用sscanf()。它的%n占位符可以用来确定消耗的字符数,可以和字符串长度进行比较:

for (argCounter = 2; argCounter < argc; argCounter++) 
{
    int value, consumed;

    if ((sscanf(argv[argCounter], "%d%n", &value, &consumed) != 1) ||
        (argv[argCounter][consumed] != '\0'))
    {
        printf("Error!");
        return 0;
    } 

    total *= value;
}

或者,您可以使用strtol()。它可以输出指向第一个未解析字符的指针。您可以检查该字符是否为空终止符:

for (argCounter = 2; argCounter < argc; argCounter++) 
{
    char *end;

    errno = 0;
    long value = strtol(argv[argCounter], &end, 10);

    if ((end == argv[argCounter]) ||
        (*end != '\0') ||
        (((value == LONG_MIN) || (value == LONG_MAX)) && (errno == ERANGE)))
    {
        printf("Error!");
        return 0;
    } 

    total *= value;
}

【讨论】:

  • 第一个解决方案不起作用,但使用 strtol() 的第二个解决方案起作用了。谢谢你。现在要弄清楚它是如何/为什么起作用的,因为复制/粘贴对我没有好处 =D .....我记得曾经尝试使用 strtol() 但该功能让我有点困惑,所以我不知道我在做什么正在做。
  • @blindside044 "第一个解决方案无效" - Works fine for me
  • 顺便说一句:我发现"%d %n" 带有空格是一种更好更宽容的格式,因为它允许尾随空格通过 - 不是尾随或前导空格通常在程序参数中遇到。
  • @chux-ReinstateMonica “程序参数通常不会遇到尾随或前导空格” - 它们根本不应该出现,除非可能在引用的参数中。跨度>
  • 没错,它们可能由于引用的参数、对main() (yeech) 和exec() 的调用而发生。无论如何都是好的答案 - 只是注意到潜在的扩展。
【解决方案2】:

嗯,我是一个初学者,我不完全明白你想做什么? 如果我理解,您想检查所有参数是否是整数范围内的数字(仅数字),您希望总数包含所有这些整数相乘的结果(我假设您也希望总数在整数范围内? )

long long total = 1;
for (argCounter = 1; argCounter < argc; argCounter++) 
{
    char *check_end;
    long long nbr = stroll(arg[argCounter], &check_end, 10);
    if (!argv[argCounter][0]|| *check_end || nbr > INT_MAX || nbr < INT_MIN || nbr * total > INT_MAX || nbr * total < INT_MIN)
    {
        total = 0;
        printf("Error\n");
        break;
    }
    total *= nbr;
}

也许这应该会有所帮助,将基础(作为第三个参数)中的字符串(作为第一个参数给出)转换为 long long 并将字符串的指针(作为第二个参数给出)设置到字符串上的位置转换停止(\0,如果符号后只有数字)你可以检查漫步者;无论如何,我不确定我的代码是否非常优化或功能强大,您可能希望在最后得到一个 int,以便将 int 总变量转换为 int 变量。

【讨论】:

  • 我尝试了您的解决方案,但没有奏效。雷米的第二个解决方案似乎对我有用。无论如何,谢谢。
  • 注意:OP的代码从argCounter = 2;开始
  • 很好奇,为什么代码使用long long vs long 然后与INT_MAX, INT_MIN 比较? nbr * total 也很容易溢出,导致未定义的行为 (UB)。
  • 好吧,是的,我是一个初学者,并试图用一些东西来最大化检测 INT 溢出的机会,因为我认为盲人想要的东西,无论如何它仍然可以溢出我猜(INT_MAX * INT_MAX肯定大于 long long 最大值。对不起我的菜鸟
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2011-01-31
  • 2020-11-27
  • 2021-04-16
  • 1970-01-01
  • 2012-04-09
  • 2013-11-17
相关资源
最近更新 更多