#include<stdio.h>
#include<iostream>
#include<fstream>
#include<string>
#include <vector>
#include<sstream>
#include<algorithm>
using namespace std;
//定义结构体,以便接下来对学生成绩进行排序
struct Student {
std::string line; // 保存原始行内容
int score; // 保存第m个字段的分数
int sum; //总成绩使用
//double average; //平均分使用
// 定义自定义比较运算符,用于排序
bool operator<(const Student& other) const {
return score > other.score;
}
};
struct Student_Beifen {
std::string line;
double average;
bool operator<(const Student_Beifen& other) const {
return average > other.average; // 按平均数降序排列
}
};
//总成绩函数
void FileContSum() {
std::string filename = "./filename.txt";
std::ifstream inputFile(filename); // 打开文件以读取内容
std::string line;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
std::vector<std::string> fields;
std::string field;
while (iss >> field) {
fields.push_back(field);
}
int sum = 0;
for (int i = fields.size() - 3; i < fields.size(); ++i) {
sum += std::stoi(fields[i]);
}
line += " " + std::to_string(sum); // 将和追加到每行的末尾
std::cout << line << std::endl; // 输出带有和的每行内容
}
inputFile.close(); // 关闭文件
}
//文件读取函数
void FileR(){
std::ifstream file("./filename.txt"); // 打开文件
if (file.is_open()) { // 检查文件是否成功打开
std::string line;
while (std::getline(file, line)) { // 逐行读取文件内容
std::cout << line << std::endl; // 输出每一行内容
}
file.close(); // 关闭文件
}
else {
std::cout << "无法打开文件" << std::endl;
}
}
//写入文件函数
void FileW() {
std::ofstream file("./filename.txt", std::ios::app); // 打开文件并追加内容
if (file.is_open()) { // 检查文件是否成功打开
std::string input;
std::cout << "请按照<学号 姓名 性别 班级 数据结构 Linux编程 算法设计与分析>顺序输入该学生信息及成绩(以EOF结束):" << std::endl;
while (std::getline(std::cin, input)) { // 逐行读取用户输入
if (input == "EOF") {
FileContSum(); //BUG,调用该函数会导致刚写入的成绩信息前面有一行空格
break; // 输入 EOF 结束循环
}
file << input << std::endl; // 追加内容到文件末尾
}
file.close(); // 关闭文件
std::cout << "成绩录入完成" << std::endl;
}
else {
std::cout << "无法打开文件" << std::endl;
}
}
//文件内容删除函数
void FileContDel(long long int student_id) {
std::string strstudent_id = std::to_string(student_id); //把long long int 转化为str类型,否则下面将无法匹配
std::string filename = "./filename.txt";
std::ifstream inputFile(filename); // 打开文件以读取内容
std::vector<std::string> lines; // 存储文件的每一行内容
std::string line;
while (std::getline(inputFile, line)) {
std::string firstPart;
std::istringstream isse(line);
isse >> firstPart; // 读取每一行开头的数字部分
if (firstPart != strstudent_id) { // 如果不是目标行,则将其存储在 vector 中
lines.push_back(line);
}
}
inputFile.close(); // 关闭文件
if (lines.empty()) { // 如果文件内容已被清空,则直接删除文件并返回
std::remove(filename.c_str());
std::cout << "文件已被清空。" << std::endl;
return;
}
std::ofstream outputFile(filename); // 以写入模式打开同一个文件
if (!outputFile) {
std::cerr << "无法打开文件:" << filename << std::endl;
return;
}
for (const auto& line : lines) {
outputFile << line << std::endl; // 将修改后的内容写入文件
}
outputFile.close(); // 关闭文件
std::cout << "学号为 " << student_id << " 的学生成绩信息已被删除。" << std::endl;
}
//文件内容查找函数
void FileContSearch(std::string name) {
//cout << "函数被调用"<<endl; //测试用例
std::string filename = "./filename.txt"; //定义文件变量
std::ifstream inputFile(filename); // 打开文件以读取内容
std::string line;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
std::string field2; // 第二个字段
iss >> field2; // 读取第二个字段
size_t pos = line.find(name); // 在整行中查找目标内容
if (pos != std::string::npos) { // 如果找到匹配的内容,则输出整行内容
std::cout << line << std::endl;
}
}
inputFile.close(); // 关闭文件
}
//文件内容排序
void FileContSort(int m) {
std::string filename = "./filename.txt"; // 定义文件名
std::ifstream inputFile(filename); // 打开文件进行读取
std::vector<Student> students; // 存储学生信息的结构体数组
std::string line;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
Student student;
student.line = line;
// 解析字段直到第m个字段
for (int i = 1; i < m+4; ++i) { //不要直接i<m!!!因为输入的m并不是i的边界值
std::string temp;
iss >> temp;
}
// 将第m个字段转换为整数作为分数
iss >> student.score;
students.push_back(student);
}
std::sort(students.begin(), students.end()); // 根据分数对学生进行排序
for (const auto& student : students) {
std::cout << student.line << std::endl; // 输出排好序的行内容
}
inputFile.close(); // 关闭文件
}
//统计函数
void FileContCount(int function_count) {
std::string filename = "./filename.txt"; // 定义文件名
std::ifstream inputFile(filename); // 打开文件以读取内容
std::vector<Student_Beifen> students;
std::string line;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
std::vector<std::string> fields;
std::string field;
while (iss >> field) {
fields.push_back(field);
}
int sum = 0;
for (int i = fields.size() - 3; i < fields.size(); ++i) {
sum += std::stoi(fields[i]);
}
double average = static_cast<double>(sum) / 3.0; // 计算平均数
Student_Beifen student1;
student1.line = line;
student1.average = average;
students.push_back(student1);
}
std::sort(students.begin(), students.end()); // 按平均数降序排列
for (const auto& student1 : students) {
std::cout << student1.line << " 平均分:" << student1.average << std::endl; // 输出按平均数降序的每行内容
}
inputFile.close(); // 关闭文件
}
//界面函数
void Interface() {
int outputSelect = 0; //控制功能列表选择变量
int Class = 0; //班级变量
int state = 1; //控制功能列表状态
int state_class = 1; //控制班级功能列表选择变量
int outputSelect_class = 0; //班级功能列表选择
long long int student_id = 0; //学号,并且以防学好超出int范围
std::string name = ""; //学生姓名
int source_sort = 0; //排序选项
int state_sort = 1; //控制排序列表变量
//string fname = ""; //班级文件名,用于区分班级
int function_count = 0; //控制统计功能的变量
int state_count = 1; //控制统计状态的变量
while (state)
{
int state_count = 1; //防止返回功能列表后无法再进行统计
cout << "-------功能列表--------"<<endl;
cout << "1、选择班级"<< endl;
cout << "2、成绩查询"<<endl;
cout << "3、成绩删除"<<endl;
cout << "4、成绩统计"<<endl;
cout << "5、成绩排序" << endl;
cout << "6、退出程序"<<endl;
cout << "选择你使用的功能:" ;
cin >> outputSelect;
switch (outputSelect) {
case 1:
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
cout << "---当前功能为班级选择---"<<endl;
cout << "选择你的班级:";
cin >> Class;
cout << "";
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
while (state_class) { //进入班级功能选择
cout << "---班级功能列表---" << endl;
cout << "当前班级为:" << Class << "班" << endl;
cout << "1、输入成绩" << endl;
cout << "2、查看成绩" << endl;
cout << "3、退至主功能列表" << endl;
cout << "你的选择:";
cin >> outputSelect_class; //这段代码要写入循环否则会产生死循环
switch (outputSelect_class) {
case 1:
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
cout << "学号 姓名 性别 班级 数据结构 Linux 算法设计与分析 总分"<<endl;
FileW(); //调用文件写入函数
break;
case 2:
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
cout << "学号 姓名 性别 班级 数据结构 Linux 算法设计与分析 总分"<<endl;
FileR(); //调用文件读取函数
break;
case 3:
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
Interface(); //调用功能列表函数
break;
default:
cout << "错误输入,退出程序";
state_class = 0;
}
}
break;
case 2:
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
cout << "你要查询的学生姓名:";
cin >> name;
FileContSearch(name);
break;
case 3:
cout << "请输入你要删除成绩信息的学生学号:";
cin >> student_id;
FileContDel(student_id); //调用成绩删除函数
break;
case 4:
while (state_count) {
cout << "1、统计每个学生的平均分,按平均分降序输出" << endl;
cout << "2、统计每个班级的平均分,按平均分降序输出" << endl; //功能未实现
cout << "3、统计每个班中总分最高的前三名和总分最低的后三名" << endl;
cout << "4、统计获得奖学金的学生信息(平均分>=90且各科成绩>=85)" << endl;
cout << "5、返回功能列表" << endl;
cout << "输入你选择的功能:";
cin >> function_count;
if (function_count == 5) {
state_count = 0;
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
}
else {
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
FileContCount(function_count);
}
}
break;
case 5:
while (state_sort) {
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
cout << "1、按照数据结构成绩降序" << endl;
cout << "2、按照Linux编程成绩降序" << endl;
cout << "3、按照算法设计与分析成绩降序" << endl;
cout << "4、按照总分降序" << endl;
cout << "请选择你的排序方式:";
cin >> source_sort;
if (source_sort == 1 || source_sort == 2 || source_sort == 3 || source_sort == 4) {
FileContSort(source_sort);
}
else {
cout << "输入有误,退出程序";
std::exit(0); // 结束程序并返回状态码 0
}
cout << "0、返回功能列表" << endl;
cout << "1、继续排序" << endl;
cout << "请输入:";
cin >> state_sort;
std::cout << "\033[2J\033[1;1H"; // 清屏,并将光标移动到左上角
}
break;
case 6:
std::exit(0); // 结束程序并返回状态码 0
break;
default:
cout << "输入有误,退出程序";
std::exit(0); // 结束程序并返回状态码 0
}
}
}
//折半插入排序函数
void binaryInsertionSort(int arr[], int n) {
// 遍历数组
for (int i = 1; i < n; i++) {
// 获取当前元素
int key = arr[i];
// 定义二分查找的上下限
int low = 0, high = i - 1;
// 二分查找插入位置
while (low <= high) {
// 计算中间位置
int mid = (low + high) / 2;
// 如果当前元素小于中间位置的元素,则在左半侧继续查找插入位置
if (key < arr[mid]) {
high = mid - 1;
}
// 否则,在右半侧继续查找插入位置
else {
low = mid + 1;
}
}
// 将大于当前元素的元素后移
for (int j = i - 1; j >= low; j--) {
arr[j + 1] = arr[j];
}
// 插入当前元素
arr[low] = key;
}
}
//冒泡排序函数
void bubbleSort(int arr[], int n) {
// 外层循环控制每一轮比较的次数
for (int i = 0; i < n - 1; i++) {
// 内层循环进行相邻元素的比较和交换
for (int j = 0; j < n - i - 1; j++) {
// 如果前一个元素大于后一个元素,则交换它们的位置
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
//快速排序函数
int partition(int arr[], int low, int high) {
// 选择最后一个元素作为基准值
int pivot = arr[high];
// 初始化 i 为分区的边界索引,初始值为 low-1
int i = low - 1;
// 遍历分区内的元素
for (int j = low; j <= high - 1; j++) {
// 如果当前元素小于基准值,则将其交换到分区的边界位置,并更新边界索引
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
// 将基准值交换到正确的位置上
swap(arr[i + 1], arr[high]);
// 返回基准值的索引
return i + 1;
}
void quickSort(int arr[], int low, int high) {
// 当分区的起始索引小于结束索引时进行递归排序
if (low < high) {
// 对分区进行划分,获取基准值的索引
int pivotIndex = partition(arr, low, high);
// 对左侧分区进行快速排序
quickSort(arr, low, pivotIndex - 1);
// 对右侧分区进行快速排序
quickSort(arr, pivotIndex + 1, high);
}
}
int main() {
Interface();
return 0;
}