鱼C论坛

 找回密码
 立即注册
查看: 821|回复: 4

[已解决]链表问题

[复制链接]
发表于 2021-1-21 10:48:00 | 显示全部楼层 |阅读模式

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

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

x
这是个创建链表和删除节点的程序,基本功能没问题,但是当我测试程序时,第一个节点就输入0时,我的删除节点函数void del(struct student *q,int num1)直接报错,里面的条件判断
if(q1->num==0) printf("空表无法执行!");起不了作用。

#include <stdio.h>
#include <malloc.h>


struct student
{
        int num;
        float score;
        struct student *next;//结构体变量成员指针,用于存放下一个节点的地址
};

int n;

int main(void)
{
        struct student *creat();
        void print(struct student *r);
        void del(struct student *q,int num1);

        int m;
        struct student *stu;

        stu=creat();//返回链表头节点
        printf("\nThere are %d record!\n\n",n);
        print(stu);//输出所有节点

        printf("请输入你想删除的学生的编号:");
        scanf("%d",&m);
        printf("\n\n");
        del(stu,m);

        printf("\n\n");
}

struct student *creat()
{
        struct student *p1,*p2,*head;
        n=0;
        head=NULL;
        p2=(struct student *)malloc(sizeof(struct student));
        while(1)
        {
                p1=(struct student *)malloc(sizeof(struct student));
                printf("Please enter this student number:");
                scanf("%d",&p1->num);
                printf("Please enter this student score:");
                scanf("%f",&p1->score);
                if(0==p1->num)
                {
                        break;
                }
                else
                {
                        n++;
                        if(1==n)
                        {
                                head=p1;
                                p2=p1;
                        }
                        else
                        {
                                p2->next=p1;
                                p2=p1;
                        }
                }                
}
        p2->next=NULL;

        return head;
}

void print(struct student *r)
{
        
        while(r)//当q运行至链尾,自动停止
        {
                printf("第 %d 位学生的成绩是 %.1f\n",r->num,r->score);
                r=r->next;
        }
        printf("\n");
}

void del(struct student *q,int num1)
{
        void print(struct student *r);

        struct student *q1,*q2;
        q1=q;
        if(q1->num==0)
        {
                printf("空表无法执行!");
        }
        else
        {
                if(num1==q1->num)
                {
                        q=q->next;
                }
                else
                {
                        while(1)
                        {
                                if(num1!=q1->num)
                                {
                                        q2=q1;
                                        q1=q1->next;
                                }
                                else if(num1==q1->num)
                                {
                                        q2->next=q1->next;
                                        q1->next=NULL;
                                        break;
                                }
                        }
                }
        }
        print(q);
}
最佳答案
2021-1-21 14:08:50
        始终把被调用的函数放在调用函数的前面就可以避免对函数的声明。就像下面这样,把 main() 放在最后。
#include <stdio.h>
#include <stdlib.h>

struct student
{
        int num;
        float score;
        struct student *next;//结构体变量成员指针,用于存放下一个节点的地址
};

int n;

void print(struct student *r)
{
        for(; r ; r = r -> next) printf("学号: %d , 成绩 : %.1f\n" , r -> num , r -> score) ;
        printf("\n")                                                                        ;
}

struct student *creat()
{
        struct student *p1,*p2,*head;
        n=0;
        head=NULL;
        p2=(struct student *)malloc(sizeof(struct student));
        while(1)
        {
                p1=(struct student *)malloc(sizeof(struct student));
                printf("Please enter this student number:");
                scanf("%d",&p1->num);
                printf("Please enter this student score:");
                scanf("%f",&p1->score);
                if(0==p1->num)
                {
                        break;
                }
                else
                {
                        n++;
                        if(1==n)
                        {
                                head=p1;
                                p2=p1;
                        }
                        else
                        {
                                p2->next=p1;
                                p2=p1;
                        }
                }                
}
        p2->next=NULL;

        return head;
}

struct student * del(struct student * q , int num1)
{
        struct student * h , * q1 , * q2                                                   ;
        if(q) {
                for(h = q1 = q2 = q ; q1 && q1 -> num != num1 ; q2 = q1 , q1 = q2 -> next) ;
                if(q1) {
                        if(q1 == q2) h = q1 -> next                                        ; // 将要被删除的是头节点
                        else q2 -> next = q1 -> next                                       ; // 将要被删除的是内部节点
                        free(q1)                                                           ; // 释放节点占用内存
                        print(h)                                                           ; // 只是在删除成功的时候才打印新的链表
                } else {
                        printf("抱歉,节点未找到。\n")                                     ;
                }
        } else {
                printf("抱歉,链表为空,无法操作。\n")                                     ;
        }
        return h                                                                           ; // 头节点有可能被删除,所以,必须返回新的头节点
}

int main(void)
{
        int m                                  ;
        struct student * stu = NULL            ;
        stu = creat()                          ; // 返回链表头节点
        printf("\nThere are %d record!\n\n",n) ;
        print(stu)                             ; // 输出所有节点
        printf("请输入你想删除的学生的编号:") ;
        scanf("%d" , & m)                      ;
        printf("\n\n")                         ;
        stu = del(stu , m)                     ;
        printf("\n\n")                         ;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-1-21 12:32:33 | 显示全部楼层
       你还是先把前面的求助帖结了吧。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-21 13:04:19 | 显示全部楼层
jackz007 发表于 2021-1-21 12:32
你还是先把前面的求助帖结了吧。

哈哈哈,好了,搞忘了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-21 14:08:50 | 显示全部楼层    本楼为最佳答案   
        始终把被调用的函数放在调用函数的前面就可以避免对函数的声明。就像下面这样,把 main() 放在最后。
#include <stdio.h>
#include <stdlib.h>

struct student
{
        int num;
        float score;
        struct student *next;//结构体变量成员指针,用于存放下一个节点的地址
};

int n;

void print(struct student *r)
{
        for(; r ; r = r -> next) printf("学号: %d , 成绩 : %.1f\n" , r -> num , r -> score) ;
        printf("\n")                                                                        ;
}

struct student *creat()
{
        struct student *p1,*p2,*head;
        n=0;
        head=NULL;
        p2=(struct student *)malloc(sizeof(struct student));
        while(1)
        {
                p1=(struct student *)malloc(sizeof(struct student));
                printf("Please enter this student number:");
                scanf("%d",&p1->num);
                printf("Please enter this student score:");
                scanf("%f",&p1->score);
                if(0==p1->num)
                {
                        break;
                }
                else
                {
                        n++;
                        if(1==n)
                        {
                                head=p1;
                                p2=p1;
                        }
                        else
                        {
                                p2->next=p1;
                                p2=p1;
                        }
                }                
}
        p2->next=NULL;

        return head;
}

struct student * del(struct student * q , int num1)
{
        struct student * h , * q1 , * q2                                                   ;
        if(q) {
                for(h = q1 = q2 = q ; q1 && q1 -> num != num1 ; q2 = q1 , q1 = q2 -> next) ;
                if(q1) {
                        if(q1 == q2) h = q1 -> next                                        ; // 将要被删除的是头节点
                        else q2 -> next = q1 -> next                                       ; // 将要被删除的是内部节点
                        free(q1)                                                           ; // 释放节点占用内存
                        print(h)                                                           ; // 只是在删除成功的时候才打印新的链表
                } else {
                        printf("抱歉,节点未找到。\n")                                     ;
                }
        } else {
                printf("抱歉,链表为空,无法操作。\n")                                     ;
        }
        return h                                                                           ; // 头节点有可能被删除,所以,必须返回新的头节点
}

int main(void)
{
        int m                                  ;
        struct student * stu = NULL            ;
        stu = creat()                          ; // 返回链表头节点
        printf("\nThere are %d record!\n\n",n) ;
        print(stu)                             ; // 输出所有节点
        printf("请输入你想删除的学生的编号:") ;
        scanf("%d" , & m)                      ;
        printf("\n\n")                         ;
        stu = del(stu , m)                     ;
        printf("\n\n")                         ;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-21 14:45:02 | 显示全部楼层
jackz007 发表于 2021-1-21 14:08
始终把被调用的函数放在调用函数的前面就可以避免对函数的声明。就像下面这样,把 main() 放在最后 ...

哦,明白了,这里q调用的是头节点,如果用户输入0,head是没有被改变的,依然是NULL,直接用头节点进行条件判断,排除空表。行,谢谢大佬
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-12 06:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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