C:链表并写入文件

Posted

技术标签:

【中文标题】C:链表并写入文件【英文标题】:C: Linked list and writing to a file 【发布时间】:2017-04-21 15:44:13 【问题描述】:

我在使用链表并将其内容写入文件时遇到了一些问题。 我写了一些与链表一起使用的函数(你可以在开头/结尾插入节点,在第 n 个位置删除节点或搜索 一个元素,然后删除它)。 所有这些功能都可以正常工作。如果我显示链表的内容,一切都很好,正如预期的那样。 但是当我尝试删除一个节点然后将链表的内容写入文件时出现问题,有很多垃圾值。 如果我在列表的开头/结尾插入一个节点,它会正确显示文件。该问题仅在删除节点时出现。 每次更新链表时,都会重写文件。下面是将内容写入文件的函数:

void writetofile(const STUDENT *head,FILE *fw)


    if(head == NULL)
    
        fprintf(stderr,"Ziadne zaznamy\n");
        return;
    
    while(head!=NULL)
    
        fprintf(fw,"%s %s %c %.2lf \n",head->meno,head->priezvisko,head->pohlavie,head->priemer);
        head = head->next;
    

   return;

这个函数显示一个文件的内容:

void showfile(FILE *f)

    int c;
    while((c=getc(f))!=EOF)
        putchar(c);
    printf("\n\n");

程序由一个使用 switch 语句的简单菜单驱动,如下所示:

do
   
    puts("\nYour choice:(q) to quit");
   printf("a:insert at the begining\tb:insert at the end\n");
   printf("c: delete from nth position\td:search for a name and delete\n");
   printf("e: display file\n");


   switch(choice = toupper(getchar()))
   

       case 'A':
           pridajstudentanazaciatok(&head,tempmeno,temppriezvisko,temppohlavie,tempznamky);
           rewind(subor);
           writetofile(head,subor);
           break;

       case 'B':
           pridajstudentanakoniec(&head,tempmeno,temppriezvisko,temppohlavie,tempznamky);
           rewind(subor);
           writetofile(head,subor);
           break;

        case 'C':
            vymazzpozicie(&head,poziciaStudenta);
            rewind(subor);
            writetofile(head,subor);
            break;

        case 'D':
            vymazstudenta(&head,temppriezvisko);
            rewind(subor);
            writetofile(head,subor);
            break;

        case 'E':
            rewind(subor);
            showfile(subor);
            break;

        default:
            break;
   
   while(choice!='Q');

正如我所说,更新链表时会重写文件。

这是从第 n 个位置删除节点的函数:

void vymazzpozicie(STUDENT **head,int pozicia)

    if(*head==NULL)
    
        fprintf(stderr,"Prazdny zoznam.\n");
        return;
    
    int i = 0;
    STUDENT *temp1 = *head;
    if(pozicia == 0)
    
        *head =  temp1->next;
        free(temp1);
        return;
    
     while(i != (pozicia-1))
    
         temp1 = temp1->next;
         i++;

    

    STUDENT * temp2 = temp1->next;
    temp1->next = temp2->next;
    free(temp2);
    return;

这个函数搜索一个节点并删除它:

void vymazstudenta(STUDENT **head,const char *priezvisko)


    STUDENT *traverse = *head;
    STUDENT *previous = NULL;
    if(*head == NULL || priezvisko==NULL)
    
        fprintf(stderr,"Nespravny vstup.\n");
        return;
    
    while( traverse != NULL )
    
        if( strcmp(traverse->priezvisko,priezvisko) == 0 )
        
            if( previous == NULL )
            
                *head = traverse->next;
            
            else
            
                previous->next = traverse->next;
            
            free( traverse );
            return;
        
        else
        
            previous = traverse;
            traverse = traverse->next;
        
    

    fprintf(stderr,"Student %s sa nenasiel.\n",priezvisko);

    return;


有人可以帮助我吗? 谢谢。

【问题讨论】:

“当我尝试删除节点时出现问题”-> 该代码似乎已从帖子中“删除”。发布您的插入/删除功能。 从描述看来问题出在删除节点的函数中(问题不包括在内)。您是否在被删除之前的节点(如果有)与被删除之后的节点(如果有)之间设置了链接? @Mtf22 你能添加代码吗?否则我们如何帮助您? 我在问题中添加了代码 vymazzpozicie 不检查索引是否越界(如果pozicia 大于或等于列表的长度)。您可能未定义的行为 【参考方案1】:

这个删除函数有一个主要错误:你假设你要找的位置存在

试试这个:

void vymazzpozicie(STUDENT **head,int pozicia)

    if(*head==NULL)
    
        fprintf(stderr,"Prazdny zoznam.\n");
        return;
    
    int i = 0;
    STUDENT *temp1 = *head;
    if(pozicia == 0)
    
        *head =  temp1->next;
        free(temp1);
        return;
    
     while(temp1 != NULL && i != (pozicia-1))
    
         temp1 = temp1->next;
         i++;

    

    if(temp1 == NULL || temp1->next == NULL)
      // print some error
      return;
    

    STUDENT * temp2 = temp1->next;
    temp1->next = temp2->next;
    free(temp2);
    return;


更新

我建议不要使用rewind() 函数,而是使用freopen(...) 重新打开文件,因为:如果您使用rewind() 删除一个元素,您只会覆盖第一个N-1 的文件内容元素,将第 N 个留在文件中。相反,您需要始终清除所有文件。

【讨论】:

您在尝试删除最后一个元素时遇到同样的错误。 @CristiFati 实际上它适用于最后一个元素。问题是如果没有 temp1 的继任者。无论如何,谢谢你的提示!

以上是关于C:链表并写入文件的主要内容,如果未能解决你的问题,请参考以下文章

C语言问题,求解释(关于动态链表和文件写入):

C语言如何将链表里的值写入文件

Lisp - 使用低内存占用写入文件

C语言怎么把文件的内容读到链表里面?

如何在c中的文件上写入文本?

pandas如何在现有的Excel表格上新建工作表并添加dataframe