鱼C论坛

 找回密码
 立即注册
查看: 1132|回复: 9

[已解决]C语言链表删除问题求解!

[复制链接]
发表于 2019-9-22 13:04:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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的函数已经释放,下面这一步是不是有问题
最佳答案
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[20]                  ;
        struct student * pnext         ;
} stu                                  ;

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

int getnum(int * num)
{
        int m , ret                                                ;
        char s[260]                                                ;
        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[260] , * ret                                        ;
        name[0] = '\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[20]                                                            ;
        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)       ;
}
   
      这个代码花了比较大的力气在键盘输入检测方面,任何时候,如果从键盘获取的参数是空回车,则随时结束输入。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-9-22 14:46:25 | 显示全部楼层
free掉的是p中的内容。p本身还是存在的。p就是一个地址的代号。这个是不会删掉的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-22 15:39:58 From FishC Mobile | 显示全部楼层
本帖最后由 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 来把数据保存在新节点里面了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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));得出的结果是一样的。
还想请问一下,我发图片回复,您帮我看看

                               
登录/注册后可看大图


                               
登录/注册后可看大图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-22 17:18:59 From FishC Mobile | 显示全部楼层
seglex 发表于 2019-9-22 16:58
我试了加了p=(stu *)malloc(sizeof (stu));得出的结果是一样的。
还想请问一下,我发图片回复,您帮我 ...

      楼主,贴代码文本要比贴图片简单容易的多,找到文本输入区上方的快捷工具栏,按下标有 "<>" 的按钮,把代码文本贴到新弹出的代码框里就得了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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[20];
        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;
        
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-22 17:36:36 From FishC Mobile | 显示全部楼层
本帖最后由 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) ;
 }
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-22 17:46:44 | 显示全部楼层

这一段中我输入三个数,分别是11 22 22
得到的结果并不是我想象的那样,只删除第一个值,后面的值并没有删除

                               
登录/注册后可看大图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[20]                  ;
        struct student * pnext         ;
} stu                                  ;

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

int getnum(int * num)
{
        int m , ret                                                ;
        char s[260]                                                ;
        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[260] , * ret                                        ;
        name[0] = '\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[20]                                                            ;
        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)       ;
}
   
      这个代码花了比较大的力气在键盘输入检测方面,任何时候,如果从键盘获取的参数是空回车,则随时结束输入。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-25 09:51:11 | 显示全部楼层
jackz007 发表于 2019-9-22 23:30
这是我系统地为你修改的代码,新增加了几个函数,你测试一下,看看能否解决你的问题。

   

非常感谢,我会仔细阅读参考的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-4 11:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表