c语言链表无法删除头节点 *head是全局变量 删除头结点后输出显示乱码 删除中间节点和尾节点输出正常

只贴了问题代码 谢谢各路高手大神了!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct market
{
int num;
char name[30];
float inpri;
float outpri;
int inco;
int outco;
float outpriall;
int remindco;
float maoli;
struct market *next;
}*head;

int menu();
struct market *input();
struct market *dele(struct market *head);

int main()
{
printf("***********************************\n");
printf(" 欢迎进入超市管理系统\n");
printf("***********************************\n");
while(1)
{
switch(menu())
{
case 1:
input();break;
case 2:
change(head);break;
case 3:
dele(head);break;
case 4:
add(head);break;
case 5:
search();break;
case 6:
output();break;
case 7:
printf("退出系统!\n");
exit(0);
}
}
return 0;
}

int menu()
{
int cho;

printf("\n\n请选择数字进行操作\n");
printf("1.建立库存信息\n");
printf("2.修改商品信息\n");
printf("3.删除商品信息\n");
printf("4.添加商品信息\n");
printf("5.查询商品信息\n");
printf("6.输出销售情况\n");
printf("7.退出\n");
printf("请选择对应数字1--7\n");
while(1)
{
scanf("%d",&cho);
if(cho<1||cho>7)
{
printf("输入错误,请重新输入:");
}
else
break;

}
return cho;

}

struct market *input()//建立链表正常

struct *dele(struct market *head)
{
struct market *p3=head,*p4=NULL;
int n;

FILE *fp;

if((fp=fopen("goods message.txt","w"))==NULL)
{
printf("can not open the file");
exit(0);
}

printf("请输入要删除商品的编号\n");
scanf("%d",&n);
if(p3==NULL)
{
printf("列表为空!");

}
else
{
if(p3->num==n)
{
head->next=p3->next;
free(p3);
printf("删除成功!");

}
else
{
while(1)
{
p4=p3;
p4=p4->next;
if(p4->num==n)
{
p3->next=p4->next;
free(p4);
printf("删除成功!");
break;
}
if(p4==NULL)
{
printf("没有此商品!");
break;
}
}
}
}
fclose(fp);
return head;
}

你的代码:
struct *dele(struct market *head)  
{
    struct market *p3=head,*p4=NULL; 
    
    int n;

    FILE *fp;

    if(p3==NULL)     //链表的检查工作放在最开始 ,链表为空,后面的程序根本无法执行 
       return NULL;
       
     
    /*fp文件根本没在代码中使用,注释掉 
    if((fp=fopen("goods message.txt","w"))==NULL)//打开文件 
    {
        printf("can not open the file");
        exit(0);                 
    }
    */  
    
    printf("请输入要删除商品的编号\n");
    scanf("%d",&n);     

     //根据输入的商品编号来删除节点 
    if(p3->num==n)   //如果删除的是头结点 
    {
        head->next=p3->next;   //错误点:head是函数的参数,等同于局部变量,更改head的值,不会反应到全局head中 
        free(p3);              //C语言是安值传递的!!! 
        printf("删除成功!");   //既然head是全局变量,何必把head当参数传递呢?函数可以直接使用。 
                               //另一种方法:要修改head的值,需要使用head的指针,也就是指针的指针 
    }
    
    else
    {
        while(1)
        {
            p4=p3;
            p4=p4->next;
            if(p4->num==n)
            {
                p3->next=p4->next;
                free(p4);
                printf("删除成功!");
                break;
            }
            if(p4==NULL)
            {
                printf("没有此商品!");
                break;
            }
        }
    }        
    
    //fclose(fp);
    return head;
}



修改后的代码:

bool deleteNode(struct market **pphead)  
{
    struct market * p=*pphead,*front=NULL; 
    
    bool delOK = false;    //删除成功标志 
    
    int n;
    
    if(p==NULL)     //链表的检查工作放在最开始 ,链表为空,后面的程序根本无法执行 
       return false;

    
    printf("请输入要删除商品的编号\n");
    scanf("%d",&n); 
    
    
    while(p!=NULL)
    {
        if(p->num == n)
        {
            if(p==*pphead)   //要删除的是头结点 
            {
                *pphead = p->next;
                free(p);
                
            }
            else
            {
                front->next = p->next;
                free(p);
                
            }
            
            delOK =true;
            break;
        }
        
        
        front = p;     //front保存的是当前结点的前一个结点地址 
        p=p->next;
    }
    

   return delOK;   //返回删除状态值 
    
   
}



建议:为链表添加头结点,这样在删除节点的时候,就不用考虑删除的是不是头结点问题了。

追问

啊谢谢你问题解决了 想问一下添加头节点是怎么一个加法……一直没有搞明白……

追答

头结点位于链表的第一个结点,他和普通的数据节点是一样的。只是它不存储任何有效数据,头结点后面的结点才是真正存储你向存储的数据,比如你这里的商品信息。那么头结点是什么作用呢?
就好比你用胶带,如果每次扯下一段,第二次往往很难找到头了,那么,你可以在胶带的头前面贴个标记,这样就方便了。
也就是说:头结点不存储有效数据,所以只要链表存在,它永远不会被删除,被更改。那么,你只要记住头结点的地址,就不会丢失整个链表啦。

追问

谢谢你!头节点真的很好用TVT终于写完了工程实践,最后想问一个问题会加分!就是最后输出的时候有一个以某个数据大小排序,最初我直接交换数据最后还是按原来顺序输出了,难道还是因为是全局变量的原因?有什么办法可以直接交换内容吗?

贴不上交换代码,截一下图,麻烦啦

追答//排序,冒泡排序的思想 
void sortList(LinkedList list,int(*comp)(const DataType*pd1,const DataType*pd2)  )
{

Node*p = list->next;
DataType t;

for(Node*i = list->next;i!=NULL;i=i->next)
{
for(Node*k = i->next;k!=NULL;k=k->next)
{
if( 0 < comp(&(i->data),&(k->data) )  )
{
t = i->data;
i->data = k->data;
k->data = t;

}
}

}

}


//comp是链表使用者编写的函数,用来比较2个商品。
// 如果想按价格排序,就写p1->price,按编号num排序吗,就比较编号 
//将排序和比较分离,更加灵活 
int comp(const DataType*p1,const DataType *p2)
{
if(p1->price > p2->price)
  return 1;
    else if(p1->price == p2->price)
      return 0;

else return -1;

}


字数限制,不能贴全部代码了。注意:这个是带头结点的。

温馨提示:答案为网友推荐,仅供参考
相似回答