2016-10-10 105 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語句中嘗試了我的更改嗎? –