【发布时间】:2021-03-04 08:57:29
【问题描述】:
我正在尝试编写一个程序来检查一个文本文件,但也使用一个作为最后一个参数传递的数字。我想做一些错误检查以确保最后一个参数是数字。
【问题讨论】:
-
什么是
digit? -
isdigit((usigned char)argv[argc-1][0]) && (argv[argc-1][1] == 0)
我正在尝试编写一个程序来检查一个文本文件,但也使用一个作为最后一个参数传递的数字。我想做一些错误检查以确保最后一个参数是数字。
【问题讨论】:
digit?
isdigit((usigned char)argv[argc-1][0]) && (argv[argc-1][1] == 0)
我不知道digit()函数是什么,但是不管这个函数是什么,它永远不会检查字符串argv[argc-1]是否成功。这是因为如果argv[argc-1] 不是数字字符串,则atoi() 函数将返回零作为错误,但如果argv[argc-1] 是"0" 也将返回零。
要验证argv[argc-1] 是否为一位且只有一位,您需要:
argv[argc-1][1] == '\0');isdigit( argv[argc-1][0] ))。这是最终代码。
char *a = argv[argc-1];
if ( (a[1] != '\0') || !isdigit(a[0]) ) {
printf("No valid digit entered\n");
exit(1);
}
我的原始答案有两个问题,如下面的一些用户所述。
首先,我假设argv 中的字符串不能为空。但是,如果像./program "" 这样调用程序,argv[1] 将是一个空字符串。
出于演示目的,这里有一个程序可以打印stdout 所有argv 字符串及其长度。
/* program.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
for (int i = 0; i < argc; i++)
printf("strlen(\"%s\") = %zu\n", argv[i], strlen(argv[i]));
return EXIT_SUCCESS;
}
这是输出,确认argv[1]是一个空字符串。
$ gcc -Wall -std=c99 -o program program.c
$ ./program ""
strlen("./program") = 9
strlen("") = 0
$
第二个问题与isdigit()函数的使用有关。根据手册(终端上的man isdigit),传递给isdigit() 的参数必须是unsigned char。
int isdigit(int c);
这些函数检查是否 c,它的值必须是 an unsigned char 或 EOF,属于某个字符类 到指定的语言环境。
这是没有下面cmets中提到的问题的最终解决方案。
char *a = argv[argc-1];
if ( !isdigit((unsigned char) a[0]) || (a[1] != '\0') ) {
printf("No valid digit entered\n");
exit(1);
}
【讨论】:
!isdigit(a[0]) 首先防止测试超出 null 字符。虽然长度为 0 的 argv[] 并不常见,但在某些情况下是可能的(例如在调用 main().IAC 时,更习惯于在下一个之前测试 a[] 的第一个数组元素。
there is no way for a string in argv to be empty, unless you changed it:这是不正确的。在 C 中没有被禁止。 argv[i] 很有可能指向一个空字符串。例如,程序可以这样调用:./program "" 和 argv[1] 将指向一个空字符串。
isdigit 的参数需要转换为unsigned char 以避免未定义行为的风险。
"%ld\n",与strlen()中的size_t类型肯定不匹配。最好使用"%zu\n"。
atoi()函数如果argv[argc-1]不是数字字符串会返回零作为错误 No, it's even worse than that: "如果结果的值不能被表示,行为是未定义的。”它可能会返回零。或者它也可以在 750 万年后返回 42...