检查命令行输入是否为数字
check that command line input is numeric
我是 C 的新手,想编写一个简单的程序来调用正好有两个命令行参数(第一个是程序的名称,第二个是字符串)。
我已经验证了 number 个参数,现在想验证仅包含数字的输入。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <cs50.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if isdigit(argv[1][i])
{
printf("Success!\n");
}
else
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
else
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
虽然上面的代码没有抛出错误,但它没有正确验证输入,我不明白为什么。有人能给我指出正确的方向吗?
提前致谢,祝一切顺利
if (argc != 2)
必须是
if (argc == 2)
正在做
if isdigit(argv[1][i])
{
printf("Success!\n");
}
如果数字有 4 位,你将打印 "Success" 4 次,最好做类似的事情:
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (!isdigit(argv[1][i])
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
printf("Success!\n");
return 0;
示例:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char * argv[])
{
if (argc == 2)
{
int i, n;
for (i = 0, n = strlen(argv[1]); i < n; i++)
{
if (!isdigit(argv[1][i]))
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
printf("Success!\n");
}
else {
puts("argument is missing");
return 1;
}
return 0;
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
argument is missing
pi@raspberrypi:/tmp $ ./a.out az
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $ ./a.out 12
Success!
pi@raspberrypi:/tmp $ ./a.out 12a
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out 123
==2051== Memcheck, a memory error detector
==2051== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2051== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2051== Command: ./a.out 123
==2051==
Success!
==2051==
==2051== HEAP SUMMARY:
==2051== in use at exit: 0 bytes in 0 blocks
==2051== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==2051==
==2051== All heap blocks were freed -- no leaks are possible
==2051==
==2051== For counts of detected and suppressed errors, rerun with: -v
==2051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
虽然您可以依靠遍历字符来检查每个 isdigit()
,但如果您的目的是使用参数表示的数值,您也可以使用 strtol/strtoul
来转换值到一个 signed/unsigned
值,并依靠强大的错误报告来准确告诉您转换过程中发生了什么,以及参数的哪些部分(如果有的话)由非数字组成。
strtoX
函数族将指向数字字符串的指针和 endptr
的地址作为参数(以及整数转换的基数)。该函数尝试将数字转换为数字更新 endptr
以指向成功转换最后一个数字后的第一个字符。这允许您确定您的参数是否由前导数字组成,这些数字是否在尝试转换类型的范围内,以及在转换的最后一个数字之后是否存在任何其他字符。
一个简短的例子说明:
#include <stdio.h>
#include <stdlib.h> /* for strtol */
#include <errno.h> /* errno - for strtol validation */
int main (int argc, char **argv) {
char *endptr; /* end pointer for strtol */
long l;
if (argc < 2) { /* validate at least one argument provided */
fprintf (stderr, "error: insufficient arguments provided.\n"
"usage: %s number\n", argv[0]);
return 1;
}
errno = 0; /* zero errno before call */
l = strtol (argv[1], &endptr, 0); /* attempt converstion to long */
if (endptr == argv[1]) { /* check if digits were converted */
fprintf (stderr, "error: no digits converted in '%s'.\n", endptr);
return 1;
}
else if (errno) { /* check for error in conversion */
perror ("strtol-argv[1]");
return 1;
}
printf ("number provided: %ld\n", l); /* output number */
if (*endptr) /* endptr not pointing to `'[=10=]'`, chars remain */
printf ("\nadditional characters following number: '%s'.\n", endptr);
return 0;
}
例子Use/Output
$ ./bin/strtolarg 123456
number provided: 123456
$ ./bin/strtolarg -123456
number provided: -123456
$ ./bin/strtolarg "val=123456"
error: no digits converted in 'val=123456'.
$ ./bin/strtolarg "123456=val"
number provided: 123456
additional characters following number: '=val'.
检查一下,如果您有任何问题,请告诉我。
我是 C 的新手,想编写一个简单的程序来调用正好有两个命令行参数(第一个是程序的名称,第二个是字符串)。 我已经验证了 number 个参数,现在想验证仅包含数字的输入。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <cs50.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if isdigit(argv[1][i])
{
printf("Success!\n");
}
else
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
else
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
虽然上面的代码没有抛出错误,但它没有正确验证输入,我不明白为什么。有人能给我指出正确的方向吗?
提前致谢,祝一切顺利
if (argc != 2)
必须是
if (argc == 2)
正在做
if isdigit(argv[1][i])
{
printf("Success!\n");
}
如果数字有 4 位,你将打印 "Success" 4 次,最好做类似的事情:
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (!isdigit(argv[1][i])
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
printf("Success!\n");
return 0;
示例:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char * argv[])
{
if (argc == 2)
{
int i, n;
for (i = 0, n = strlen(argv[1]); i < n; i++)
{
if (!isdigit(argv[1][i]))
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
printf("Success!\n");
}
else {
puts("argument is missing");
return 1;
}
return 0;
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
argument is missing
pi@raspberrypi:/tmp $ ./a.out az
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $ ./a.out 12
Success!
pi@raspberrypi:/tmp $ ./a.out 12a
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out 123
==2051== Memcheck, a memory error detector
==2051== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2051== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2051== Command: ./a.out 123
==2051==
Success!
==2051==
==2051== HEAP SUMMARY:
==2051== in use at exit: 0 bytes in 0 blocks
==2051== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==2051==
==2051== All heap blocks were freed -- no leaks are possible
==2051==
==2051== For counts of detected and suppressed errors, rerun with: -v
==2051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
虽然您可以依靠遍历字符来检查每个 isdigit()
,但如果您的目的是使用参数表示的数值,您也可以使用 strtol/strtoul
来转换值到一个 signed/unsigned
值,并依靠强大的错误报告来准确告诉您转换过程中发生了什么,以及参数的哪些部分(如果有的话)由非数字组成。
strtoX
函数族将指向数字字符串的指针和 endptr
的地址作为参数(以及整数转换的基数)。该函数尝试将数字转换为数字更新 endptr
以指向成功转换最后一个数字后的第一个字符。这允许您确定您的参数是否由前导数字组成,这些数字是否在尝试转换类型的范围内,以及在转换的最后一个数字之后是否存在任何其他字符。
一个简短的例子说明:
#include <stdio.h>
#include <stdlib.h> /* for strtol */
#include <errno.h> /* errno - for strtol validation */
int main (int argc, char **argv) {
char *endptr; /* end pointer for strtol */
long l;
if (argc < 2) { /* validate at least one argument provided */
fprintf (stderr, "error: insufficient arguments provided.\n"
"usage: %s number\n", argv[0]);
return 1;
}
errno = 0; /* zero errno before call */
l = strtol (argv[1], &endptr, 0); /* attempt converstion to long */
if (endptr == argv[1]) { /* check if digits were converted */
fprintf (stderr, "error: no digits converted in '%s'.\n", endptr);
return 1;
}
else if (errno) { /* check for error in conversion */
perror ("strtol-argv[1]");
return 1;
}
printf ("number provided: %ld\n", l); /* output number */
if (*endptr) /* endptr not pointing to `'[=10=]'`, chars remain */
printf ("\nadditional characters following number: '%s'.\n", endptr);
return 0;
}
例子Use/Output
$ ./bin/strtolarg 123456
number provided: 123456
$ ./bin/strtolarg -123456
number provided: -123456
$ ./bin/strtolarg "val=123456"
error: no digits converted in 'val=123456'.
$ ./bin/strtolarg "123456=val"
number provided: 123456
additional characters following number: '=val'.
检查一下,如果您有任何问题,请告诉我。