2016-10-10 101 views
0

我无法将FILE指针作为参数传递给多个函数。C:传递文件作为参数

我想打开main中的文件,然后将它传递给一个函数,它将写入一些东西,然后从该函数传递给另一个函数。我可以将它从主函数传递到第一个函数没有问题,但是当我尝试将它传递给第二个函数时,它会出现分段错误。

我的代码看起来是这样的:

void firstFunction(FILE*); 
void secondFunction(FILE*); 

int main(void) { 
    FILE *fp; 
    if((fp = fopen("test.txt", "ab+")) == 0) { 
    return 1; 
    } 
    firstFunction(fp); 
    return 0; 
} 

void firstFunction(FILE *fp) { 
    fprintf(fp, "test"); /* Works */ 
    secondFunction(fp); /* Causes Segmentation fault */ 
} 

void secondFunction(FILE *fp) { 
    /* never reaches here */ 
    fprintf(fp, "test2"); 
} 

这很好解释了我在哪里与此有关。我试过传递各种不同的语法,如secondFunction(* fp),但没有成功。

怎么回事?从主要功能到第一功能而不是从第一功能到第二功能时它是如何工作的?

编辑:实际代码

#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 

#define LINESIZE 512 

void runCommand(const char[], FILE*); 
    void append(const char[], FILE*); 

int main(int argc, char * argv[]) { 
    char filename[LINESIZE]; 
    FILE *fp; 
    char line[LINESIZE]; 

    sscanf(argv[1], "%s", filename); 

    /* Open file for saving data */ 
    if((fp = fopen(filename, "ab+")) == 0) { 
     perror("fopen"); 
     return 1; 
    } else {  
     /* Reads lines from user */ 
     while(fgets(line, LINESIZE, stdin)){ 
      /* Omits empty lines */ 
      if(strlen(line) > 1) { 
       runCommand(line, fp); 
      } 
     } 
    } 

    return 0; 
} 

/* Parses first word in input and executes proper command */ 
void runCommand(const char input[], FILE *fp) { 
    char param1[LINESIZE]; 

    fprintf(fp, "test"); 
    append(input, fp); 

    int r = sscanf(input, "%s", param1); 

    if (!strcmp(param1, "append")){ 
     append(input, fp); 
    } else { 
     /* Error Handling */ 
    } 
} 

void append(const char input[], FILE *fp) { 
    char command[7]; 
    char fName[20]; 
    char lName[20]; 
    int score; 

    int r = sscanf(input, "%s%s%s%d", command, fName, lName, score); 

    if (r != 4) { 
     /* Error Handling */ 
    } 

    fprintf(fp, "%s%s%d", fName, lName, score); 
} 
+5

这是您的实际代码?它不会在第5行的'FILE * fp'和'#include '之后没有分号来编译。但随着这些改动,它在我的系统上编译和运行得很好。 –

+1

请提供可以重现seg故障的真实代码。上面的代码不会有这样的结果。 – kaylum

+0

http://stackoverflow.com/help/mcve –

回答

1
$ gcc -g -W -Wall -Wextra x.c -o x 
x.c: In function 'append': 
x.c:56:5: warning: format '%d' expects argument of type 'int *', but argument 6 has type 'int' [-Wformat=] 
    int r = sscanf(input, "%s%s%s%d", command, fName, lName, score); 
    ^
x.c:56:9: warning: 'score' is used uninitialized in this function [-Wuninitialized] 
    int r = sscanf(input, "%s%s%s%d", command, fName, lName, score); 
     ^
$ valgrind ./x test.txt 
==16814== Memcheck, a memory error detector 
==16814== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==16814== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 
==16814== Command: ./x test.txt 
==16814== 
a b c 123 
==16814== Use of uninitialised value of size 8 
==16814== at 0x4E9B2D9: _IO_vfscanf (in /lib64/libc-2.20.so) 
==16814== by 0x4EA9BAB: __isoc99_vsscanf (in /lib64/libc-2.20.so) 
==16814== by 0x4EA9B26: __isoc99_sscanf (in /lib64/libc-2.20.so) 
==16814== by 0x400A4A: append (x.c:56) 
==16814== by 0x400993: runCommand (x.c:39) 
==16814== by 0x4008F9: main (x.c:26) 

你及格分数管线56在调用sscanf的,但你应该通过它的地址。所以添加一个符号:

int r = sscanf(input, "%s%s%s%d", command, fName, lName, &score); 

之后,错误不见了,test.txt的内容是这样的:

testbc123testcd23cd23 

在C语言中,函数的参数总是传值调用。所以如果sscanf应该写入变量,传递变量不会有帮助。你实际上必须传递它的地址,所以sscanf可以写入它。其他三个变量(command,fName和lName)不需要&符号是因为在C中,您也不能传递数组。如果你尝试传递一个数组,事实上你正在传递一个指向它的第一个元素的指针。所以函数原型

void runCommand(const char[], FILE*); 
    void append(const char[], FILE*); 

实际上missleading,因为他们真正的意思是这样的:

void runCommand(const char *, FILE*); 
    void append(const char *, FILE*); 

,并在调用的sscanf,阵列“倒下”的指针(这样的sscanf实际上可以写入他们的内容)。

/编辑:轻微修改后的代码,包括在fprintf中陈述(和记下的电话是)一些新行,这是上面的输入输出:

runCommand: test 
append: bc123 
runCommand: test 
append: cd23 
append: cd23 
+0

未来可能会解决一个小错误,但此时并不能解决上述问题。 –

+0

是的,它的确如此。只需一秒钟,即可添加cat test.txt的输出 - 完成(嗯,以前的运行中仍然存在该文件中的内容...但您看到bc123 - 输出不是您所期望的,您遇到了另一个问题)。 –

+0

你真的在sscanf语句中尝试了我的更改吗? –