ANSI C 链接列表.Add() 函数的行为很有趣

  • 本文关键字:函数 链接 列表 Add ANSI c
  • 更新时间 :
  • 英文 :


代码:

#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 : %sn", _identifier, _expression); fflush(NULL);
}
void show(node* database, int size) {
    if (database == NULL) {
        printf("Database emptyn");
    }
    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;
}

"Add"函数在手动调用时效果很好,但它在循环中不起作用,从标准输入读取数据。下面是一次运行的结果:

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"。我已经花了一天时间,但我无法弄清楚。任何人?

你的问题是它们都指向同一个指针:identifier .(也是expression)。(而前 3 个添加指向静态初始化的单独const char*

要解决此问题,您需要为您添加的每个新元素动态分配空间(例如,使用 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 : %sn", _identifier, _expression); fflush(NULL);
}

必须确保在某个时候相应地释放这些资源,否则将出现内存泄漏。

嗯...因为您存储的是指针而不是字符串的副本?

您每次都在 main 中存储"标识符"和"表达式"的地址,因此链表上的所有 3 个项目都指向相同的数据。

最新更新