如何检查传递的参数是否是c中的字符串?

时间:2013-09-24 01:41:49

标签: c

我有以下代码:

void test(int N)
{
    printf("%d", N);

}
int main(int ac, char **av)
{
    test("");
    return 0;
}

我有一个函数测试需要一个整数参数,但是在我调用函数时,我给出了一个字符串参数,然后将它转换为一个整数并为我打印。但我想要的是,如果有人传递一个字符串而不是我给出错误。如何检查参数是否为字符串?

谢谢!

4 个答案:

答案 0 :(得分:1)

void test(int N) { /* ... */ }

...

test("");

该函数调用完全无效。 test需要int类型的参数,或者可以隐式转换为int的参数(任何算术类型都可以)。 ""是一个字符串文字;在此上下文中,它被转换为char*值,该值指向'\0'字符,该字符是数组的第一个(也是最后一个)字符。

没有从char*int的隐式转换。符合标准的编译器必须为无效调用发出诊断,可能(恕我直言)应该完全拒绝它。它与尝试获取字符串文字的平方根或将42添加到结构完全无效。

较早版本的C(在1989 ANSI标准之前)对这种事情更加宽松,而且松弛存在于一些现代编译器中。可能的情况是,如果您的编译器没有拒绝该调用,它将获取字符串文字的地址并将其转换为int。这种转变的结果在很大程度上毫无意义;这样的编译器实际上并没有通过允许它来帮助你。

如果你的编译器没有拒绝,或者至少警告过这个电话,你应该启用任何必要的选项来实现这一点。例如,对于gcc,您可以尝试类似:

gcc -std=c99 -pedantic -Wall -Wextra filename.c

如果您想使用特定于gcc的扩展程序,可以删除-pedantic-std=选项有几个可能的参数。有关更多信息,请参阅gcc文档 - 或者您正在使用的任何编译器的文档。

如果您要求验证用户输入(即来自运行程序的人的输入而不是编写C代码),则用户输入通常不是数字形式。它是 text 形式的字符序列。例如,您可以使用fgets()函数从标准输入中读取一行文本。然后,如果您愿意,可以检查该行是否具有整数文字的形式。一种方法是使用sscanf函数。一个简单的例子:

#include <stdio.h>
int main(void) {
    char line[200];
    int n;

    printf("Enter an integer: ");
    fflush(stdout);
    fgets(line, sizeof line, stdin);
    if (sscanf(line, "%d", &n) == 1) {
        printf("You entered %d (0x%x)\n", n, (unsigned)n);
    }
    else {
        printf("You did not enter an integer\n");
    }
}

但是如果你的问题是关于编写调用你提供的函数的C代码的人,编译器会检查任何参数都是有效的类型。

答案 1 :(得分:0)

天真的方法是这样的:

int is_integer( const char *s )
{
    if( *s == '-' || *s == '+' ) s++;
    while( isdigit(*s) ) s++;
    return *s == 0;
}

这将告诉您所有字符是否为数字,并带有可选符号。然而,它并不是特别强大。它不能处理空格,也不检查整数是否在有效范围内。

但是,它可能足以满足您的需求。

示例:

int main( int argc, char **argv )
{
    int val;

    if( argc <= 1 || !is_integer(argv[1]) ) {
        fprintf( stderr, "Syntax: %s val\n\nWhere val is an integer\n", argv[0] );
        return 1;
    }

    val = strtol( argv[1], NULL, 10 );
    test(val);

    return 0;
}

答案 2 :(得分:0)

  

我想要的是,如果有人传递字符串而不是我发出错误

这不是你的问题。我认为大多数编译器会对此发出警告 - 假设已启用警告。

问题是C总是按值传递,但字符串参数是一个数组,其值是数组中第一个字符的地址 - 指针,但指针值可以视为整数。同样,如果您正确使用它们,大多数编译器都足够聪明以捕捉这种模糊性。

对于不正确使用它的人,您无法完全防范您的代码。您编写了一个API,并将其记录下来,但是您不必为那些无法正确使用基本工具的人提供案例。

核心标准C库不包含您在此处查找的排序检查,因此将它们合并到您的API中似乎毫无意义 - 有大量内置标准命令,int args到哪个数组可以以相同的方式传递。拯救某人不会对你的库做一些愚蠢的行为不会使他们不能用基本的C lib做同样的事情 - 也就是说,你不能阻止他们传递指针代替整数。周期。

答案 3 :(得分:0)

-Wall-Werror进行汇编,您的问题将会神奇地消失。

gcc -Wall -Werror file.c