计算学生成绩,程序的组织,对程序进行模块化。本文我将对上次程序进行进阶(上次程序http://t.csdn.cn/K9iP2)
由于我只是个初学者,所以我写了多个头文件和源文件分别代表不同的功能
首先第一个头文件是student_info.h,是对读入成绩的函数的声明
student_info.h
#ifndef STUDENT_INFO_H_INCLUDED
#define STUDENT_INFO_H_INCLUDED
#include <iostream>
#include <string>
#include <vector>
struct Student_info
{
std::string name;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif
首先第一个源文件student_info.cpp,读入学生成绩,包括期中成绩,期末成绩,家庭作业成绩。
student_info.cpp
#include"Student_info.h"
using std::istream;
using std::vector;
using std::endl;
using std::cout;
bool compare(const Student_info& x, const Student_info& y)//将输入的信息按首字母顺序排序
{
return x.name < y.name;
}
istream& read(istream& is, Student_info& s)
{
// 读并存储学生的姓名以及期中,期末,家庭作业的成绩
cout << "input name midterm final :" << endl;
is >> s.name >> s.midterm >> s.final;
cout << "homework" << endl;
read_hw(is, s.homework);
cout << "next"<<endl;
// 读并记录所有的学生的家庭作业成绩
return is;
}
//将家庭作业读到向量中
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
// 将向量hw内存储的个数设置为0
hw.clear();
double x;
//cout << "输入家庭作业成绩:" << endl;
while (in >> x)
hw.push_back(x);
//in.sync();//清空流
in.clear();//将流中的所有状态值都重设为有效值
//in.sync();//清空流
}
return in;
}
注意:此处如果采用vs2019编译器进行编译那么在主函数中结束cin得输入就不能在采用输入一个与定义得数据类型不同得数据来结束输入,因为这样得结束方式与in.clear()函数不能搭配使用,而要采用换行后ctrl+z结束输入。
第二个头文件是grade.h,是对计算成绩的函数的声名
grade.h
#ifndef STUDENT_ccccc
#define STUDENT_ccccc
#include <vector>
#include "Student_info.h"
using namespace std;
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
double grade(const Student_info&);
#endif
第二个源文件是grade.cpp,是具体的计算学生的成绩的函数
grade.cpp
#include <vector>
#include "grade.h"
#include "medain.h"
#include <stdexcept>
using std::domain_error;
using std::vector;
using std::string;
/*重构*/
double grade(double Midterm, double Final, double homework)
{
return 0.2 * Midterm + 0.4 * Final + 0.4 * homework;//返回总成绩
}
double grade(double Midterm, double Final, const vector<double>& hw)
{
if (hw.size() == 0)
throw domain_error("student has done no homework");
return grade(Midterm, Final, median(hw));//这个grade调用第一个grade,返回总成绩
}
double grade(const Student_info& s)
{
return grade(s.midterm, s.final, s.homework);
}
第三个头文件是median.h,是对家庭作业成绩求中值得函数(这里我们把多次家庭作业得中值作为最终得家庭作业成绩)。
median.h
#ifndef STUDENT_aaaaa
#define STUDENT_aaaaa
#include<vector>
using namespace std;
double median(std::vector<double>);
#endif
第三个源文件是median.cpp,是对求家庭作业成绩得函数得具体
median.cpp
#include <algorithm> // 获得排序的宣言sort
#include <stdexcept> // 获得域错误的声明
#include <vector> // 获得vector的声明
#include"medain.h"
#include<iostream>
// compute the median of a vector<double>
/* 计算中值*/
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;//定义vector<double>::size_type类型的替代名为vec_sz
vec_sz Size = vec.size();//定义vec_sz类型的Size并令他等于vec的大小
if (Size == 0)
{
throw domain_error("median of an empty vector");//
}
sort(vec.begin(), vec.end());//进行排序
vec_sz mid = Size / 2;//定义vec_sz类型的mid
return Size % 2 == 0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];//三元运算
}
最后就是主函数test.3s.cpp
#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include "grade.h"
#include "Student_info.h"
#include "medain.h"
using std::cin; using std::setprecision;
using std::cout; using std::sort;
using std::domain_error; using std::streamsize;
using std::endl; using std::string;
using std::max; using std::vector;
int main()
{
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
// maxlen 包含学生中最长的名称的长度
while (read(cin, record))
{
// 找最长名字的长度
maxlen = max(maxlen, record.name.size());
students.push_back(record);
}
// 按名字首字母字母顺序排列学生生记录
sort(students.begin(), students.end(), compare);
// write the names and grades
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i)
{
// 写下名称,在右侧填充到最大长度 + 1 个字符
cout << students[i].name << string(maxlen + 1 - students[i].name.size(), ' ');
// 计算并写入成绩,try为检查,检查函数,catch为捕捉
try {
double final_grade = grade(students[i]);
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade << setprecision(prec);
}
catch (domain_error e) //捕捉到错误,则输出错误原因
{
cout << e.what();
}
cout << endl;
}
return 0;
}
运行结果如下
输出得名字成绩一一对齐,名字按照首字母顺序排列。
本文得目的只是记录自己得学习过程,初学者一个,若有错我请大佬指正。