上个月程序设计作业做了一个学生信息管理系统,效果如下图
附上源代码。
//由于不熟悉文件读写,有些地方的代码有点奇怪。但是功能是可以实现的。
//虽然是用C++,但主要还是用了面向过程
/*
·File name: file.h
·Description: 所有和文件读写相关的操作
*/
#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include"student.h"
/*
函数:read_record()
功能:从record.txt读入记录,得到现有的记录条数
参数:学生信息记录条数&m, 成绩条数&n,
返回值:1
*/
int read_record(int &m, int &n)
{
std::ifstream fin("record.txt");
fin >> m;
fin >> n;
return 1;
}
/*
函数:write_record()
功能:写入记录到record.txt,更新记录条数
参数:学生信息记录条数m, 成绩条数n,
返回值: 0
*/
int write_record(int m, int n)
{
std::ofstream fout("record.txt");
fout << m;
fout << " ";
fout << n;
return 1;
}
/*
函数:save_score()
功能:保存文件到score.dat
参数: 学生成绩指针StudentScore*, 学生成绩条数n
*/
void save_score(StudentScore* stu_score,int n)
{
using namespace std;
ofstream fout("score.dat", ios::binary);
if (!fout)
{
cout << "创建文件失败\n";
return;
}
int i = 0;
for (int i = 0; i < n; i++)
{
fout << stu_score[i].ID << " " << stu_score[i].lesson_number << " "
<< stu_score[i].lesson_name << " " << stu_score[i].credit<< " "
<< stu_score[i].daily_score << " " << stu_score[i].exp_score<< " "
<< stu_score[i].exam_score << " " << stu_score[i].total_score<< " "
<< stu_score[i].actual_score << "\n";
}
fout.close();
}
/*
函数:read_to_stu_score()
功能:从文件score.dat读入分数到数组
参数:学生成绩数组StudentScore*, 学生成绩条数&n
*/
int read_to_stu_score(StudentScore* stu_score, int &n)
{
using namespace std;
int i = 0;
ifstream fin("score.dat", ios::binary);
if (!fin)
{
cout << "读取成绩文件score.dat失败" << endl;
return 0;
}
for (int i = 0; i < n; i++)
{
fin >> stu_score[i].ID >> stu_score[i].lesson_number
>> stu_score[i].lesson_name >> stu_score[i].credit
>> stu_score[i].daily_score >> stu_score[i].exp_score
>> stu_score[i].exam_score >> stu_score[i].total_score
>> stu_score[i].actual_score;
}
fin.close();
return i;
}
/*
函数:read_to_stu()
功能:从文件student.txt读入学生信息到数组
参数:学生数组Student*, 学生信息条数m
*/
int read_to_stu(Student* stu, int &m)
{
using namespace std;
int i = 0;
ifstream fin("student.txt");
if (!fin)
{
cout << "读取学生基本文件student.txt失败" << endl;
return 0;
}
string temp;//临时string,读入第一行的5个字符串
for (int i = 0; i < 5; i++)
{
fin >> temp;
}
for (int i = 0; i < m; i++)
{
fin >> stu[i].ID >> stu[i].name >> stu[i].sex >> stu[i].dor_number
>> stu[i].phone;
}
fin.close();
return 1;
}
/*
函数:save_stu
功能:写入学生信息到student.txt
参数:学生数组Student*,学生信息条数m
*/
void save_stu(Student* stu, int m)
{
using namespace std;
ofstream fout("student.txt");
if (!fout)
{
cout << "创建文件失败\n";
return;
}
fout << "学号 姓名 性别 宿舍号码 电话号码\n";
for (int i = 0; i < m; i++)
{
fout << stu[i].ID << " " << stu[i].name << " " << stu[i].sex << " "
<< stu[i].dor_number << " " << stu[i].phone<<"\n";
}
fout.close();
}
/*
·File name: func.h
·Description: 实现学生管理系统的相关函数的声明
*/
#pragma once
#include<string>
#include"student.h"
int read_data_and_calcu(StudentScore* stu_score, int & n);
int find(Student * stu, StudentScore* stu_score,int m, int n);
void find_baseinfo(Student* stu, int n);
void find_baseinfo_by_id_name(Student* stu, int m);
void find_baseinfo_by_dor(Student* stu, int m);
void find_score(Student* stu, StudentScore * stu_score,int m, int n);
int sort_score(StudentScore * stu_score, int n);
int delete_by_ID(Student * stu, StudentScore * stu_score, int &m, int &n);
/*
·File name: menu.h
·Description: 菜单相关函数的声明
*/
#pragma once
#include"student.h"
void show_menu();
bool choose_func(char choice, bool & active, StudentScore * stu_score, Student * stu,
int & m, int& n);
/*
·File name: student.h
·Description: 学生类和学生成绩类
*/
#pragma once
#include<iostream>
#include<iomanip>
#include<string>
using std::string;
// StudentScore 存储学生成绩
class StudentScore
{
public:
int ID; //学号
string lesson_number; //课程编号
string lesson_name; //课程名称
int credit; //学分
int daily_score; //平时成绩
int exp_score; //实验成绩
int exam_score; //卷面成绩
double total_score; //综合成绩, 计算得到
double actual_score; // 实际得分, 计算得到
public:
StudentScore() ;
StudentScore(int ID, string lesson_number,string lesson_name,int credit,
int daily_score,int exp_score,int exam_score);
~StudentScore() ;
friend std::ostream& operator<<(std::ostream& os, const StudentScore& score);
};
//Student类,存储学生信息
class Student
{
public:
int ID; //学号
string name; //姓名
string sex; //性别
int dor_number; //宿舍号码
int phone; //电话
public:
Student();
~Student();
friend std::ostream & operator<<(std::ostream & os, const Student& stu);
};
/*
·File name: func.cpp
·Description: 实现菜单的4项功能:1.读入数据; 2.查找; 3.删除; 4.成绩排序
*/
#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
#include"student.h"
using std::string;
using std::cin;
using std::cout;
//下面这4个函数被find调用,故先声明。
void find_baseinfo(Student* stu, int m);
void find_baseinfo_by_id_name(Student* stu, int m);
void find_baseinfo_by_dor(Student* stu, int m);
void find_score(Student* stu, StudentScore * stu_score,int m,int n);
/*
函数:read_data_and_calcu()
功能:从键盘读入成绩相关的7项数据,并根据公式计算出综合成绩和实得学分。
参数:StudentScore*(分数数组地址), &n(已有的成绩条数)
返回值:写入的条数
*/
int read_data_and_calcu(StudentScore* stu_score, int & n)
{
int Max_read = 1; //每次最多读入的条数
bool flag_input = true;// 用来判断是否正常输入
int id = 0; //学号
string lesson_number;//课程编号
string lesson_name; //课程名称
int credit; //学分
int daily_score; //平时成绩
int exp_score; //实验成绩
int exam_score; //卷面成绩
int i = 0;
for( i = n; i< n+Max_read && flag_input; i++)
{
cout << "开始输入学生数据:\n";
cout << "学号,"<< " 课程编号, " << " 课程名称: \n";
cin >> id;
cin >> lesson_number;
cin >> lesson_name;
cout << "学分, " << " 平时成绩, " << " 实验成绩," << " 卷面成绩:\n";
cin >> credit>> daily_score >>exp_score>> exam_score;
stu_score[i] = StudentScore(id, lesson_number, lesson_name, credit, daily_score,
exp_score, exam_score);
cout << "录入该学生数据成功";
}
cout << "\n";
n += i;
return i;
}
/*
函数:find()
功能:查询(总),通过用户选择查询类型调用find_baseinfo()或find_score(),显示对应的信息。
参数:Student*(学生数组地址), StudentScore*(分数数组地址),int m(学生信息条数), int n(分数条数)
返回值:0
*/
int find(Student * stu,StudentScore* stu_score,int m, int n)
{
cout << "输入查询类型:1.学生基本情况查询; 2.成绩查询:";
char find_kind;
cin >> find_kind;
switch (find_kind)
{
case '1':
//学生基本情况查询
find_baseinfo( stu, m);
break;
case '2':
//成绩查询
find_score(stu, stu_score,m, n);
break;
default:
cout<<"无效选择\n";
break;
}
cout << "\n";
return 0;
};
/*
函数:find_baseinfo()
功能:查询_学生基本信息,被find()调用,显示对应的学生信息
参数:Student*, m
*/
void find_baseinfo(Student* stu, int m)
{
cout << "输入查询方式:1.按学号或姓名查询 2.按宿舍查询: ";
int choice;
cin >> choice;
switch (choice)
{
case 1:
find_baseinfo_by_id_name(stu, m);
break;
case 2:
find_baseinfo_by_dor(stu, m);
break;
}
}
/*
函数:find_baseinfo_by_id_name()
功能:查询_学生基本信息_通过_id或name,被find_baseinfo()调用
参数:Student*, m
*/
void find_baseinfo_by_id_name(Student* stu, int m)
{
cout << "选择:1.使用学号查询 2.使用姓名: ";
int choice_2;
cin >> choice_2;
switch (choice_2)
{
case 1:
{
//按学号查询,打印结果
cout << "输入学号: ";
int id;
cin >> id;
bool flag_find_id = false;
for (int i = 0; i < m; i++)
{
if (id == stu[i].ID)
{
flag_find_id = true;
cout << "学号 姓名 性别 宿舍号码 电话号码\n";
cout << stu[i];
break;
}
if (i == m - 1 && !flag_find_id )
cout << " 此ID记录不存在\n";
}
}
break;
case 2:
{
//使用姓名查询,打印结果
cout << "输入姓名: ";
string name;
cin >> name;
bool flag_find_name = false;
for (int i = 0; i < m; i++)
{
if (name == stu[i].name)
{
flag_find_name = true;
cout << "学号 姓名 性别 宿舍号码 电话号码\n";
cout << stu[i];
break;
}
if (i == m - 1 && !flag_find_name)
cout << " 此姓名记录不存在\n";
}
break;
}
}
}
/*
函数:find_baseinfo_by_dor()
功能:查询_学生基本信息_通过_宿舍,被find_baseinfo()调用
参数:Stuent*, m
*/
void find_baseinfo_by_dor(Student* stu, int m)
{
//按宿舍查询,打印结果
cout << "输入宿舍号: ";
int dor_number;
cin >> dor_number;
cout << "学号 姓名 性别 宿舍号码 电话号码\n";
bool flag_find_dor = false;
for (int i = 0; i < m; i++)
{
if (dor_number == stu[i].dor_number)
{
flag_find_dor = true;
cout << stu[i];
cout << "\n";
}
if (i == m - 1 && !flag_find_dor )
cout << " 宿舍记录不存在\n";
}
}
/*
函数:find_score()
功能:查询_分数,被find()调用,显示对应的分数信息
参数:Student*, StudentScore*,m(学生信息条数),n(分数信息条数)
*/
void find_score(Student* stu, StudentScore* stu_score, int m, int n)
{
cout << "输入该学生的学号:";
int id;
cin >> id;
bool flag_find_id = false;
for (int i = 0; i < m; i++)
{
if (id == stu[i].ID)
{
flag_find_id = true;
cout << "\t\t\t\t学号: "<<std::setiosflags(std::ios::left)
<<std::setw(10)<< stu[i].ID << "姓名: "
<<std::setw(10)<< stu[i].name;
break;
}
if (i == m - 1 && !flag_find_id)
{
cout << "\n\t\t此ID学生信息记录不存在\n";
}
}
bool flag_find_score = false;
int lesson_n = 0;
double all_credit = 0;
for (int i = 0; i < n; i++)
{
if (id == stu_score[i].ID)
{
flag_find_score = true;
cout << "\n" << stu_score[i];
lesson_n++;
all_credit += stu_score[i].actual_score;
}
if (i == n - 1 && !flag_find_score)
{
cout << "\n\t\t此ID成绩记录不存在\n";
}
}
cout << "\n\t\t共修: " << lesson_n << "科,实得总学分为: " << all_credit;
}
/*
函数:delete_by_ID()
功能:删除和ID相关的信息
返回值:0
*/
int delete_by_ID(Student * stu, StudentScore * stu_score, int &m, int &n)
{
cout << "删除该学号的所有相关信息:\n输入学号:";
int ID;
cin >> ID;
//删除ID相关的学生基本信息
for (int i = 0; i < m; i++)
{
if (stu[i].ID == ID)
{
int k = i;
if (k == m - 1)
{
stu[i] = Student(); //使其为空
m--;
}
else
{
for (int j = k+1; j < m; j++)
{
stu[j-1] = stu[j];
}
m--;
}
}
}
//删除ID相关的成绩信息
for (int i = n-1; i >= 0; i--)
{
if (stu_score[i].ID == ID)
{
int k = i;
if (k == n - 1)
{
stu_score[i] = StudentScore(); //使其为空
n--;
}
else
{
for (int j = k + 1; j < n; j++)
{
stu_score[j - 1] = stu_score[j];
}
n--;
}
}
}
cout << "该学生所有相关信息删除成功\n";
return 0;
};
/*
函数:sort_score()
功能:按分数排序,(降序)。
参数:StudentScore*, n(成绩条数)
返回值:n(成绩条数)
*/
int sort_score(StudentScore * stu_score, int n)
{
int choice;
cout << "选择:1.按综合成绩排序 2.按实得学分排序";
cin >> choice;
switch (choice)
{
case 1:
{
StudentScore temp;
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (stu_score[j].total_score < stu_score[j + 1].total_score)
{
temp = stu_score[j];
stu_score[j] = stu_score[j+1];
stu_score[j + 1] = temp;
}
}
}
break;
}
case 2:
{
StudentScore temp;
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (stu_score[j].actual_score < stu_score[j + 1].actual_score)
{
temp = stu_score[j];
stu_score[j] = stu_score[j + 1];
stu_score[j + 1] = temp;
}
}
}
break;
}
}
for (int i = 0; i < n; i++)
{
cout<<"学号: "<<std::setiosflags(std::ios::left)<<std::setw(4)
<<stu_score[i].ID<<stu_score[i] << "\n";
}
return n;
};
/*
·File name: menu.cpp
·Description: 所有和菜单相关的操作。
*/
#include<iostream>
#include"student.h"
#include"func.h"
using std::cout;
using std::cin;
/*
函数:show_menu()
功能:显示主菜单
*/
void show_menu()
{
cout<<"############################\n";
cout<<" 学生信息管理系统\n"
<<" 选择功能\n"
<<"1.数据的录入和计算\n"
<<"2.查询功能\n"
<<"3.删除功能\n"
<<"4.排序功能\n"
<<"q.退出程序。\n";
}
/*
函数:choose_func
功能:读入选择,执行功能
返回:程序状态(运行ture,结束false)
*/
bool choose_func(char choice, bool & active,StudentScore * stu_score,Student * stu,
int & m, int& n )
{
switch(choice)
{
case '1' :
n = read_data_and_calcu(stu_score,n);
break;
case '2':
find( stu, stu_score,m, n);
break;
case '3':
delete_by_ID(stu, stu_score, m, n);
break;
case '4':
sort_score(stu_score, n);
break;
case 'q':
cout<<"quit~\n";
active = false;
break;
default:
cout << "无效输入\n";
}
return active;
}
/*
·File name: student.cpp
·Description: 学生类和成绩类的相关函数。
*/
#include"student.h"
/*
计算综合成绩,返回综合成绩。
传入参数: exp_score, exam_score, daily_score
返回值: total_score
*/
double calcu_total_score(int exp_score, int exam_score, int daily_score);
/*
计算实得学分,返回实得学分
传入参数: total_score, credit
返回值: actual_score
*/
double calcu_actual_score(double total_score, int credit);
//分数的默认构造函数,初始化ID = 0,分数为负数,表示无效成绩;
StudentScore::StudentScore() : ID(0),lesson_number("None"),lesson_name("None"),credit(-1),
daily_score(-1),exp_score(-1),exam_score(-1)
{
}
//分数的构造函数2,传入参数进行初始化,自动调用calcu_total_score,calcu_actual_score计算 综合成绩和实得学分
StudentScore::StudentScore(int m_ID, string m_lesson_number, string m_lesson_name, int m_credit,
int m_daily_score, int m_exp_score, int m_exam_score) : ID(m_ID),lesson_number(m_lesson_number),
lesson_name(m_lesson_name),credit(m_credit),daily_score(m_daily_score),
exp_score(m_exp_score),exam_score(m_exam_score)
{
total_score = calcu_total_score( m_exp_score, m_exam_score, m_daily_score);
actual_score = calcu_actual_score( total_score, m_credit);
}
//分数的析构函数,暂无工作要做
StudentScore::~StudentScore()
{
}
//分数的友元函数<<,用于显示
std::ostream& operator<<(std::ostream& os, const StudentScore& stu_score)
{
os << std::setiosflags(std::ios::left)
<<"课程编号: " <<std::setw(8)<< stu_score.lesson_number
<< "课程名称: "<<std::setw(12) << stu_score.lesson_name
<< "综合成绩: "<<std::setw(8) << stu_score.total_score
<< "实得学分: " << stu_score.actual_score;
return os;
}
//学生的默认构造函数,初始化0
Student::Student(): ID(0), name("None"), sex("None"), dor_number(0), phone(0)
{
}
//学生的析构函数,暂无工作要做
Student::~Student()
{
}
//学生的友元函数<< 用于打印输出.
std::ostream & operator<<(std::ostream & os, const Student& stu)
{
os <<std::setiosflags(std::ios::left)
<<std::setw(5)<< stu.ID
<<std::setw(8)<< stu.name
<< stu.sex << " " << stu.dor_number << " "
<< stu.phone;
return os;
}
// 计算实得学分
double calcu_actual_score(double total_score, int credit)
{
double actual_score;
int flag_total =total_score/10;
switch (flag_total)
{
case 10: case 9: actual_score = credit;
break;
case 8: actual_score = credit * 0.8;
break;
case 7: actual_score = credit * 0.75;
break;
case 6: actual_score = credit * 0.6;
break;
default: actual_score = 0;
break;
}
return actual_score ;
}
//计算综合成绩
double calcu_total_score(int exp_score, int exam_score, int daily_score)
{
double total_score;
if(exp_score == -1)
total_score = daily_score * 0.3 + exam_score * 0.7;
else
total_score = daily_score * 0.15 + exp_score * 0.15 + exam_score * 0.7;
return total_score;
}
/*
# File name: main.cpp
# Author: 一只大鸽子
# Date: 2018/9/10
# Description: 学生信息管理系统的主函数
*/
#include<iostream>
#include"menu.h"
#include"student.h"
#include"file.h"
//主函数main,程序入口
int main()
{
char choice = 0; //choice,让用户输入选择
bool active = true; //active,用来判断程序运行状态,true代表运行中,false代表结束
int m = 0; //学生基本信息 数量
int n = 0; //成绩信息 数量
read_record(m, n);//得到学生基本信息、成绩信息条数
Student * stu = new Student[m+10]; //学生数组stu,存储学生信息
StudentScore * stu_score = new StudentScore[n+400];//分数数组stu_score,存储成绩信息
read_to_stu(stu, m); //从student.txt读入数据到数组中
read_to_stu_score(stu_score, n); //从score.dat读入数据到数组中
//显示主菜单
show_menu();
//进入循环,用户选择菜单上的功能。直到active为false,程序即将结束时,退出循环
while(active)
{
std::cin>>choice;
choose_func(choice,active,stu_score,stu,m,n);
if(active)
show_menu();
}
/*
程序即将结束,将学生信息写入student.txt;将分数信息写入score.dat;
写入信息数量到record.txt中;
*/
save_stu(stu, m);
save_score(stu_score, n);
write_record(m, n);
//归还使用的内存
delete[] stu;
delete[] stu_score;
system("pause"); //暂停
return 0;
}
小结:
这是我的第一个C++实践程序,写了大概有两三天。
中间遇到一些问题,比如文件读写,格式输出。。。。。。第一次运行时还有一些奇奇怪怪的问题。比如stackoverflow...
最后还是通过看书和百度解决了。
总结一点经验:
1.变量和函数的命名很重要,一定要清晰易懂,一看到这个名字就知道它是干什么的,不要随便起 a,b,c或者fun1,fun2之类的名字。
2.注释很重要
3.代码格式很重要(对齐缩进)
4.不要自己钻到一个问题里就不出来了,很浪费时间。 比如排序功能可能你一下子想不出来,就可以上网搜搜(c++排序),
借鉴一下。如果找不到,也不要一直纠结,先空着,过一会可能就想到了。
5.代码重构。当你代码写着写着感觉某个函数太长了,或者感觉一些功能可以提取出来,就可以把某个功能做成函数。
6..注意身体,注意休息,喝水。最好能定时休息。