紫清祈 2022-12-25 22:54 采纳率: 100%
浏览 43
已结题

关于用动态链表实现对学生数据的的删除与输出的提问

在设计动态链表用于存放学生的姓名,学号和三门课程的成绩,要求设计del函数实现对前六个学生中成绩平均分最高与最低的学生数据删除。
在设计过程中遇到了下列问题
1.动态链表的输出多了一段地址
2.结构体指针在使用时发生了冲突。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
#define len sizeof(struct date)
int n;//节点数量
struct date//建立结构体
{   
    char name;//姓名
    int id;//学号
    int score1;//成绩1
    int score2;//成绩2
    int score3;//成绩3
    struct date *next;//指向下一个结构体的指针
};
struct date* creat(void)//创建动态链表并返回头指针
{
    struct date* head, * p1, * end;
    n = 0;
    p1 = end = (struct date*)malloc(len);
    printf("请输入学生的姓名,学号,以及三门课程的成绩:\n");
    scanf("%c,%d %d %d %d", &p1->name,&p1->id, &p1->score1, &p1->score2, &p1->score3);
    head = NULL;
    while (p1->name!=32)
    {
        n = n + 1;
        if (n == 1)
            head = p1;
        else
            end->next= p1;
        end = p1;
        p1 = (struct date*)malloc(len);
        scanf("%c,%d %d %d %d", &p1->name, &p1->id, &p1->score1, &p1->score2, &p1->score3);
    }
    end->next = NULL;//尾指针
    return(head);
}
struct date* creat(void);
void del(struct date* pt);
int main()
{
    int i;
    struct date* pt,;
    pt = creat();//让pt成为头指针
    printf("若不执行任何操作请输0\n");
    printf("若要新增数据请输1;\n");
    printf("若要删除前面6个学生中平均分最高和最低的学生的数据请输2\n");
    scanf("%d", &i);
    switch (i)
    {
    case 0:break;
    //case 1:insert(pt, n); break;
    case 2:del(pt); break;
    }
    do{   
        printf("%c,%d %d %d %d\n",(pt->name),(pt->id),(pt->score1),(pt->score2),(pt->score3));//输出链表
        pt=pt->next;
    } while (pt ->next!= NULL);
    return 0;
}
void del(struct date* pt)//找出前6组数据中的最高,最低平均分并删去
{
    struct date* h1 = pt,*h2=pt,*in=pt,*h3=pt;
    int averge[6] = { 0 }, x = 0, i = 0, z = 0;
    int y, o=0, p;
    float min,max;
    min = (float)(averge[0]);
    max = (float)(averge[0]);
    for (y= 0; y < 6; y++)
    {
        averge[y] = (float)((h2->score1 + h2->score2 + h2->score3) / 3);//用一个数组记录每个人的平均分
        h2 = h2->next;
    }
    free(h2);
    for (y = 0; y < 6; y++)
    {
        if ((float)averge[y] < min)
        {
            min = (float)averge[y];
            o= y;//记下最小值的坐标
        }
        if ((float)averge[y] > max)
        {
            max = (float)averge[y];
            p = y;
        }
    }
    while (i < o && h1 != NULL)
    {
        in = h1;
        h1 = h1->next;//使指针移动到要找到的坐标
        i++;
    }
    if (h1 != NULL)
    {
        in->next = h1->next;//更改最小值坐标的前一个结构体的指针使其跳过该坐标
        free(h1);
    }
    while (z < p && h3 != NULL)
    {
        in = h3;
        h3= h3->next;
        i++;
    }
    if (h3 != NULL)
    {
        in->next = h3->next;
        free(h3);
    }
}

运行结果及详细报错内容

img

img

思路:对于del函数,先用数组储存每个同学的平均分,然后再找出最高分与最低分的地址。对其前一个结构体的指针进行修改。

我想要达到的结果,如果你需要快速回答,请尝试 “付费悬赏”
  • 写回答

2条回答 默认 最新

  • 冷0_O 2022-12-27 11:06
    关注

    动态链表之所以会多出一段地址。是因为你的scanf里面有输入字符类型的变量,你每次输入一组数据是不是还要按一下回车。比如你输入a 1 2 3 4,此时输入缓冲区包含了a 1 2 3 4其实还有一个回车字符。程序在创建a 1 2 3 4这一个节点后再一次来到scanf函数,此时scanf发现缓冲区还有一个回车字符就不会让用户进行输入操作,而是会将回车也当作一个字符赋值给节点的name变量中,这就导致你输入一次数据程序实际上创建了两个节点。而回车这个字符是没有形状的,这也就是为什么你多出来的数据第一个字符显示空,后面四个int都是随机值。解决方法就是在scanf后面加一个getchar函数将回车字符回收掉。
    代码仅供参考

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct stu {
        char name;
        int id;
        int scoreOne;
        int scoreTwo;
        int scoreThree;
        struct stu* next;
    } STUDATE;
    
    STUDATE* CreateDate(void);
    STUDATE* DeleteMaxOrMin(STUDATE* headPtr_);
    STUDATE* DeleteNode(STUDATE* headPtr_, STUDATE* nodePtr_);
    void PrintList(STUDATE* headPtr_);
    
    int main(void) {
        STUDATE* headStr = CreateDate();
        headStr = DeleteMaxOrMin(headStr);
        PrintList(headStr);
        return 0;
    }
    
    STUDATE* CreateDate(void) {
        STUDATE* headPtr = NULL;
        STUDATE* tempPtr = NULL;
        STUDATE* endPtr = NULL;
        while (1) {
            tempPtr = (STUDATE*)malloc(sizeof(STUDATE));
            tempPtr->next = NULL;
            scanf("%c%d%d%d%d", &(tempPtr->name), &(tempPtr->id), &(tempPtr->scoreOne), &(tempPtr->scoreTwo), &(tempPtr->scoreThree));
            getchar();
            if (tempPtr->name == '#')
                break;
            if (headPtr == NULL) {
                headPtr = tempPtr;
                endPtr = tempPtr;
            } else {
                endPtr->next = tempPtr;
                tempPtr->next = NULL;
                endPtr = tempPtr;
            }
        }
        return headPtr;
    }
    
    STUDATE* DeleteMaxOrMin(STUDATE* headPtr_) {
        STUDATE* maxPtr = headPtr_;
        STUDATE* minPtr = headPtr_;
        int avergeMin = 0;
        int avergeMax = 0;
        int currentAverge = 0;
        STUDATE* ptr = headPtr_->next;
        while (ptr) {  // ptr != NULL
            avergeMax =
                (maxPtr->scoreOne + maxPtr->scoreTwo + maxPtr->scoreThree) / 3;
            avergeMin =
                (minPtr->scoreOne + minPtr->scoreTwo + minPtr->scoreThree) / 3;
            currentAverge = (ptr->scoreOne + ptr->scoreTwo + ptr->scoreThree) / 3;
            if (currentAverge < avergeMin)
                minPtr = ptr;
            if (currentAverge > avergeMax)
                maxPtr = ptr;
            ptr = ptr->next;
        }
        // delete
        if (maxPtr == minPtr)  // 代表所有学生平均成绩都相等 不做删除操作
            return headPtr_;
        headPtr_ = DeleteNode(headPtr_, maxPtr);
        headPtr_ = DeleteNode(headPtr_, minPtr);
        return headPtr_;
    }
    
    STUDATE* DeleteNode(STUDATE* headPtr_, STUDATE* nodePtr_) {
        STUDATE* deletePrev = headPtr_;
        if (nodePtr_ == headPtr_) {
            headPtr_ = headPtr_->next;
            nodePtr_->next = NULL;
            free(nodePtr_);
            return headPtr_;
        }
        while (deletePrev->next != nodePtr_)  // 指向删除节点的前一个节点
            deletePrev = deletePrev->next;
    
        if (nodePtr_->next = NULL) {  // 要删除的在最后
            deletePrev->next = NULL;
            free(nodePtr_);
        } else {  // 在中间
            deletePrev->next = nodePtr_->next;
            nodePtr_->next = NULL;
            free(nodePtr_);
        }
        return headPtr_;
    }
    
    void PrintList(STUDATE* headPtr_) {
        STUDATE* str = headPtr_;
        while (str) {
            printf("%c %d %d %d %d\n", str->name, str->id, str->scoreOne, str->scoreTwo, str->scoreThree);
            str = str->next;
        }
    }
    
    ```c
    
    
    

    ```

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月20日
  • 已采纳回答 3月12日
  • 修改了问题 12月25日
  • 创建了问题 12月25日

悬赏问题

  • ¥30 Hyper-v虚拟机相关问题,求解答。
  • ¥15 TSM320F2808PZA芯片 Bootloader
  • ¥45 谷歌浏览器出现开发者工具无法显示已创建的,但您可以调试已部署的代码。 状态代码 404, net::ERR HTTP RESPONSE CODE FAILURE
  • ¥15 chatgpt网页版侧边栏和模型切换点击没反应怎么办
  • ¥15 如何解决蓝牙通话音频突发失真问题
  • ¥15 安装opengauss数据库报错
  • ¥15 【急】在线问答CNC雕刻机的电子电路与编程
  • ¥60 在mc68335芯片上移植ucos ii 的成功工程文件
  • ¥15 笔记本外接显示器正常,但是笔记本屏幕黑屏
  • ¥15 Python pandas