如何在链表中动态插入字符串?

时间:2018-01-07 00:37:49

标签: c list data-structures

我的C程序应该读取一个输入文件并将其保存在一个链接列表中,然后打印它。但是当它在列表中插入下一行时,列表中的所有元素都成为新元素。

输入:

ABC
高清
ghi

输出:

GHI
GHI
GHI

我不确定,但我的猜测是它没有为列表中的新元素正确分配新内存。

这是代码:

s2

listd.h:

#include "listd.h"
#include <stdio.h>
void show(Value v) {
    printf(v);
    printf("\n");
}

int main( void ) {
    List lines = init();
    char a;
    while(a != EOF){
        a=getchar();
        char currentline[256] = " ";
        int i = 0;
        while(a != '\n' && a != EOF){
            currentline[i]=a;
            a = getchar();
            i++;
        }
        lines = insert(currentline, lines); //Here is probably the error
    }
    iterate(lines, show);
}

listd.h给了我们。但它是为int做的,所以我改变了

#include <stdlib.h>
#include <stdio.h>
#define DEFAULT 0

typedef enum {False ,True} Bool;
typedef char* Value;
typedef void (*VProc)(Value);
typedef struct _list {
    Value val;
    struct _list *next;
} Elem , *List;

List init() { return NULL; }
List insert(Value v, List l) {
    List e = malloc( sizeof (Elem));
    e->val = v;
    e->next = l;
    return e ;
}
void iterate(List l, VProc p) {
    for (;!empty(l);l=tail(l)) p(head(l));
    }

typedef int Value;

2 个答案:

答案 0 :(得分:0)

问题1:在struct _list中,val是一个char指针。 当你做malloc(sizeof(Elem))时,只分配两个指针(char *,struct_list *)的内存。

问题2:当执行e-&gt; val = v时,它会将char * v复制到e-&gt; val。它不复制字符串,只复制指针。这里v是当前行。因此很明显,所有元素的e-> val将是指向存储在当前行中的最后一个值的指针。在这种情况下,最后一个值是&#34; ghi&#34;。

请尝试以下代码并告知我们:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT 0

typedef enum {False ,True} Bool;
typedef char* Value;
typedef void (*VProc)(Value);
typedef struct _list {
    Value val;
    struct _list *next;
} Elem , *List;

List init() { return NULL; }
List insert(Value v, List l) {
    List e = malloc( sizeof (Elem));
    e->val = malloc(strlen(v) * sizeof(char));
    strcpy(e->val, v);
    e->next = l;
    return e ;
}

答案 1 :(得分:0)

当您访问其范围之外的本地变量的地址时,您的程序正在具有未定义的行为

currentline的范围在while循环中 - while(a != EOF),因为它已在循环块中声明。

insert(),你正在做:

e->val = v;

列表val的每个元素的 char *指针(类型lines)指向currentlinecurrentline不存在while循环块。您的程序访问lines循环块之外的列表while,这会导致未定义的行为。

来自C Standards:

  

对象的生命周期是程序执行的一部分,在此期间保证为其保留存储。一个对象存在,具有一个常量地址,33)并在其整个生命周期内保留其最后存储的值.34)如果一个对象在其生命周期之外被引用,则该行为是未定义的。当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定。

undefined behavior包括 - 程序可能会按预期工作,也可能会崩溃或发生任何事情。由于列表中所有元素的val指针指向同一个内存位置currentline,因此currentline的最后一个值是您在打印时获得的值指向列表val的所有元素的值指针lines。您很幸运,当您的程序访问其范围之外的对象内存时,您没有收到任何错误。但是每次运行程序时都可能不是这种情况。

要解决此问题,您应该将内存分配给val指针并将值currentline复制到其中。

你可以这样做:

List insert(Value v, List l) {
    List e = malloc(sizeof(Elem));
    if (NULL == e)
        exit(EXIT_FAILURE);

    e->val = malloc((strlen(v)+1) * sizeof(char));
    if (NULL == e->val)
        exit(EXIT_FAILURE);

    strcpy(e->val, v);
    e->next = l;
    return e ;
}