这几天在搞一个作业,大体内容是将学生的一些信息、成绩写入到文件中,然后再把他们读取出来按照成绩采用不同方式的排序(冒泡、选择、插入、快速等)。最后出现了一个问题,是在Switch语句中,每次都会调用同一个读取文件的函数,在进行不同的排序后,堆排序的结果显示出某一个结构体数组没有初始化的结果
上代码:
// 功能函数实现.cpp
#include"head.hpp" // 头文件中定义了各个函数以及头文件
void Show_Menu() {
cout << "*************************" << endl;
cout << " 1、录入学生基本信息" << endl;
cout << " 2、直接插入排序" << endl;
cout << " 3、冒泡排序" << endl;
cout << " 4、快速排序" << endl;
cout << " 5、简单选择排序" << endl;
cout << " 6、堆排序" << endl;
cout << " 7、2-路归并排序" << endl;
cout << " 8、输出学生信息" << endl;
cout << " 0、退出" << endl;
cout << "*************************" << endl;
}
void File_Read(Student stu[]) {
ifstream ifs;
ifs.open("StudentData.txt", ios::in);
int i = 1;
while (ifs >> stu[i].Id && ifs >> stu[i].Name && ifs >> stu[i].Score)
++i;
ifs.close();
}
// 直接插入排序
void Sort_Insert(Student stu[], int num) {
int j;
for (int i = 2; i <= num; ++i) {
if (stu[i].Score > stu[i - 1].Score) {
stu[0] = stu[i];
stu[i] = stu[i - 1];
for (j = i - 2; stu[0].Score > stu[j].Score; --j)
stu[j + 1] = stu[j];
stu[j + 1] = stu[0];
}
}
Input_Position(stu, num);
}
// 冒泡排序
void Sort_Bubble(Student stu[], int num) {
Student temp;
for (int i = 1; i <= num - 1; ++i)
for (int j = i + 1; j <= num; ++j)
if (stu[i].Score < stu[j].Score) {
temp = stu[i];
stu[i] = stu[j];
stu[j] = temp;
}
Input_Position(stu, num);
}
// 获取分割的位置
int getStandard(Student stu[], int low, int high) {
int i = low - 1;
int j = high;
int key = stu[j].Score;
while (true) {
while (stu[++i].Score > key);
while (stu[--j].Score < key);
if (i < j)
swap(stu[i], stu[j]);
else
break;
}
swap(stu[i], stu[high]);
return i;
}
// 快速排序
void Sort_Quick(Student stu[], int low, int high) {
if (low < high) {
int mid = getStandard(stu, low, high);
Sort_Quick(stu, low, mid - 1);
Sort_Quick(stu, mid + 1, high);
}
}
// 简单选择排序
void Sort_Choose(Student stu[], int num) {
int flag;
for (int i = 1; i <= num - 1; ++i) {
flag = i;
for (int j = i + 1; j <= num; ++j)
if (stu[flag].Score < stu[j].Score)
flag = j;
if (flag != i)
swap(stu[flag], stu[i]);
}
Input_Position(stu, num);
}
/* 堆排序
堆排序的要点:
下标为i的结点,父节点下标为(i-1)/2
下标为i的结点,左孩子下标为i*2+1
下标为i的结点,右孩子下标为i*2+2
*/
// 数据降序排序,需要使用小根堆
// 以小根堆为基础,维护堆的性质
void Defend_Heapify(Student stu[], int n, int i) {
int min = i; // 假设根节点为最大
int l_son = i * 2 + 1;
int r_son = i * 2 + 2;
if (l_son < n && stu[l_son].Score > stu[min].Score)
min = l_son;
if (r_son < n && stu[r_son].Score > stu[min].Score)
min = r_son;
if (min != i) {
swap(stu[min], stu[i]);
Defend_Heapify(stu, n, min);
}
}
// 堆排序的入口
void Sort_Heap(Student stu[], int n){
// 建立堆
for (int i = n / 2 - 1; i > 0; --i)
Defend_Heapify(stu, n, i);
// 进行排序
for (int j = n - 1; j > 0; --j) {
swap(stu[j], stu[0]);
Defend_Heapify(stu, j, 1);
}
Input_Position(stu, n);
}
// 归并排序中用于划分区域的函数
void Merge_Algorithm(Student stu[], Student arr[], int left, int right) {
// 区域中不止一个元素
if (left < right) {
// 划分中间点
int mid = (left + right) / 2;
// 划分左半区域
Merge_Algorithm(stu, arr, left, mid);
// 划分右半区域
Merge_Algorithm(stu, arr, mid + 1, right);
// 合并
Merge_Arr(stu, arr, left, mid, right);
}
}
// 归并排序中用于合并的函数
void Merge_Arr(Student stu[], Student arr[], int left, int mid, int right) {
int l_pos = left; // 左半区第一个未排序的元素
int r_pos = mid + 1; // 右半区第一个未排序的元素
int pos = left; // 临时数组下标
while (l_pos <= mid && r_pos <= right) {
if (stu[l_pos].Score > stu[r_pos].Score) {
arr[pos] = stu[l_pos];
++pos;
++l_pos;
}
else {
arr[pos] = stu[r_pos];
++pos;
++r_pos;
}
}
// 合并左半区域
for (; l_pos < mid; ++pos, ++l_pos)
arr[pos] = stu[l_pos];
// 合并右半区
for (; r_pos < right; ++pos, ++r_pos)
arr[pos] = stu[r_pos];
// 临时数组的元素赋给原数组
while (left < right) {
stu[left] = arr[left];
++left;
}
}
// 归并排序入口
void Sort_Merge(Student stu[], int n) {
Student* tempArr = new Student[n];
if (tempArr) {
for (int i = 0; i < n; ++i)
tempArr[i].Name = "";
Merge_Algorithm(stu, tempArr, 1, n);
delete[] tempArr;
}
else {
cout << "error: failed to allocate memory" << endl;
}
Input_Position(stu, n);
}
void Swap(Student& s1, Student& s2) {
Student temp = s1;
s1 = s2;
s2 = temp;
}
// 将学生的名次录入
void Input_Position(Student stu[], int num) {
int j = 1;
for (int i = 1; i < num; ++i)
if (stu[i].Score != stu[i + 1].Score) {
stu[i].Pos = j;
++j;
stu[i + 1].Pos = j;
}
else {
stu[i].Pos = j;
stu[i + 1].Pos = j;
}
}
void Display_Information(Student stu[], int num) {
cout << "名次\t 学号\t 姓名\t 成绩" << endl;
for (int i = 1; i <= num; ++i)
cout << stu[i].Pos << "\t" << stu[i].Id << "\t" << stu[i].Name << "\t" << stu[i].Score << endl;
cout << endl;
}
// main.cpp
#include"head.hpp"
using namespace std;
int num = 0;
void Init_StudentInformation(Student stu[]) {
cout << "本次录入信息的学生个数:";
int after;
cin >> after;
num += after;
int id, score;
string name;
ofstream ofs;
ofs.open("StudentData.txt", ios::app);
if (!ofs.is_open()) {
cout << "Error: Open file failed." << endl;
exit(-1);
}
for (int i = 1; i <= after; ++i) {
cout << "第" << i << "位学生的学号:";
cin >> id;
cout << "第" << i << "位学生的姓名:";
cin >> name;
cout << "第" << i << "位学生的分数:";
cin >> score;
ofs << id << "\t" << name << "\t" << score << endl;
}
ofs.close();
}
int main() {
Student* stu = new Student[100];
int choice;
ofstream ofs;
ofs.open("StudentData.txt", ios::trunc);
ofs.close();
while (true) {
Show_Menu();
cin >> choice;
switch (choice) {
case 1:Init_StudentInformation(stu); cout << "Get Information Successfully." << endl;
system("pause"); system("cls"); break;
case 2: File_Read(stu); Sort_Insert(stu, num); cout << "Insert Sort Successfully." << endl;
system("pause"); system("cls"); break;
case 3: File_Read(stu); Sort_Bubble(stu, num); cout << "Bubble Sort Successfully." << endl;
system("pause"); system("cls"); break;
case 4: File_Read(stu); Sort_Quick(stu, 1, num); Input_Position(stu, num); cout << "Quick Sort Successfully." << endl;
system("pause"); system("cls"); break;
case 5: File_Read(stu); Sort_Choose(stu, num); cout << "Choose Sort Successfully." << endl;
system("pause"); system("cls"); break;
case 6: File_Read(stu); Sort_Heap(stu, num); cout << "Heapify Sort Successfully." << endl;
system("pause"); system("cls"); break;
case 7: File_Read(stu); Sort_Merge(stu, num); cout << "Merge Sort Successfully." << endl;
system("pause"); system("cls"); break;
case 8: cout << "Students' Information:" <<endl; Display_Information(stu, num);
system("pause"); system("cls"); break;
case 0: cout << "System Exit." << endl; return 0;
default: cout << "Error: Input illegal. Please re-enter." << endl;
}
}
return 0;
}
在其他选项中,输出的结果表明结构体数组中所输出的元素是有数据的,但是如果录入数据后先选择6(堆排序),就会有一个元素没有被赋初值
如下:
很明显第二个数据显示出的结果表明没有被初始化。
求帮助
很明显,读取行的时候发生了异常。
可以Debug到文件路径下
查看文件如何被读取。
while (ifs >> stu[i].Id && ifs >> stu[i].Name && ifs >> stu[i].Score)
++i;