实验六歧路与纠错

一、歧路

实验六的程序不算太难,因此我一下午就写完了(好像也挺久),但执行起来却不符合我的预期。
总是存在这样的问题:
输入3个及以上数据时,直接输出的是正确数据,可排序后输出总会有至少一个结构体内的数据是乱的,不是我输入进去的数据。
花费一个下午,可以说有一半时间是因为这个原因。
而且,即使我把程序看了很久,思考了很久,还是没能想到是哪里错了。

二、纠错

在不断的错误后,我暂时放弃了。
时间来到晚上,我突然想起汪老师曾多次强调过debug的重要性。
于是我想到用debug进行调试。
可是,我不会用debug呀(这也是我一下午都没想到使用debug的原因)。
在请教大佬舍友张桓溪后,我大致学会了debug的使用方法。
debug不愧是debug,你大哥还是你大哥。
debug如同摧枯拉朽般指出了我的错误(夸张手法)。
在窗口中,我发现我输入进去的数据与我希望存放的位置竟然不同!
例如,第三组数据并未存放在[2]中,而是在[3]中,第四组数据更是跑到了[6]中去!
突然间,仿佛石破天惊,我想到我在函数中使用的都是指针pt。
在排序函数中,因为会涉及排序,我写的是*(pt+i)
在read_information和write_information中,为图方便,我写的是pt+=i;,循环内直接使用*pt
而这两者,是有区别的:
第一种方式,pt指针存放的地址不变。
第二种方式,pt指针不断变化,而且后面的变化在前面的基础之上!
正因为如此,[0] (0+0) > [1] (0+1) > [3] (1+2) > [6] (3+3),这正是我用debug得到的结果!
真相水落石出。
两个解决方法:
1.每次都重置pt,即

在循环开始pt+=i;
在循环结尾pt-=i;

2.pt每次偏移一个元素,即

在循环结尾pt++;

还有一个小插曲,就是解决问题后,有部分数据中平均数有误。
原来是在求平均数函数中,我使用的也是pt+=i

三、代码

使用的是解决方法2,因为更简洁美观,且更合理一些。

点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student
{
    long id;
    char name[10];
    int scoremt;
    int scoreen;
    int scoreph;
    int total;
    float ave;
} STUDENT;

void write_menu();
int read_information(STUDENT *pt);
void calculate_total_and_average(STUDENT *pt,int n);
void sort_by_score(STUDENT *pt,int n);
void sort_by_name(STUDENT *pt,int n);
void write_information(STUDENT *pt,int n);
void search_by_name(STUDENT *pt,int n);
void write_to_file(STUDENT *pt,int n);
void file_to_screen(STUDENT *pt,int n);

int main()
{
    int choice,student_number;
    STUDENT stu[40];
    STUDENT *ps=stu;
    write_menu();
    do
    {
        printf("Please enter your choice:");
        scanf("%d",&choice);
        switch(choice)
        {
        case 1:
        {
            student_number=read_information(ps);
            break;
        }
        case 2:
        {
            calculate_total_and_average(ps,student_number);
            break;
        }
        case 3:
        {
            sort_by_score(ps,student_number);
            write_information(ps,student_number);
            break;
        }
        case 4:
        {
            sort_by_name(ps,student_number);
            write_information(ps,student_number);
            break;
        }
        case 5:
        {
            sort_by_score(ps,student_number);
            search_by_name(ps,student_number);
            break;
        }
        case 6:
        {
            write_to_file(ps,student_number);
            break;
        }
        case 7:
        {
            file_to_screen(ps,student_number);
            write_information(ps,student_number);
            break;
        }
        case 9:
        {
            write_information(ps,student_number);
            break;
        }
        }
    }
    while(choice!=0);
    return 0;
}

void write_menu()
{
    printf("1.Append record\n");
    printf("2.Caculate total and average score of every student\n");
    printf("3.Sort in ascending order by total score of every student\n");
    printf("4.Sort in dictionary order by name\n");
    printf("5.Search by name\n");
    printf("6.Write to a file\n");
    printf("7.Read from a file\n");
    printf("0.Exit\n");
}

int read_information(STUDENT *pt)
{
    int n,i;
    printf("How many students?\n");
    scanf("%d",&n);
    for(i=0; i<n; i++)
    {
        printf("For student %d\n",i+1);
        printf("input id:");
        scanf("%ld",&(*pt).id);
        printf("input name:");
        scanf("%s",&(*pt).name);
        printf("input score math,English,physics:");
        scanf("%d,%d,%d",&(*pt).scoremt,&(*pt).scoreen,&(*pt).scoreph);
        pt++;
    }
    return n;
}

void calculate_total_and_average(STUDENT *pt,int n)
{
    int i;
    for(i=0; i<n; i++)
    {
        (*pt).total=(*pt).scoremt+(*pt).scoreen+(*pt).scoreph;
        (*pt).ave=(*pt).total/3.0;
        pt++;
    }
}

void sort_by_score(STUDENT *pt,int n)
{
    STUDENT temp;
    int i,j,ji;
    for(i=0; i<n-1; i++)
    {
        ji=i;
        for(j=i+1; j<n; j++)
        {
            if((*(pt+ji)).total<(*(pt+j)).total)
                ji=j;
        }
        temp=(*(pt+i));
        (*(pt+i))=(*(pt+ji));
        (*(pt+ji))=temp;
    }
}

void sort_by_name(STUDENT *pt,int n)
{
    STUDENT temp;
    int i,j,ji;
    for(i=0; i<n-1; i++)
    {
        ji=i;
        for(j=i+1; j<n; j++)
        {
            if(strcmp((*(pt+ji)).name,(*(pt+j)).name)>0)
                ji=j;
        }
        temp=(*(pt+i));
        (*(pt+i))=(*(pt+ji));
        (*(pt+ji))=temp;
    }
}

void write_information(STUDENT *pt,int n)
{
    int i;
    for(i=0; i<n; i++)
    {
        printf("student %d:",i+1);
        printf("id:%ld,name:%s,",(*pt).id,(*pt).name);
        printf("math:%d,English:%d,physics:%d,",(*pt).scoremt,(*pt).scoreen,(*pt).scoreph);
        printf("total:%d,average:%f\n",(*pt).total,(*pt).ave);
        pt++;
    }
}

void search_by_name(STUDENT *pt,int n)
{
    char searchname[10];
    int i,ji=-1;
    printf("name:");
    scanf("%s",&searchname);
    for(i=0; i<n; i++)
    {
        if(strcmp((*(pt+i)).name,searchname)==0)
        {
            ji=i;
            pt+=i;
            printf("student %d:",i+1);
            printf("id:%ld,name:%s,",(*pt).id,(*pt).name);
            printf("math:%d,English:%d,physics:%d,",(*pt).scoremt,(*pt).scoreen,(*pt).scoreph);
            printf("total:%d,average:%f,",(*pt).total,(*pt).ave);
            printf("rank:%d\n",i+1);
        }
    }
    if(ji==-1)
        printf("NOT FOUND!\n");
}

void write_to_file(STUDENT *pt,int n)
{
    FILE *fp;
    if((fp=fopen("student.txt","w"))==NULL)
    {
        printf("Failure to open student.txt!\n");
        exit(0);
    }
    fwrite(pt,sizeof(STUDENT),n,fp);
    fclose(fp);
}

void file_to_screen(STUDENT *pt,int n)
{
    int i;
    FILE *fp;
    if((fp=fopen("student.txt","r"))==NULL)
    {
        printf("Failure to open student.txt!\n");
        exit(0);
    }
    for(i=0; i<n; i++)
    {
        fread(pt+i,sizeof(STUDENT),1,fp);
    }
    fclose(fp);
}

四、经验总结

使用指针要时刻明确指针的指向

posted @ 2023-12-18 00:16  20231420  阅读(16)  评论(0编辑  收藏  举报