1

コード:

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

typedef struct node {
    char* identifier;
    char* expression;
    struct node* next;
} node;

void add(node** database, char* _identifier, char* _expression, int * size) {
    node* tmp = (node*) malloc (sizeof(node));
    tmp->identifier = _identifier;
    tmp->expression = _expression;
    tmp->next = *database;
    *database = tmp;
    (*size)++;
    printf("Added: %s : %s\n", _identifier, _expression); fflush(NULL);
}

void show(node* database, int size) {
    if (database == NULL) {
        printf("Database empty\n");
    }
    else {
        node* tmp = database;
        printf("Identifier list (%d):\n", size); fflush(NULL);
        while (tmp != NULL) {
            printf("%s : \"%s\" \n", tmp->identifier, tmp->expression);fflush(NULL);
            tmp = tmp->next;
        }
    }
}

int main() {
    node* database = NULL;
    int size = 0;
    add(&database, "a1", "abc", &size);
    add(&database, "a2", "def", &size);
    add(&database, "a3", "ghi", &size);

    char identifier[20];
    char expression[1000];
    int i;
    for (i = 0; i<3; i++) {
        scanf("%s %s", identifier, expression);
        add(&database, identifier, expression, &size);
    }
    show(database, size);
    printf ("Bye!");
    return 0;
}

「追加」関数は、手動で呼び出すとうまく機能しますが、標準入力からデータを読み取るループ内では機能しません。以下は、1 回実行した結果です。

Added: a1 : abc
Added: a2 : def
Added: a3 : ghi
a4 mno
Added: a4 : mno
a5 ghi
Added: a5 : ghi
a6 kml
Added: a6 : kml
Identifier list (6):
a6 : "kml" 
a6 : "kml" 
a6 : "kml" 
a3 : "ghi" 
a2 : "def" 
a1 : "abc" 
Bye!

ご覧のとおり、ノード a1、a2、a3 がリストに正しく追加されました。ただし、リストに正しく追加された a4 と a5 は、a6 が追加された後、すべて「a6」に変更されました。すでに1日かかりましたが、理解できませんでした。誰か?

4

2 に答える 2

2

あなたの問題は、それらがすべて同じポインタを指していることです: identifier. (またexpression)。const char*(一方、最初の 3 つの add は、静的に初期化された別の s を指しています。)

これを解決するには、追加する新しい要素ごとに動的にスペースを割り当て (例: を使用)、それらを削除するときにmallocそれらを解放する必要があります (例: を使用)。free

例えば:

void add(node** database, char* _identifier, char* _expression, int * size) {
   node* tmp = (node*) malloc (sizeof(node));
   tmp->identifier = (char *)malloc(strlen(_identifier));
   strcpy(tmp->identifier, _identifier);
   tmp->expression = (char *)malloc(strlen(_expression));
   strcpy(tmp->expression, _expression);
   tmp->next = *database;
   *database = tmp;
   (*size)++;
   printf("Added: %s : %s\n", _identifier, _expression); fflush(NULL);
}

これらのリソースがある時点で対応して解放されていることを確認する必要があります。そうしないと、メモリ リークが発生します。

于 2012-04-16T17:32:13.577 に答える
2

うーん...文字列のコピーではなくポインタを保存しているためですか?

「識別子」と「式」のアドレスを毎回メインに保存しているため、リンクされたリストの3つのアイテムはすべて同じデータを指しています。

于 2012-04-16T17:34:56.313 に答える