c++利用类与对象进行学生文件读写


#include
#include
#include
#include
using namespace std;
class CStudent {
private:
    char No[11], Name[7];
    int score[4];
    float ave;
public:
    CStudent() {}
    void SetData(char *NO,char *NAME,int one,int two,int three);
    void Display();
    float Average() {
        ave = score[3] / 3.0;
        return ave;
    }
    int GetScore_one() {
        return score[0];
    }
    int GetScore_two() {
        return score[1];
    }
    int GetScore_three() {
        return score[2];
    }
    int GetScore_four() {
        return score[3];
    }
};
void CStudent::SetData(char *NO,char *NAME,int one,int two,int three) {
    strcpy(No,NO);
    strcpy(Name,NAME);
    score[0]=one;
    score[1]=two;
    score[2]=three;
    score[3]=one+two+three;
}
void CStudent::Display() {
    cout << endl << endl << No << " " << Name << " " <<
        score[0] << " " << score[1] << " " <<
        score[2] << " " << Average()<<"  ";
}


class CStatistic {
private:
    int Nums;
    float Ave[4];
    CStudent* StuArray;
public:
    CStatistic();
    void Average();
    void Display_one();
    void Sort();
};
CStatistic::CStatistic() {
    FILE *fp;
    Nums=0;
    int k=0;
    char NO[11],NAME[7];
    int one,two,three;
    fp=fopen("D:\\dddd.txt","r");
    while(!feof(fp)){
        fscanf(fp,"%s %s %d %d %d",NO,NAME,&one,&two,&three);
        Nums++;
    }
    fclose(fp);
    StuArray=new CStudent[Nums+1];
    fp=fopen("D:\\dddd.txt","r");
    while(!feof(fp)){
        fscanf(fp,"%s %s %d %d %d",NO,NAME,&one,&two,&three);
        StuArray[k].SetData(NO,NAME,one,two,three);
        k++;
    }
    fclose(fp);
}
void CStatistic::Sort() {
    for (int i = 0; i < Nums; i++) {
        for (int j = 0; j < (Nums - i); j++) {
            if (StuArray[j].GetScore_four() < StuArray[j + 1].GetScore_four()) {
                StuArray[Nums] = StuArray[j];
                StuArray[j] = StuArray[j + 1];
                StuArray[j + 1] = StuArray[Nums];
            }
        }
    }

}
void CStatistic::Average() {
    for (int s = 0; s < 4; s++) {
        Ave[s] = 0;
    }
    for (int j = 0; j < Nums; j++) {
        Ave[0] += StuArray[j].GetScore_one();
        Ave[1] += StuArray[j].GetScore_two();
        Ave[2] += StuArray[j].GetScore_three();
        Ave[3] += StuArray[j].Average();
    }
}
void CStatistic::Display_one() {
    cout << "学号" << "姓名" << "语文" << "数学" << "英语" << "平均分" << endl;
    for (int i = 0; i < Nums; i++) {
        StuArray[i].Display();
        cout << i + 1 << endl;
    }
    cout << "总评" << Ave[0]/3.0  << " "
        << Ave[1] / 3.0 << " " << Ave[2] / 3.0 << " " << Ave[3] / 3.0 << endl;
}
int main() {
    CStatistic* pStatistic = new CStatistic();
    pStatistic->Sort();
    pStatistic->Average();
    pStatistic->Display_one();
    return 0;
}

做一个从文件中读取学生成绩的类组合,代码能运行,但点运行后就闪退,不知道哪里出了问题。其中读的文件是学号加姓名加三科成绩。

参考GPT和自己的思路,闪退的原因可能是因为以下几个问题:

1.在进行文件读取时,需要判断文件是否成功打开,以及文件读取是否成功,否则可能导致程序崩溃。在代码中没有进行文件打开和读取的错误处理,可能会导致程序异常结束。

2.在CStatistic类的构造函数中,动态分配内存时申请了Nums+1个CStudent对象,可能会导致数组越界,应该申请Nums个对象。

3.在CStatistic类的Sort()函数中,冒泡排序的内部循环应该是j < (Nums - i - 1),而不是j < (Nums - i),否则可能会越界。

4.在CStatistic类的Sort()函数中,交换数组元素的代码可能会导致越界访问,应该将StuArray[Nums]改为一个临时的CStudent对象。

修改后的代码如下:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>
using namespace std;

class CStudent {
private:
    char No[11], Name[7];
    int score[4];
    float ave;
public:
    CStudent() {}
    void SetData(char* NO, char* NAME, int one, int two, int three);
    void Display();
    float Average() {
        ave = score[3] / 3.0;
        return ave;
    }
    int GetScore_one() {
        return score[0];
    }
    int GetScore_two() {
        return score[1];
    }
    int GetScore_three() {
        return score[2];
    }
    int GetScore_four() {
        return score[3];
    }
};

void CStudent::SetData(char* NO, char* NAME, int one, int two, int three) {
    strcpy_s(No, NO);
    strcpy_s(Name, NAME);
    score[0] = one;
    score[1] = two;
    score[2] = three;
    score[3] = one + two + three;
}

void CStudent::Display() {
    cout << endl << endl << No << " " << Name << " " <<
        score[0] << " " << score[1] << " " <<
        score[2] << " " << Average() << "  ";
}

class CStatistic {
private:
    int Nums;
    float Ave[4];
    CStudent* StuArray;
public:
    CStatistic();
    void Average();
    void Display_one();
    void Sort();
    ~CStatistic() {
        delete[] StuArray;
    }
};

CStatistic::CStatistic() {
    FILE* fp;
    Nums = 0;
    int k = 0;
    char NO[11], NAME[7];
    int one, two, three;

    // 打开文件
    if (fopen_s(&fp, "D:\\dddd.txt", "r") != 0) {
        cout << "文件打开失败" << endl;
        exit(1);
    }

    // 计算学生人数
    while (!feof(fp)) {
        fscanf_s(fp, "%s %s %d %d %d", NO, 11, NAME, 7, &one, &two, &three);
        Nums++;
    }

    fclose(fp);
}

参考GPT和自己的思路:

根据代码,可能是以下几个问题导致程序闪退:

  1. 在CStatistic类中,StuArray数组的大小应该为Nums而不是Nums+1,即应该是StuArray=new CStudent[Nums];

  2. 由于使用了动态内存分配,需要在CStatistic类析构函数中释放StuArray指向的内存:

CStatistic::~CStatistic() {
    delete[] StuArray;
}
  1. 在SetData函数中,score[3]应该是one+two+three,而不是three个数据的平均值,即应该是:
score[3]=one+two+three;

经过以上修改后,程序应该能正确执行。

不要直接运行,要f5调试,然后看运行到哪里出现错误,把错误的行贴出来
多半是指针问题

https://blog.csdn.net/he4yu1xuan5/article/details/127229564

参考GPT和自己的思路:根据您提供的代码,您定义了CStudent类和CStatistic类,其中CStatistic类有一个CStudent对象数组StuArray和一些成员函数来对学生数据进行处理,包括排序和计算平均值。在main函数中,您创建了一个CStatistic对象指针pStatistic,并调用了一系列成员函数。

但是,从代码中无法确定闪退问题的原因。在您的代码中,有一些潜在的问题可能会导致程序崩溃,例如:

1.在CStatistic构造函数中,您计算学生人数的方式可能会导致问题:

while(!feof(fp)){
    fscanf(fp,"%s %s %d %d %d",NO,NAME,&one,&two,&three);
    Nums++;
}

eof函数在文件结尾处返回true,但在读取最后一行之前,它会一直返回false。因此,您的代码会将学生人数计算为文件中的行数+1,这可能导致数组越界或其他问题。

2.在CStatistic构造函数中,您没有检查文件是否成功打开:

fp=fopen("D:\\dddd.txt","r");

如果文件不存在或无法打开,fp将为NULL。您应该在打开文件之后检查它是否为NULL,以确保您可以从文件中正确读取数据。

3.在CStatistic::Sort()函数中,如果j等于Nums-1,j+1将越界:

if (StuArray[j].GetScore_four() < StuArray[j + 1].GetScore_four()) {

因此,应将内部循环的终止条件更改为“j < (Nums - i - 1)”:

for (int j = 0; j < (Nums - i - 1); j++) {

4 在CStatistic::Sort()函数中,将StuArray数组中的对象进行交换时,需要使用对象的引用或指针,而不是复制对象:

CStudent temp = StuArray[j];
StuArray[j] = StuArray[j + 1];
StuArray[j + 1] = temp;

应该修改为:

Copy code
CStudent& temp = StuArray[j];
StuArray[j] = StuArray[j + 1];
StuArray[j + 1] = temp;

或者:

CStudent* temp = &StuArray[j];
StuArray[j] = StuArray[j + 1];
StuArray[j + 1] = *temp;

否则,每次交换都会调用对象的拷贝构造函数,导致性能下降。

除了上述潜在问题之外,闪退问题可能还与其他代码有关。您可以尝试使用调试器来跟踪程序崩溃的位置,以便更容易地确定问题所在。