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

C 检查第一个参数是否为仅由十进制数字组成的有效数字,c,cs50,C,Cs50,这是我试图用于“验证密钥”部分的代码,仅当参数是数字时才尝试返回成功。然而,当我运行我的程序时,一些数字被认为是错误的。我不明白为什么 ~/pset2/caesar/ $ ./caesar 9 Usage: ./caesar key ~/pset2/caesar/ $ ./caesar 45 Success 45 #包括 #包括 #包括 #包括 #包括 int main(int argc,字符串argv[]){ int n=atoi(argv[1]); if(argc==2&&isdigit

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

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

#包括
#包括
#包括
#包括
#包括
int main(int argc,字符串argv[]){
int n=atoi(argv[1]);
if(argc==2&&isdigit(argv[1][n])){
printf(“成功\n%s\n”,argv[1]);
返回0;
}否则{
printf(“用法:./caesar key\n”);
返回1;
}
您的错误如下:

if (argc == 2 && isdigit(argv[1][n])) {
这一行没有意义,您正在检查第一个参数的第n个字符是否是数字,但是(1)您甚至不知道第一个参数是否有足够的字符(
n
atoi
返回,因此它可能是任意大的)和(2)您没有检查参数的所有数字


如果要检查给程序的第一个参数中的每个字符是否都是数字,可以通过两种方式进行检查:

  • 迭代每个字符并使用
    isdigit()
    进行检查:

    #包括
    #包括
    int main(int argc,字符**argv){
    char*c;
    如果(argc!=2){
    FPUT(“用法:./prog\n”,标准);
    返回1;
    }
    对于(c=argv[1];*c!='\0';c++){
    如果(!isdigit(*c)){
    FPUT(“用法:./prog\n”,标准);
    返回1;
    }
    }
    printf(“成功!\n%s\n”,argv[1]);
    返回0;
    }
    
  • 使用类似(not
    atoi
    )的函数,因为它不会发出错误信号。使用
    strtol
    还可以自动检查数字是否在可存储在
    long
    中的值范围内(如果不是,则返回
    LONG\u MIN
    LONG\u MAX
    ,并适当设置
    errno

    #包括
    #包括
    #包括
    #包括
    int main(int argc,字符**argv){
    长数;
    char*endp;
    如果(argc!=2){
    FPUT(“用法:./prog\n”,标准);
    返回1;
    }
    errno=0;
    num=strtol(argv[1],&endp,10);
    if(endp==argv[1]| |*endp!='\0'| | errno==ERANGE){
    FPUT(“用法:./prog\n”,标准);
    返回1;
    }
    printf(“成功!\n%ld\n”,num);
    返回0;
    }
    
  • 选项2的优点是已经为您转换了数字,因此我建议您使用选项1。请注意,如果给定字符串以
    -
    开头,则
    strtol
    可以返回负值(例如
    -123
    ):如果不允许使用负数,您可能需要检查该值

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

    对于像
    “123”
    这样的输入参数,下面的代码尝试检查3个字符参数的第123个字符是否为数字。对
    argv[1]
    外部
    “123”
    的访问是未定义的行为(UB)-错误


    要测试输入是否为所有数字:

  • 在使用
    argv[1]
    之前,请检查预期的参数数

  • 测试字符串的每个字符
    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 == '\0') {
          printf("Success\n%s\n", argv[1]);
          return 0;
        }
      }
      printf("Usage: ./caesar key\n");
      return 1;
    }
    

    验证这些输入的正确方法是使用
    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("Success\n%s\n", argv[1]);
        return 0;
      } else {
        printf("Usage: ./caesar key\n");
        return 1;
      }
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    int validate_arg(常量字符*s){
    尺寸透镜;
    len=标准参考编号(s,“0123456789”);
    返回len>0&!s[len];
    }
    int main(int argc,字符串argv[]){
    int n=atoi(argv[1]);
    if(argc==2&&validate_arg(argv[1])){
    printf(“成功\n%s\n”,argv[1]);
    返回0;
    }否则{
    printf(“用法:./caesar key\n”);
    返回1;
    }
    }
    

    旁注:最好使用无符号类型,并使用
    stroul

    转换数字。请以可读的方式格式化代码。您需要检查每个
    argv[1][i]
    ,其中
    i
    从0到
    strlen(argv[1])
    。如果(argc==2…未正确检查是否有足够的参数。正确使用了
    strspn()
    。是的,我没有纠正其他方面,只是验证。
    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 == '\0') {
          printf("Success\n%s\n", argv[1]);
          return 0;
        }
      }
      printf("Usage: ./caesar key\n");
      return 1;
    }
    
        const unsigned char *digit = argv[1];
        while (isdigit(*digit)) {
          digit++;
        }
    
    #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("Success\n%s\n", argv[1]);
        return 0;
      } else {
        printf("Usage: ./caesar key\n");
        return 1;
      }
    }