我的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;
答案 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
)指向currentline
且currentline
不存在while
循环块。您的程序访问lines
循环块之外的列表while
,这会导致未定义的行为。
对象的生命周期是程序执行的一部分,在此期间保证为其保留存储。一个对象存在,具有一个常量地址,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 ;
}