2016-07-12 12 views
-2

私は比較的C言語で新しく、リンクリストを含むプログラムを作成していました。ここに、私に問題を引き起こすコードの非常に簡略化されたバージョンがあります。C:リンクリストの変数が初期化されていません

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

#define STRLEN 100 

struct Gene { 
    int num[4]; 
    struct Gene *next; 
    }; 
typedef struct Gene item; 

void build_list(item *current, item *head, FILE *in); 

int main() { 

    FILE *input; 
    FILE *output; 
    input = fopen("test.data", "r"); 
    output = fopen("test.out", "w+"); 

    item *curr; 
    item *head; 
    head = NULL; 
    int i; 

    build_list(curr, head, input); 
    curr = head; 

    while(curr) { 
     for (i = 0; i < 4; ++i) 
      fprintf(output, "%d\n", curr->num[i]); 
     curr = curr->next; 
     } 

    fclose(input); 
    fclose(output); 
    free(curr); 
} 

void build_list(item *current, item *head, FILE *in) { 

    char gene[STRLEN]; 
    char *tok; 
    char gene_name[STRLEN]; 
    char *search = ","; 
    int j; 

    while (fgets(gene, sizeof(gene), in)) { 

     current = (item *)malloc(sizeof(item)); 
     tok = strtok(gene, search); 
     strcpy(gene_name, tok); 
     for (j = 0; j < 4; ++j) { 
      tok = strtok(NULL, search); 
      current->num[j] = atoi(tok); 
      } 
     current->next = head; 
     head = current; 
    } 
} 

私はこれをコンパイルしようとすると、それは言う変数currが初期化されていないが、私はmallocで初期化した場合でも、それがセグメンテーションフォールトをスローし、あるいはそれがすべてでは何も出力しません。なぜこれができますか?

+0

'build_list(curr、head、input)'が初期化されていない値を最初のパラメータとして渡すことに気付いていますか? – immibis

+0

'curr'と' head'は値によって渡されます.... –

+0

はい、どうすればこの問題を回避できますか? – matnnar

答えて

0

@Sourav Ghoshは既にあなたのコードに何が間違っているのかを説明しており、それを解決する方法も示唆しています。ここに別の方法があります。

currentheadを関数の内部で(つまりポインタへのポインタとして)変更する変数として渡す代わりに、関数の戻り値を使用することをお勧めします。このようにして、ポインタからポインタへのポインタを使用する必要はありません。

item* add_item(item* head) 
{ 
    // Place a new item in front 
    item* current = malloc(sizeof(item)); 
    current->next = head; 
    return current; 
} 

item* build_list(item* head, FILE *in) { 

    char gene[STRLEN]; 
    char *tok; 
    char gene_name[STRLEN]; 
    char *search = ","; 
    int j; 

    while (fgets(gene, sizeof(gene), in)) 
    { 
     // Get a new item 
     head = add_item(head); 

     // Fill data into the new item 
     tok = strtok(gene, search); 
     strcpy(gene_name, tok); 
     for (j = 0; j < 4; ++j) 
     { 
      tok = strtok(NULL, search); 
      head->num[j] = atoi(tok); 
     } 
    } 

    return head; 
} 

mainから好きそれを呼び出す:

head = NULL; 
head = build_list(head, input); 

注:よう

何か読みやすさのために、私はmallocの失敗のためにすべてのチェックをスキップ。実際のコードでは、常にmallocがNULLを返したかどうかを確認する必要があります。

2

Cは、引数引き渡しに値渡しを使用します。したがって、build_list(curr, head, input);に電話すると、currhead自体が値渡され、これらの変数(対応するパラメータ)に対する変更は呼び出し元に反映されません。

ので、呼び出し側では、

while(curr) 

undefined behaviorを呼び出して初期化されない変数(meeory)にアクセスしています。

currheadを自分で変更する必要がある場合は、そのアドレスを渡して機能内で変更する必要があります。

build_list(&curr, &head, input); 

void build_list(item **current, item **head, FILE *in) 

*current = malloc(sizeof(item)); 

のようなものはあなたのために仕事を得ることができます。

+0

あなたがお勧めしたことは、 'メンバ参照の基本型' item(別名 'struct Gene *')が構造体または共用体ではないというエラーが発生し、初期化されていない変数についても警告します。何が悪かったのか? – matnnar

+0

@matnnar申し訳ありませんが、私は関数呼び出しの例で間違いを犯しました。今すぐ確認してください。 –

+0

ありがとうございますが、55行目と57行目に 'member reference base type'アイテム**(別名 'struct Gene **')が構造体または共用体ではありません 'というエラーが表示されています。それを修正する? – matnnar

関連する問題