2016-10-10 18 views
0

FILEポインタをパラメータとして複数の関数に渡すときに問題があります。C:パラメータとしてファイルを渡す

私はメインでファイルを開き、そのファイルを関数に渡して、そこにいくつかのものを書き込んでから、その関数から別の関数に渡したいと思っています。メインから最初の関数に問題はありませんが、2番目の関数に渡すとSegmentationフォールトが発生します。私はこれででてるところ

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)などのさまざまな構文を渡してみましたが、成功しませんでした。

What's going wrong? mainからfirstFunctionへ行くときにはどのように動作しますが、firstからsecondFunctionには移動しませんか?

EDIT:実際のコード

#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) 

あなたがSSCANFするお電話でのライン56でスコアを渡しているが、あなたはそれがアドレスだ渡す必要があります。その後

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

、エラーがなくなっとtest.txtのは次のように読み取る:

testbc123testcd23cd23 

Cでは、関数の引数は、常に値で呼び出しているので、アンパサンドを追加します。したがって、sscanfが変数に書き込む必要がある場合、変数を渡すことは役に立ちません。実際にはアドレスを渡す必要があるので、sscanfはそのアドレスに書き込むことができます。他の3つの変数(command、fName、lName)にはアンパサンドが必要ないというのは、C言語でも配列を渡すことができないからです。配列を渡そうとすると、実際にはその配列へのポインタが渡されています。そうsscanf関数は、実際にすることができます(

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

とSSCANFためにあなたの呼び出しで、配列はポインタに「落ちる」:だから、関数のプロトタイプ

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

は実際にどのような彼らが本当に意味することはこれですので、missleadingされていますその内容に書き込む)。

/編集:fprintfの文の中で、いくつかの改行(およびコールだったノート)、これは上記の入力の出力で含めるように少し変更したコード:

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

将来的に軽微なエラーを解決する可能性がありますが、この時点で上記の問題は解決されません。 –

+0

はい、そうです。ちょっと待って、cat test.txtの出力を追加しようとしました - done(うーん、以前の実行からそのファイルにはまだコンテンツが残っていました...しかし、あなたはbc123を見ます - それはあなたが期待していたものではなく、 )。 –

+0

実際にsscanfステートメントで自分の変更を試しましたか? –

関連する問題