用c语言显示的链表具有相同的值

用c语言显示的链表具有相同的值,c,structure,C,Structure,我有一个CSV文件,其中包含以“,”分隔的行 该文件如下所示: FIRST,00-92-93,1,0,1 SECOND,53-12-53,5,1,5 THIRD,12-33-51,5,0,51 struct Data{ char *dat; char *uname; bool war_dep; int edu_period; bool dorms; }; struct llist{ Data d; llist *next; }; vo

我有一个CSV文件,其中包含以“,”分隔的行

该文件如下所示:

FIRST,00-92-93,1,0,1
SECOND,53-12-53,5,1,5
THIRD,12-33-51,5,0,51
struct Data{
    char *dat;
    char *uname;
    bool war_dep;
    int edu_period;
    bool dorms;
};

struct llist{
    Data d;
    llist *next;
};
void inserti(llist **head, char *line){
    char *tok;
    llist *p=new llist;
    int i=0;

    tok = strtok(line, ",");
    while(tok!=NULL){
            switch(i){
            case 0:
                p->d.dat=strdup(tok);
                break;
            case 1:
                p->d.uname=strdup(tok);
                break;
            case 2:
                p->d.war_dep=atoi(tok);
                break;
            case 3:
                p->d.edu_period=atoi(tok);
                break;
            case 4:
                p->d.dorms=atoi(tok);
                break;
            }
            i++;
            tok=strtok(NULL, ",");
            }
    p->next=NULL;
    if(*head!=NULL)
        p->next=*head;
    *head=p;

    printf("Callback: %s\n", p->d.dat);
}
链表如下所示:

FIRST,00-92-93,1,0,1
SECOND,53-12-53,5,1,5
THIRD,12-33-51,5,0,51
struct Data{
    char *dat;
    char *uname;
    bool war_dep;
    int edu_period;
    bool dorms;
};

struct llist{
    Data d;
    llist *next;
};
void inserti(llist **head, char *line){
    char *tok;
    llist *p=new llist;
    int i=0;

    tok = strtok(line, ",");
    while(tok!=NULL){
            switch(i){
            case 0:
                p->d.dat=strdup(tok);
                break;
            case 1:
                p->d.uname=strdup(tok);
                break;
            case 2:
                p->d.war_dep=atoi(tok);
                break;
            case 3:
                p->d.edu_period=atoi(tok);
                break;
            case 4:
                p->d.dorms=atoi(tok);
                break;
            }
            i++;
            tok=strtok(NULL, ",");
            }
    p->next=NULL;
    if(*head!=NULL)
        p->next=*head;
    *head=p;

    printf("Callback: %s\n", p->d.dat);
}
我有一个函数,它对这个文件进行排序,将每一行分成块并 将它们添加到结构中

这是我的程序:

void showi(llist *u){
    while(u){
        printf("Name: %s\t Date: %s\n", u->d.dat, u->d.uname);
        u=u->next;
    }
}

void inserti(llist **head, char *line){
    char *tok;
    llist *p=new llist;
    int i=0;

    tok = strtok(line, ",");
    while(tok!=NULL){
            switch(i){
            case 0:
                p->d.dat=tok;
                break;
            case 1:
                p->d.uname=tok;
                break;
            case 2:
                p->d.war_dep=atoi(tok);
                break;
            case 3:
                p->d.edu_period=atoi(tok);
                break;
            case 4:
                p->d.dorms=atoi(tok);
                break;
            }
            i++;
            tok=strtok(NULL, ",");
            }
    p->next=NULL;
    if(*head!=NULL)
        p->next=*head;
    *head=p;

    printf("Callback: %s\n", p->d.dat);
}

int main()
{
    FILE *fp;
    char line[128], *tok;
    llist *head;

    head = NULL;
    int i=0;
    fp=fopen("data.txt", "r");

    while(fgets(line, sizeof(line), fp))
    {
        inserti(&head, line);
    }
    fclose(fp);

    showi(head);

    return 0;
}
当执行上述代码时,我从inserti得到回调(只是为了确保每一行都得到正确处理),但是当我试图显示我的列表时,我只得到最后一个值(在本例中,我得到3个第三个)。我不知道为什么会发生这种情况,可能是inserti中的这段代码有问题

p->next=NULL;
    if(*head!=NULL)
        p->next=*head;
    *head=p;

fgets
line
一起使用时,数据存储到
line
中<代码>行然后被传递到
inserti
,它使用
strtok
从行中定位所需的数据
tok
是指向
中的字符的指针,该字符随后存储在链表节点
p
中。当读取下一行时,
line
将更新,并且
p
中的所有指针现在都指向更新的行。您需要做的是为
p
的各个成员分配一个新字符串,或者在每次读取一行时为
分配一个新缓冲区。尝试使用
strdup(tok)
而不是直接将
p
的成员分配给
tok

p->d.dat = strdup(tok);
这对我有帮助! 通过改变
p->d.dat=tok,我做了一些小的调整至p->d.dat=strdup(tok)

inserti
现在看起来像这样:

FIRST,00-92-93,1,0,1
SECOND,53-12-53,5,1,5
THIRD,12-33-51,5,0,51
struct Data{
    char *dat;
    char *uname;
    bool war_dep;
    int edu_period;
    bool dorms;
};

struct llist{
    Data d;
    llist *next;
};
void inserti(llist **head, char *line){
    char *tok;
    llist *p=new llist;
    int i=0;

    tok = strtok(line, ",");
    while(tok!=NULL){
            switch(i){
            case 0:
                p->d.dat=strdup(tok);
                break;
            case 1:
                p->d.uname=strdup(tok);
                break;
            case 2:
                p->d.war_dep=atoi(tok);
                break;
            case 3:
                p->d.edu_period=atoi(tok);
                break;
            case 4:
                p->d.dorms=atoi(tok);
                break;
            }
            i++;
            tok=strtok(NULL, ",");
            }
    p->next=NULL;
    if(*head!=NULL)
        p->next=*head;
    *head=p;

    printf("Callback: %s\n", p->d.dat);
}

您正在将令牌指针存储在结构中,但当您读取下一行时,数据将被覆盖。这就是为什么最后一行的数据出现在所有记录中

您应该复制每个令牌,例如

p->d.dat = strdup(tok);

其他成员也一样。以后不要忘记
释放这些指针,因为
strdup
在内部使用
malloc

复制前两个字段时:

p->d.dat=tok;
...
p->d.uname=tok;
实际上,您正在将指针复制到
数组中的某个位置。这与main中的
行相同,每次都会被覆盖

您希望将这些字符串中的每一个都复制到结构中。您可以这样做,同时使用
strdup
为它们分配空间:

p->d.dat=strdup(tok);
...
p->d.uname=strdup(tok);

清理列表时,在对节点调用
free
之前,请确保在每个节点中
free
这些字段。

可能是因为存储的
strtok
中的指针在处理下一行时会覆盖其数据。使用
strdup
并存储指向令牌副本的指针<代码>p->d.dat=strdup(tok)此行:
llist*p=新的llist看起来不是C。现在忽略C标签,你实际使用什么语言。是的,'List*P=新LLIST是C++的,但是我希望它不会影响代码谢谢!!!!!p->d.dat=strdup(tok);这就是问题所在。另外,在C中,我认为您对
数据d的引用struct-llist
中的code>需要是
struct-Data-d。与所有对
llist
的引用相同。或者,您可以使用代码> TyPufF避免使用“代码>结构代码< /代码>对它们进行排序。再次,您使用的是<代码>新的< /COD> C++关键字。这不是用C编译的。请更改标记以删除
C
,然后添加
C++
。我知道了@Ryker我把它改为struct-llist*p=(llist*)malloc(sizeof(struct-llist));我的意思是,现在看起来你可以更新你的帖子来反映这种变化。