seglex 发表于 2019-9-22 13:04:05

C语言链表删除问题求解!

void shanchu(stu *p)
{
        int i;
        printf("请输入删除学生的学号\n");
        scanf("%d",&i);       
        stu * temp =p;
        p=p->pnext;

        while (p != NULL)
        {
                if(p->num==i)
                {
                        temp->pnext= p->pnext;
                        free(p);
                        p=temp->pnext;//上面的P已经被free掉了,再赋值是不是需要重新定义类型??
                }
                temp=temp->pnext;
                p=p->pnext;
        }
p已经被free相当于p的函数已经释放,下面这一步是不是有问题

wwhywhy 发表于 2019-9-22 14:46:25

free掉的是p中的内容。p本身还是存在的。p就是一个地址的代号。这个是不会删掉的。

jackz007 发表于 2019-9-22 15:39:58

本帖最后由 jackz007 于 2019-9-22 15:49 编辑

      p 只是一个指针,free(p) 所释放的只是 p 所指向的一片内存区域,这片区域,之前是用 p = (stu *)malloc(sizeof(stu)) 从系统中分配得到的。执行完 free(p) ,作为指针本身,p 仍然是存在和可以继续使用的一个 stu * 型的指针。
      p 被释放后,在被重新指向其它节点之前,不可以被继续作为一个 stu 型的节点来使用和访问。
      如果想创建一个新节点,可以使用 malloc() 先分配内存:
p = (stu *)malloc(sizeof(stu))
      然后,就可以通过指针 p 来把数据保存在新节点里面了。

seglex 发表于 2019-9-22 16:58:44

本帖最后由 seglex 于 2019-9-22 17:01 编辑

jackz007 发表于 2019-9-22 15:39
p 只是一个指针,free(p) 所释放的只是 p 所指向的一片内存区域,这片区域,之前是用 p = (stu *)m ...

我试了加了p=(stu *)malloc(sizeof (stu));得出的结果是一样的。
还想请问一下,我发图片回复,您帮我看看
https://raw.githubusercontent.com/alexnijd/test/master/tianruo_2019-9-22-637047677620765921.png
https://raw.githubusercontent.com/alexnijd/test/master/26.png

jackz007 发表于 2019-9-22 17:18:59

seglex 发表于 2019-9-22 16:58
我试了加了p=(stu *)malloc(sizeof (stu));得出的结果是一样的。
还想请问一下,我发图片回复,您帮我 ...

      楼主,贴代码文本要比贴图片简单容易的多,找到文本输入区上方的快捷工具栏,按下标有 "<>" 的按钮,把代码文本贴到新弹出的代码框里就得了。

seglex 发表于 2019-9-22 17:22:26

jackz007 发表于 2019-9-22 17:18
楼主,贴代码文本要比贴图片简单容易的多,找到文本输入区上方的快捷工具栏,按下标有 "" 的按钮, ...

好的,您看看
# include <stdio.h>
# include <stdlib.h>
typedef struct student
{
        int num;
        char name;
        struct student *pnext;
}stu;


//添加一个新节点
void addnode (stu *p)
{
        int n;
        printf("input\n");
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
        stu* pnew;
        pnew =(stu*)malloc(sizeof(stu));
        printf("请输入学员的信息\n");
        printf("姓名");
        scanf("%s",pnew->name);
        printf("学号");
        scanf("%d",&pnew->num);
        p->pnext = pnew;
        p=p->pnext;
        }
}
void print(stu *q)
{
        q=q->pnext;
        printf("\n==================\n");
        while(q!= NULL)
        {
                printf("%d\t%s\n",q->num,q->name);
                q=q->pnext;
        }

}
void shanchu(stu *p)
{
        int i;
        printf("请输入删除学生的学号\n");
        scanf("%d",&i);       
        stu * temp =p;//p(头地址)的值赋值给临时变量temp
        p=p->pnext;//首地址第一个有效数字地址赋值给p

        while (p != NULL)
        {
                if(p->num==i)
                {
                        temp->pnext= p->pnext;
                        free(p);//释放当前结构体下的p
                        p=(stu *)malloc(sizeof (stu));
                        p =temp->pnext;//指向下一个结构体的p
                        printf("指针的值:%d",p->num);

                }
                temp=temp->pnext;// 头地址自增
                p=p->pnext;//首地址自增 ,
        }
       

int main()
{
        stu *p;
        p =(stu *)malloc(sizeof(stu));
        p->pnext ;
        addnode(p);
        print(p);
        shanchu(p);
        print(p);
        return 0;
       
}

jackz007 发表于 2019-9-22 17:36:36

本帖最后由 jackz007 于 2019-9-22 17:58 编辑

stu * shanchu(stu *p)
{
      stu * q , temp       ;
      int i;
      q = NULL ;
      printf("请输入删除学生的学号\n");
      scanf("%d",&i);
      if (p -> num == i) {
                q = p ;
                p = p -> pnext ;
      } else {
                while (p -> pnext != NULL) {
                        if(p -> pnext -> num == i) {
                              q = p -> pnext ;
                              p -> pnext = p -> pnext -> pnext
                              break ;
                        }
                        p = p -> pnext ;
                }
      }
      if(q) {
                free(q) ;
      } else {
                printf("没有找到节点!\n")
      }
      return(p) ;
}

seglex 发表于 2019-9-22 17:46:44

jackz007 发表于 2019-9-22 17:36


这一段中我输入三个数,分别是11 22 22
得到的结果并不是我想象的那样,只删除第一个值,后面的值并没有删除
https://raw.githubusercontent.com/alexnijd/test/master/tianruo_2019-9-22-637047677620765921.png

jackz007 发表于 2019-9-22 23:30:08

本帖最后由 jackz007 于 2019-9-23 00:17 编辑

seglex 发表于 2019-9-22 17:46
这一段中我输入三个数,分别是11 22 22
得到的结果并不是我想象的那样,只删除第一个值,后面的值并没有 ...

      这是我系统地为你修改的代码,新增加了几个函数,你测试一下,看看能否解决你的问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student {
      int num                        ;
      char name                  ;
      struct student * pnext         ;
} stu                                  ;

int strip(char * s)
{
      int b , k , m                                                                               ;
      m = strlen(s)                                                                               ;
      while(m > 0 && (s == 0x07 || s == 0x0a || s == 0x0d || s == 0x20)) {
                s = 0x00                                                                     ;
                m --                                                                              ;
      }
      if(m > 0) {
                b = 0                                                                               ;
                while(b < m && (s == 0x07 || s == 0x0a || s == 0x0d || s == 0x20)) b ++ ;
                if(b > 0 && b < m) {
                        for(k = b ; k < m ; k ++) s = s                                 ;
                        s = 0x00                                                             ;
                        m -= b                                                                      ;
                }
      }
      return m                                                                                    ;
}

int getnum(int * num)
{
      int m , ret                                                ;
      char s                                                ;
      ret = 0                                                    ;
      * num = ret                                                ;
      for(;;) {
                printf("输入学号 : ")                              ;
                fgets(s , 256 , stdin)                           ;
                if(strip(s)) {
                        if(sscanf(s , "%d" , & m) == 1) {
                              ret = m                            ;
                              * num = ret                        ;
                              break                              ;
                        } else {
                              fprintf(stderr , "输入错误!\n\n") ;
                        }
                } else {
                        break                                    ;
                }
      }
      return ret                                                 ;
}

char * getname(char * name)
{
      char s , * ret                                        ;
      name = '\0'                                             ;
      ret = name                                                 ;
      printf("输入姓名 : ")                                    ;
      fgets(s , 256 , stdin)                                     ;
      if(strip(s)) strcpy(name , s)                              ;
      return ret                                                 ;
}

stu * findnode(int num , stu * p)
{
      stu * ret                      ;
      ret = NULL                     ;
      while(p) {
                if(p -> num == num) {
                        ret = p      ;
                        break          ;
                } else {
                        p = p -> pnext ;
                }
      }
      return ret                     ;
}

stu * addnode(stu * p)
{
      int num                                                                  ;
      stu * h , * q                                                            ;
      char name                                                            ;
      bool f                                                                   ;
      f = true                                                               ;
      h = p                                                                  ;
      printf("\n")                                                             ;
      printf("*** 录入学员信息 ***\n")                                       ;
      for(; f ;) {
                p = h                                                            ;
                printf("\n")                                                   ;
                if(getnum(& num)) {
                        if(! findnode(num , p)) {
                              if(strlen(getname(name))) {
                                        q = (stu *) malloc(sizeof(stu))          ;
                                        q -> num = num                           ;
                                        strcpy(q -> name , name)               ;
                                        q -> pnext = NULL                        ;
                                        if(p) {
                                                while(p -> pnext) p = p -> pnext ;
                                                p -> pnext = q                   ;
                                        } else {
                                                p = q                            ;
                                                h = p                            ;
                                        }                                       
                              } else {
                                        f = false                              ;
                              }
                        } else {
                              fprintf(stderr , "错误:节点已经存在!\n\n")   ;
                        }
                } else {
                        f = false                                                ;
                }
      }
      return h                                                               ;
}

stu * delnode(stu * p)
{
      int num                                                                                             ;
      stu * h , * q                                                                                       ;
      bool f                                                                                                ;
      f = true                                                                                              ;
      printf("\n")                                                                                          ;
      printf("*** 删除学员信息 ***\n")                                                                      ;
      h = p                                                                                                 ;
      if(p) {
                for(; f ;) {
                        if(h) {
                              p = h                                                                         ;
                              printf("\n")                                                                  ;
                              if(getnum(& num)) {
                                        if((q = findnode(num , p))) {
                                                while(p != q && p -> pnext && p -> pnext != q) p = p -> pnext ;
                                                if(p == q || p -> pnext == q) {
                                                      if(p == q) h = p -> pnext                           ;
                                                      else p -> pnext = q -> pnext                        ;
                                                      free(q)                                             ;
                                                }
                                        } else {
                                                fprintf(stderr , "错误:节点未找到!\n\n")                  ;
                                        }
                              } else {
                                        f = false                                                             ;
                              }
                        } else {
                              printf("\n")                                                                  ;
                              printf("链表节点已经全部删除!\n\n")                                          ;
                              f = false                                                                     ;
                        }
                }
      } else {
                fprintf(stderr , "错误:链表为空!\n\n")                                                      ;
      }
      return h                                                                                              ;
}                  

void print(stu * p)
{
      printf("\n")                                              ;
      printf("*** 显示学员信息 ***\n")                        ;
      if(p) {
                while(p) {
                        printf("%d\t%s\n" , p -> num , p -> name) ;
                        p = p -> pnext                            ;
                }
      } else {
                fprintf(stderr , "错误:链表为空!\n\n")          ;
      }
}

int main(void)
{
      stu * p      ;
      p = NULL       ;
      p = addnode(p) ;
      print(p)       ;
      p = delnode(p) ;
      print(p)       ;
}

   
      这个代码花了比较大的力气在键盘输入检测方面,任何时候,如果从键盘获取的参数是空回车,则随时结束输入。

seglex 发表于 2019-9-25 09:51:11

jackz007 发表于 2019-9-22 23:30
这是我系统地为你修改的代码,新增加了几个函数,你测试一下,看看能否解决你的问题。

   


非常感谢,我会仔细阅读参考的
页: [1]
查看完整版本: C语言链表删除问题求解!