【问题标题】:Why is my content of linked list disappear when it exit a function?为什么我的链表内容在退出函数时会消失?
【发布时间】:2022-01-13 01:31:41
【问题描述】:

我试图扫描文件并将数据添加到链接列表中,然后将操作打印到输出文件中。我成功将操作打印到输出文件,但是当我尝试访问它时,我的链接列表的内容是空的。

然后我检查创建和链接的每个节点的地址,发现没有问题,当它在函数内部时,链接列表工作正常,但在 main() 中没有。

输入.txt
3
1 编码标记编程
1 烹饪米妮烹饪
1 园艺一分钱植物学

此代码未完成,但包含我的问题:

#include<stdio.h>
#include<ctype.h>
#include<string.h>

struct book {
    char *title;
    char *author;
    char *subject;
};
struct library {
    struct book collection;
    int num_books;
    struct library *next;
};

void AddBook(FILE *IF, FILE *OF, struct library** thislib);//function prototype

int main(void){
    FILE *IF,*OF;
    int sel,numOp,i;
    struct library *Lib=NULL;//declare head pointer
    if(((IF=fopen("library.txt","a+"))==NULL)||((OF=fopen("output.txt","w"))==NULL)){//open input and output file
        printf("File cannot be open!");
    }
    else{   
        fscanf(IF," %d",&numOp);    //scan the number of operation from file
        for(i=0;i<numOp;i++){       //Loop according to number of operation
            if(feof(IF))            //if file pointer reach EOF break
                break;  
            fscanf(IF," %d",&sel);  //scan the type of operation
            switch(sel){
            case 1: 
                AddBook(IF,OF,&Lib);    //add the book if sel is 1
                break;
            case 2:
                
                break;
            }
            printf("%s ", Lib->collection.title);   // print the title of the book but it show nothing
        }
    }
    return 0;
}

void AddBook(FILE *IF, FILE *OF, struct library** thislib){
    char title[30],author[30],subject[20];          //declare variable to hold data
    struct library *temp=NULL;                      //create a new node
    struct library *ptr=*thislib;               //create a pointer that point to head of link list
    temp=(struct library*)malloc(sizeof(struct library));   //allocate memory for the new node
    fscanf(IF," %s %s %s" ,title,author,subject);
    temp->collection.title=title;       // put the data into link list
    temp->collection.author=author;
    temp->collection.subject=subject;
    temp->next=NULL;
    if((*thislib)==NULL){
        (*thislib)=temp;                // if there is no content in link list put temp into head
    }
    else{
        while (ptr->next!=NULL)
        {
            ptr=ptr->next;              //put node at the end of link list
        }
        ptr->next=temp;
    }
    fprintf(OF,"The book %s author %s subject %s has been added to the library.\n",title,author,subject);
    printf("%s ",(*thislib)->collection.title);  //this work fine but it keep updating, weren't it suppose to have the same value
}

【问题讨论】:

  • temp-&gt;collection.title=title; 将指向局部变量的指针放入列表节点。当函数返回时,这些指针变得无效。您需要制作字符串的动态副本,例如temp-&gt;collection.title=strdup(title)
  • 嘿,它的工作非常感谢你,strcpy() 也工作吗?
  • 在分配内存之前不能使用strcpy()strdup()malloc()strcpy() 的组合。

标签: c function linked-list scanf


【解决方案1】:
  1. 你忘了#include &lt;stdlib.h&gt;。您的代码非常未定义,因为您剪掉了malloc() 返回的高位。

  2. 您返回了指向堆栈数组的指针。

    temp->collection.title=title;       // put the data into link list
    temp->collection.author=author;
    temp->collection.subject=subject;

得骗那些。 strdup()是你的朋友:

    temp->collection.title=strdup(title);       // put the data into link list
    temp->collection.author=strdup(author);
    temp->collection.subject=strdup(subject);
  1. 此行在您的测试用例中失败:fscanf(IF," %d",&amp;numOp); 输入与模式不匹配;您使用未定义的numOp 进入循环。 (我通过更正输入文件轻松解决了这个问题。您应该始终检查 scanf 的返回。)

  2. 此 scanf 导致读取问题导致废话。

    fscanf(IF," %s %s %s" ,title,author,subject);

但您的输入中有四个以空格分隔的字段。

  1. 您的调试输出显示链接列表中的第一项,但您每次都追加到列表末尾,因此它不会更改。

“剪掉高位”的解释:

缺少#include &lt;stddef.h&gt; 的隐式声明将是int malloc(size_t),这是错误的。这在 32 位平台上有效,但在 64 位平台上无效。 int 向上转换为 void *,这不会产生正确的值。

假设malloc() 返回了0x104C000010。返回地址看起来像这样(字节顺序在这里无关紧要,原因我现在不打算讨论)

 0                                                                                                                            63
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|1|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

但是返回被解释为32位整数(大多数64平台有sizeof(int)=4),所以会被解释为

 0                                                            31
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|1|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

当转换为 struct library * 时,会导致

 0                                                                                                                            63
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这是0x4C000010。哎呀,指向其他地方。任何事情都可能发生,但很可能是崩溃。

【讨论】:

  • “你剪掉了 malloc() 返回的高位”。怎么样?
  • @MadPhysicist:隐式类型为int malloc(...);int 在现代平台上小于void *
  • 剪掉高位是什么意思?会造成什么影响?
  • @Joshua。这是一个很好的选择,特别是如果 OP 的 RAM > 4GiB。您可能想在答案中为 OP 拼写出来。
  • @Strugle: #include &lt;stdlib.h&gt; 并在启用警告的情况下进行编译。这给出了“隐式声明”的警告。
猜你喜欢
  • 2015-05-13
  • 2012-05-24
  • 2015-02-11
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2017-04-28
  • 2010-11-25
  • 1970-01-01
相关资源
最近更新 更多