通过地址,scanf,取消引用

时间:2017-03-06 07:33:08

标签: c pointers pass-by-reference scanf

我编写了一个采用以下概念的程序:

我创建了一个整数x传递给函数的地址和一个文件名,所述函数打开文件(如果可用),扫描第一行并设置pX指向的值等于扫描线。

只有它不起作用,我不知道自己做错了什么。据我所知,下面的代码通常是如何实现它的,但我不确定我是否没有正确地使用scanf()指针或什么。

void foo() {
    char input[20] = "test.txt";
    int x = 1;
    bar(input, &x);
}

void bar(char *fileName, int *pX) {
    FILE *fp = fopen(fileName, "r");
    char *buffer = malloc(15 * sizeof(int));
    fgets(buffer, 15, fp);
    scanf(buffer, "%d", *pX);
    free(buffer);
    fclose(fp);
}

3 个答案:

答案 0 :(得分:2)

更改行:

scanf(buffer, "%d", *pX);

到:

sscanf(buffer, "%d", pX);

您需要使用sscanf函数来完成您的工作。

scanfsscanf都将指针作为参数。 pX的类型为int *,因此指向int的指针应该适合您。您传递的内容*pX是此指针的内容,换句话说是int

另外,更改行:

char *buffer = malloc(15 * sizeof(int));

到:

char *buffer = malloc(15 * sizeof(char));

或简单地说:

char *buffer = malloc(15);

始终check the result of malloc

if (buffer == NULL){
    ...
}

答案 1 :(得分:1)

首先,C中没有pass-by-reference,函数参数都是按值传递的。通过传递指向数据的指针,我们模拟实现与引用传递相同的效果,但这并不意味着C具有任何传递参考概念。

那说,问题似乎是

 scanf(buffer, "%d", *pX);
                     ^^^^

其中

  • 当前语法无效并调用undefined behavior。可能你需要sscanf()

  • px已经是指向int的指针。传递px将是正确和足够的。

故事的道德:启用编译器警告并注意它们。他们是有原因的。启用适当的警告后,您应该看到类似

的内容
  

警告:格式%d需要int *类型的参数,但参数3的类型为int [-Wformat=]

最后,

  • 在使用文件指针之前,请务必检查fopen()的返回值是否成功。
  • 检查scanf()的返回值以确保扫描成功。
  • 检查fgets()的返回值以确保成功

...基本上,检查所有库调用的返回值,以确保它们按预期工作

答案 2 :(得分:1)

您错误地使用scanf():直接使用scanf解析标准输入或使用sscanf()解析fgets()读取的字符串。此外,pX已经是指向int的指针,sscanf()期望存储它转换的int值,直接传递它:sscanf(buffer, "%d", pX);

以下是修改后的版本:

int bar(const char *fileName, int *pX) {
    char buffer[15];
    FILE *fp = fopen(fileName, "r");
    int success = 0;

    if (fp != NULL) {
        fgets(buffer, sizeof buffer, fp);
        if (sscanf(buffer, "%d", pX) == 1)
            success = 1;
        fclose(fp);
    }
    return success;
}

void foo(void) {
    int x = 1;
    bar("test.txt", &x);
    /* do something with x */
}

注意:

  • 分配buf是不必要的,只需将其设置为具有自动存储功能的本地阵列即可。
  • char *buffer = malloc(15 * sizeof(int));不正确:您为15 int而不是15个字符分配空间,根据定义,这些字符的大小为1。使用目标类型的大小以避免任何不一致:

    char *buffer = malloc(15 * sizeof(*buffer));
    
  • 始终检查malloc()的返回值,以避免潜在的未定义行为。

  • fp读取而不检查fopen是否成功可能存在未定义的行为。
  • 未修改filename指向的数组内容,将其设为const char *
  • bar返回成功指标可能很有用。
  • 在编译时启用更多警告:gcc -Wall -Wextra -Werrorclang -Weverything -Werror可能已经发现scanf中的错误。