2016-04-11 7 views
-3

関数から返された文字配列をmainの変数に代入するのに問題があります。関数から返された配列をcの変数に代入する

char *read(char filename[]) { 
    int i = 0; 
    am = 0; 
    char line[80]; 
    char *record[100]; 
    FILE *infile; 
    infile = fopen(filename, "r"); 

    while (fgets(line, sizeof line, infile) != NULL) { 
     record[i] = strdup(line); 
     i++; 
     am++; 
    } 
    return record; 
} 
... 

int main() { 
    char input[100]; 
    char *record[100]; 
    char input2[100]; 
    char input3[100]; 
    while (1) { 
     scanf("%[^\n]%*c", &input); 
     strcpy(input2, strtok(input, " ")); 
     if (strcmp(input2, "print") == 0){ 
      print(record); 

     ... 

     else if (strcmp(input2, "read") == 0) { 
      strcpy(input3, strtok(NULL, " ")); 
      record = read(input3); //input3 is the file name 
     } 
    return 0; 
} 

"read"で与えられた文字配列を "print"に渡したいが、失敗している。間違った入力はありません。

編集:私は動的に割り当てを試みましたが、私はまだ私が望むものを得ていません。私はそれを間違ってやったのですか?

char* read(char filename[]) { 
    int i = 0; 
    am = 0; 
    char line[80]; 
    char *record = calloc(100, sizeof(char)); 
    if (record == NULL) return NULL; 
    FILE *infile; 
    infile = fopen(filename, "r"); 

    while (fgets(line, sizeof line, infile) != NULL) { 
     printf(line); 
     record[i] = strdup(line); 
     i++; 
     am++; 
    } 
    return record; 
} 
+0

"誤った入力がない"とはどういう意味ですか?地獄への道は善意で舗装されています。 –

+1

'record'はスタック変数です。関数がアドレスを返すと、それはもはや有効でなくなり、使用されるべきではありません。 –

+2

この関数は文字配列を返しません。 – immibis

答えて

0

問題は変数recordで、char * record[100];と宣言されています。

[100]を宣言すると、スタックにストレージが作成されます。スタックストレージは、それを含む関数が依然として有効である間のみ有効です。たとえば、recordread()から呼び出される別の関数に渡すことができます。

したがって、read()がレコードを返すと、配列の先頭へのポインタが返されます。しかし、read() - recordを含む関数 - はスコープに含まれていないため、配列自体はもはや有効ではありません。

recordのファイルスコープストレージ(ファイルスコープの変数)を作成することでこの問題を解決できます。または動的割り当て(たとえば、mallocまたはcalloc)を使用してヒープ上のrecordのストレージを作成することによって、またはrecordのストレージをread()からmain()に渡すことにより、

これを行う一般的に受け入れられる方法は、動的割り当てを使用してヒープストレージを作成し、それを返すことです。それを行うと、の所有意味の領域に入っていることに注意してください。誰がそのストレージを所有しているのか、誰が割り当てたストレージを解放するのかを決定する必要があります。

また、strdup()自体がダイナミックメモリ割り当てを使用してバッファのコピーを作成することにも注意してください。たとえそれがわからなくても、あなたはすでにこれをやっています。 :-)

+0

私のコードを編集しましたが、それでもやはり間違っています - また、私が正しくread()を書くことができれば、私の主な機能は正しいでしょうか? – Ytg

+0

これで 'record 'のタイプが間違っています。あなたは[100]を削除して同じふりをすることはできません。それを 'char ** record'(2つの星に注意してください)に変更し、' calloc(100、sizeof(char *)) '(char *に注意)で初期化してください。その時点で、char *オブジェクトのブロックがあり、 'strdup'から戻ってくるポインタを保持することができます。 –

+0

あなたのメインには中括弧がありません。しかし、あなたは沢山のものを逃してしまったので、そうではないかもしれません。私の推薦は、単に既知のファイル名に 'read'を呼び出す単純な' main'を書き、その結果を出力することです。 'read'が動作していることを知るまでそれを使用し、次のコマンドに進みます。 –

関連する問題