华丽棱青 发表于 2020-8-3 16:58:07

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

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

#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 withnumber %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:");
}

SHRS23 发表于 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 withnumber %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={'\0'};
scanf("%s", buf);
如果输入1234567890,后面的部分会被写到别的空间上去。
以上代码如果用scanf_s,第二行应改为scanf_s("%s",buf,5),表示最多读取5-1个字符,因为buf要放'\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);否则编译器会报错

SHRS23 发表于 2020-8-3 17:58:29

一个更详细的参考“:
https://blog.csdn.net/qq_43309823/article/details/95386759

baige 发表于 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 withnumber %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:");
}

baige 发表于 2020-8-3 18:49:25

本帖最后由 baige 于 2020-8-4 08:20 编辑


{:10_277:}

baige 发表于 2020-8-3 18:56:50

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

把scanf改回去就可以了

baige 发表于 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 withnumber %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:");
}

华丽棱青 发表于 2020-8-4 11:43:08

baige 发表于 2020-8-3 19:15
你的代码,已修改

感谢感谢。

baige 发表于 2020-8-4 11:43:58

可以的话给个最佳,谢谢
页: [1]
查看完整版本: 记录或删除学生成绩的<链表>,但是不知道哪里出错了