c-检查第一个参数是否为仅由十进制数字组成的有效数字



这是我试图用于;验证密钥";部分,尝试仅在参数为数字时返回成功。然而,当我运行程序时,有些数字被认为是错误的。我不明白为什么。

~/pset2/caesar/ $ ./caesar 9
Usage: ./caesar key
~/pset2/caesar/ $ ./caesar 45
Success
45

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h> 
#include <stdlib.h> 
int main(int argc, string argv[]) {
int n = atoi(argv[1]);
if (argc == 2 && isdigit(argv[1][n])) {
printf("Successn%sn", argv[1]);
return 0;
} else {
printf("Usage: ./caesar keyn");
return 1;
}

您的错误在这里:

if (argc == 2 && isdigit(argv[1][n])) {

这一行没有意义,您正在检查第一个参数的第n个字符是否是一个数字,但(1(您甚至不知道第一个参数是否有足够的字符(natoi返回,因此它可以任意大(,(2(您没有检查参数的所有数字。


如果你想检查给程序的第一个参数中的每个字符都是一个数字,你可以用两种方法:

  1. 遍历每个字符并使用isdigit():进行检查

    #include <stdio.h>
    #include <ctype.h>
    int main(int argc, char **argv) {
    char *c;
    if (argc != 2) {
    fputs("Usage: ./prog <key>n", stderr);
    return 1;
    }
    for (c = argv[1]; *c != ''; c++) {
    if (!isdigit(*c)) {
    fputs("Usage: ./prog <key>n", stderr);
    return 1;
    }
    }
    printf("Success!n%sn", argv[1]);
    return 0;
    }
    
  2. 使用类似strtol的函数(而不是atoi,因为它不会发出错误信号(。使用strtol还可以自动检查数字是否在可以存储在long中的值范围内(如果不在,则返回LONG_MINLONG_MAX,并适当设置errno(。

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <limits.h>
    int main(int argc, char **argv) {
    long num;
    char *endp;
    if (argc != 2) {
    fputs("Usage: ./prog <key>n", stderr);
    return 1;
    }
    errno = 0;
    num = strtol(argv[1], &endp, 10);
    if (endp == argv[1] || *endp != '' || errno == ERANGE) {
    fputs("Usage: ./prog <key>n", stderr);
    return 1;
    }
    printf("Success!n%ldn", num);
    return 0;
    }
    

选项2的优点是已经为您转换了数字,所以我建议您不要选择选项1注意如果给定字符串以-(例如-123(开头,则strtol可能返回负值:如果不允许负数,则可能需要检查该值。

验证此类输入的正确方法是使用strspn并检查它是否包含整个字符串。在几乎所有情况下,strspn都会比任何手动编码版本更快,除非您将验证和转换结合起来。

这是你的代码,带有一个验证函数,可以做到这一点:

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h> 
#include <stdlib.h> 
int validate_arg(const char *s) {
size_t len;
len = strspn(s, "0123456789");
return len > 0 && !s[len];
}
int main(int argc, string argv[]) {
int n = atoi(argv[1]);
if (argc == 2 && validate_arg(argv[1])) {
printf("Successn%sn", argv[1]);
return 0;
} else {
printf("Usage: ./caesar keyn");
return 1;
}
}

附带说明:最好使用无符号类型,并使用strtoul转换数字。

当我运行程序时,一些数字被认为是错误的。

使用类似"123"的输入参数,下面的代码尝试检查3个字符参数的第123个字符是否为数字。访问"123"之外的argv[1]是未定义的行为(UB(-错误。

int n = atoi(argv[1]);
if (... isdigit(argv[1][n])) ...  // UB

测试输入是否全部为数字:

  1. 使用argv[1]检查之前的预期参数数

  2. 测试字符串argv[1][]的每个字符。

样品

int main(int argc, string argv[]) {
if (argc == 2) { 
const char *digit = argv[1];
while (*digit >= '0' && *digit <= '9') {
digit++;
}
// If code reached the end of the string?
if (*digit == '') {
printf("Successn%sn", argv[1]);
return 0;
}
}
printf("Usage: ./caesar keyn");
return 1;
}

代码也可以使用isdigit(),最好使用unsigned char值调用:

const unsigned char *digit = argv[1];
while (isdigit(*digit)) {
digit++;
}

相关内容

  • 没有找到相关文章

最新更新