鱼C论坛

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

记录或删除学生成绩的<链表>,但是不知道哪里出错了

[复制链接]
发表于 2020-8-3 16:58:07 | 显示全部楼层 |阅读模式

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

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

x
/***********************************************************
************              动态记录学生成绩的链表                ************
************************************************************/

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

#define LEN sizeof(struct student)        //student 结构大小

struct student* creat();                        //创建链表(函数)

void print(struct student* head);        //打印链表(函数)

void del(struct student* head, int dnum);//删除链表函数

void ask(int i);

struct student
{
        int num;
        float score;
        struct student* next;
};

int n;                                                                //记录存放多少组数据

int main()
{
        int i,dnum;
        i = 0;
        struct student* stu;

        stu = creat();
        print(stu);

        printf("\n\n");

        while (1)
        {
                ask(i);
                scanf("%d", &i);

                if (i == 1)
                {
                        printf("\nPlease enter the number of the student:\n\tnum: ");
                        scanf_s("%d", &dnum);

                        del(stu, dnum);

                        print(stu);
                }
                else break;
        }
        system("pause");


}

struct student *creat()
{
        struct student* head;                                        //声明头部节点head
        struct student* p1, * p2;                                //声明p1 p2,两个节点

        p1 = p2 = (struct student*)malloc(LEN);        //LEN是student结构大小

        printf("Please enter the num:");
        scanf_s("%d", &p1->num);

        printf("Please enter the score:");
        scanf_s("%f", &p1->score);

        head = NULL;                                                //head归零(不指向任意东西)
        n = 0;

        while (/*0!=*/p1->num)                                //p1不为零则循环,当输入0时停止循环
        {
                n++;
                if (1 == n)
                {
                        head = p1;
                }
                else
                {
                        p2->next = p1;
                }
                p2 = p1;
                 
                p1 = (struct student*)malloc(LEN);

                printf("\nPlease enter the num :");
                scanf_s("%d", &p1->num);

                printf("Please enter the score:");
                scanf_s("%f", &p1->score);
        }

        p2->next = NULL;

        return head;
}

void print(struct student* head)                        /*输出链表内容*/
{
        struct student* p;

        printf("\n There are %d records!\n\n", n);

        p = head;
        if (/*NULL!+*/head)
        {
                do
                {
                        printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
                        p = p->next;
                } while (/*NULL!=*/p);
        }
}

void del(struct student *head,int dnum)                        //删除链表函数
{
        struct student * p1, * p2;
        int a = 0;
        if (head == NULL) { printf("This is a empty form"); }
        else
        {
                p1 = head;
                p2 = NULL;
                while (dnum != p1->num && p1!=NULL)
                {
                        p2 = p1;
                        p1 = p1->next;
                        a++;
                }
                if (p1!=NULL)
                {
                        if (p1 == head)
                        {
                                head = p1->next;
                        }
                        else
                        {
                                p2->next = p1->next;
                        }
                        printf("\nThe data of < %d > had been deleted!\n\n",dnum);
                        n = n - 1;
                }
                else if(p1==NULL)
                {
                        printf("\nNo student with  number %d was found.\n\n", dnum);
                }
        }
}

void ask(int i)
{
        printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-3 17:54:00 | 显示全部楼层
本帖最后由 SHRS23 于 2020-8-3 17:55 编辑
/***********************************************************
************              动态记录学生成绩的链表                ************
************************************************************/

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

#define LEN sizeof(struct student)        //student 结构大小

struct student *creat();                        //创建链表(函数)

void print(struct student *head);        //打印链表(函数)

void del(struct student *head, int dnum);//删除链表函数

void ask(int i);

struct student
{
    int num;
    float score;
    struct student *next;
};

int n;                                                                //记录存放多少组数据

int main()
{
    int i, dnum;
    i = 0;
    struct student *stu;
    stu = creat();
    print(stu);
    printf("\n\n");

    while(1)
    {
        ask(i);
        scanf("%d", &i);

        if(i == 1)
        {
            printf("\nPlease enter the number of the student:\n\tnum: ");
            scanf("%d", &dnum);
            del(stu, dnum);
            print(stu);
        }
        else
        {
            break;
        }
    }

    system("pause");
}

struct student *creat()
{
    struct student *head;                                        //声明头部节点head
    struct student *p1, * p2;                                //声明p1 p2,两个节点
    p1 = p2 = (struct student *)malloc(LEN);       //LEN是student结构大小
    printf("Please enter the num:");
    scanf("%d", &p1->num);
    printf("Please enter the score:");
    scanf("%f", &p1->score);
    head = NULL;                                                //head归零(不指向任意东西)
    n = 0;

    while(/*0!=*/p1->num)                                 //p1不为零则循环,当输入0时停止循环
    {
        n++;

        if(1 == n)
        {
            head = p1;
        }
        else
        {
            p2->next = p1;
        }

        p2 = p1;
        p1 = (struct student *)malloc(LEN);
        printf("\nPlease enter the num :");
        scanf("%d", &p1->num);
        printf("Please enter the score:");
        scanf("%f", &p1->score);
    }

    p2->next = NULL;
    return head;
}

void print(struct student *head)                        /*输出链表内容*/
{
    struct student *p;
    printf("\n There are %d records!\n\n", n);
    p = head;

    if(/*NULL!+*/head)
    {
        do
        {
            printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
            p = p->next;
        }
        while(/*NULL!=*/p);
    }
}

void del(struct student *head, int dnum)                       //删除链表函数
{
    struct student *p1, * p2;
    int a = 0;

    if(head == NULL)
    {
        printf("This is a empty form");
    }
    else
    {
        p1 = head;
        p2 = NULL;

        while(dnum != p1->num && p1 != NULL)
        {
            p2 = p1;
            p1 = p1->next;
            a++;
        }

        if(p1 != NULL)
        {
            if(p1 == head)
            {
                head = p1->next;
            }
            else
            {
                p2->next = p1->next;
            }

            printf("\nThe data of < %d > had been deleted!\n\n", dnum);
            n = n - 1;
        }
        else if(p1 == NULL)
        {
            printf("\nNo student with  number %d was found.\n\n", dnum);
        }
    }
}

void ask(int i)
{
    printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
}

做了个简单的小测试,程序本身问题不大
我想问一下你的调试运行环境是是什么
如果你用的visual studio并且你清楚你为什么要用scanf_s,那么修改方法就是把scanf_s缺少的参数补上;
如果你用的不是VS或者你不知道scanf_s是什么,那就像我上面的程序一样,把所有的scanf_s替换成scanf。


以下内容来自百度百科:

ANSI C中没有scanf_s(),只有scanf(),scanf()在读取时不检查边界,所以可能会造成内存访问越界,例如分配了5字节的空间但是读入了10字节
char buf[5]={'\0'};
scanf("%s", buf);
如果输入1234567890,后面的部分会被写到别的空间上去。
以上代码如果用scanf_s,第二行应改为scanf_s("%s",buf,5),表示最多读取5-1个字符,因为buf[4]要放'\0'
scanf_s最后一个参数是缓冲区的大小,表示最多读取n-1个字符.
vc++2005/2008中提供了scanf_s(),在最新的VS2015中也提供了scanf_s()。在调用时,必须提供一个数字以表明最多读取多少位字符。
3.读取单个字符也需要限定长度:scanf_s("%c,%c",&c1,1,&c2,1);而不能写成scanf_s("%c,%c",&c1, &c2,1, 1);否则编译器会报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-3 17:58:29 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-3 18:14:10 | 显示全部楼层
本帖最后由 baige 于 2020-8-3 18:45 编辑

删除那里需要用二级指针, 删除时对学号的判断以及链表是否为空有bug,当p1==NULL,p1->num是未知的,产生bug;
https://blog.csdn.net/qq_39032310/article/details/81746742
#include<stdio.h>
#include<stdlib.h>

#define LEN sizeof(struct student)//student 结构大小

struct student* creat();//创建链表(函数)
void print(struct student* head);//打印链表(函数)
void del(struct student** head, int dnum);//删除链表函数
void ask(int i);// 是否需要删除结点 

struct student
{
        int num;
        float score;
        struct student* next;
};

int n;//记录存放多少组数据

int main()
{
        int i = 0,dnum;
        struct student* stu;

        stu = creat();
        print(stu);

        printf("\n\n");

        while (1)
        {
                ask(i); 
                scanf("%d", &i);// 输入i 
                if (i == 1) // 当i==1需要删除结点 
                {
                        printf("\nPlease enter the number of the student:\n\tnum: ");
                        scanf("%d", &dnum); //  
                         
                        del(&stu, dnum); 
                        print(stu);
                }
                else break;
        }
        system("pause");
        return 0; 
}

struct student *creat()
{
        struct student* head;//声明头部节点head
        struct student* p1, * p2;//声明p1 p2,两个节点
        
        p1 = p2 = (struct student*)malloc(LEN);        //LEN是student结构大小
        printf("Please enter the num:");
        scanf("%d", &p1->num);
        head = NULL;
        p1->next = NULL; // 初始化p1指针域 
        printf("Please enter the score:");
        scanf("%f", &p1->score);
        n = 0;
    
        while (p1->num)                                //p1不为零则循环,当输入0时停止循环
        {
                n++;
                if (1 == n)
                {
                        head = p1;
                }
                else
                { 
                        p2->next = p1; 
                }
                p2 = p1;
                p1 = (struct student*)malloc(LEN);

                printf("\nPlease enter the num :");
                scanf("%d", &p1->num);
                printf("Please enter the score:");
                scanf("%f", &p1->score);
            }

        p2->next = NULL;

        return head;
}

void print(struct student* head)                        /*输出链表内容*/
{
        struct student* p = head;
        printf("\n There are %d records!\n\n", n);

        if(head) 
        {
                do
                {
                        printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
                        p = p->next;
                } while (p);
        }
}

void del(struct student **head,int dnum)                        //删除链表函数
{
        struct student *p1, *p2;
        int a = 0;
        if (*head == NULL)
        { 
                printf("This is a empty form"); 
        }
        else
        {
                p1 = *head; 
                p2 = NULL;
                while (dnum != p1->num) // 当p1->num == dumn或 p1 == NULL 退出循环 ,当p1==NULL时,p1->num位置,会导致程序发生未知错误
                {
                        p2 = p1;
                        p1 = p1->next;
                        a++;
                        if(p1==NULL)break;// 所以我把p1==NULL退出循环写到这里
                }
                if (p1!=NULL)
                {
                        if (p1 == *head)
                        {
                                *head = p1->next;
                        }
                        else
                        {
                                p2->next = p1->next;
                        }
                        printf("\nThe data of < %d > had been deleted!\n\n",dnum);
                        n = n - 1;
                }
                else
                {
                        printf("\nNo student with  number %d was found.\n\n", dnum);
                }
        }
}

void ask(int i)
{
        printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
} 

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

使用道具 举报

发表于 2020-8-3 18:49:25 | 显示全部楼层
本帖最后由 baige 于 2020-8-4 08:20 编辑


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-3 18:56:50 | 显示全部楼层
baige 发表于 2020-8-3 18:49
删除那里用2级指针,以及对于删除时判断p1->num和p1==NULL会产生bug,当p1==NULL,p1->num是未知的;

把scanf改回去就可以了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-3 19:15:54 | 显示全部楼层
本帖最后由 baige 于 2020-8-3 19:40 编辑

你的代码,已修改
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

#define LEN sizeof(struct student)        //student 结构大小

struct student* creat();                        //创建链表(函数)

void print(struct student* head);        //打印链表(函数)

void del(struct student** head, int dnum);//删除链表函数

void ask(int i);

 struct student
 {
         int num;
         float score;
         struct student* next;
 };

 int n;                                                                //记录存放多少组数据

int main()
 {
         int i,dnum;
         i = 0;
         struct student* stu;

         stu = creat();
         print(stu);

         printf("\n\n");

         while (1)
         {
                 ask(i);
                 scanf("%d", &i);

                 if (i == 1)
                 {
                         printf("\nPlease enter the number of the student:\n\tnum: ");
                         scanf("%d", &dnum);

                         del(&stu, dnum);

                         print(stu);
                 }
                 else break;
         }
         system("pause");


 }

 struct student *creat()
 {
         struct student* head;                                        //声明头部节点head
         struct student* p1, * p2;                                //声明p1 p2,两个节点

        p1 = p2 = (struct student*)malloc(LEN);        //LEN是student结构大小

        printf("Please enter the num:");
         scanf("%d", &p1->num);

         printf("Please enter the score:");
         scanf("%f", &p1->score);

         head = NULL;                                                //head归零(不指向任意东西)
        n = 0;

         while (/*0!=*/p1->num)                                //p1不为零则循环,当输入0时停止循环
        {
                 n++;
                 if (1 == n)
                 {
                         head = p1;
                 }
                 else
                 {
                         p2->next = p1;
                 }
                 p2 = p1;
                  
                 p1 = (struct student*)malloc(LEN);

                 printf("\nPlease enter the num :");
                 scanf("%d", &p1->num);

                 printf("Please enter the score:");
                 scanf("%f", &p1->score);
         }

         p2->next = NULL;

         return head;
 }

 void print(struct student* head)                        /*输出链表内容*/
 {
         struct student* p;

         printf("\n There are %d records!\n\n", n);

         p = head;
         if (/*NULL!+*/head)
         {
                 do
                 {
                         printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
                         p = p->next;
                 } while (/*NULL!=*/p);
         }
 }

 void del(struct student **head,int dnum)                        //删除链表函数
{
         struct student * p1, * p2;
         int a = 0;
         if (*head == NULL) { printf("This is a empty form"); }
         else
         {
                 p1 = *head;
                 p2 = NULL;
                 while (p1!=NULL&&dnum != p1->num)//短路
                 {
                         p2 = p1;
                         p1 = p1->next;
                         a++;
                 }
                 if (p1!=NULL)
                 {
                         if (p1 == *head)
                         {
                                 *head = p1->next;
                         }
                         else
                         {
                                 p2->next = p1->next;
                         }
                         printf("\nThe data of < %d > had been deleted!\n\n",dnum);
                         n = n - 1;
                 }
                 else if(p1==NULL)
                 {
                         printf("\nNo student with  number %d was found.\n\n", dnum);
                 }
         }
 }

 void ask(int i)
 {
         printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
 }
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-8-4 11:43:08 | 显示全部楼层
baige 发表于 2020-8-3 19:15
你的代码,已修改

感谢感谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-4 11:43:58 | 显示全部楼层
可以的话给个最佳,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-13 10:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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