文章目录
- 1 编译运行本章的程序
- 2 重写Student_info类,使它在读学生记录时计算成绩,并将成绩存储在对象中。重新实现garde函数,让它使用这个预计算的值。
- 3 将name函数定义成一个简单、非常量的成员函数,其他函数该如何改动?
- 3 捕获当未读入Student_ingo对象的值而调用grade函数引发的异常
- 4 使用vail函数避免异常发生
- 5 编写一个类和相关函数为学生产生成绩,pass及格/fail不及格。假设只根据学生的期中和期末的平均个成绩计算,按字母顺序输出学生,成绩用P或F表示。
- 6 为及格和不及格的学生重新编写计算成绩的程序,输出时首先显示全部及格的学生,然后输出不及格的学生。
- 7 把read_w不能被公共访问
1 编译运行本章的程序
头文件:
Student_info.h
//
// Created by MacBook Pro on 2020-01-13.
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
//struct student_info{
// std::string name;
// double midterm, final;
// std::vector<double> homework;
//
// std::istream& read(std::istream&);
// double garde() const;
//};
class Student_info{
public:
Student_info();//构造一个空的Student_info对象
Student_info(std::istream&);//读一个流从而构造一个对象
bool vaild() const{ return ! homework.empty();}//检查对象是否为空
double grade() const;
std::istream& read(std::istream& );
std::string name() const {return n;}//存取器:容许对一部分数据结构的进行访问
private:
std::string n;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
//std::istream& read(std::istream&, Student_info&);
#endif
grade.h
//
// Created by MacBook Pro on 2020-01-13.
//
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
//double grade(const Student_info&);
#endif
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :midterm(0), final(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
bool compare(const Student_info& x, const Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
in >> n >> midterm >> final;
read_hw(in, homework);
return in;
}
istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
double Student_info::grade() const {
//::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
return ::grade(midterm, final, 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));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
int main(int argc, char const *argv[]){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(record.read(cin)){//
maxlen = max(maxlen, record.name().size());//
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()//
<<string(maxlen + 1 - students[i].name().size(), ' ');
// try{
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }catch(domain_error e){
// cout << e.what() << endl;
// }
if(students[i].vaild() == true){
double final_grade = students[i].grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << endl;
}else{
cout << "homework is empty!"<< endl;
}
}
return 0;
}
2 重写Student_info类,使它在读学生记录时计算成绩,并将成绩存储在对象中。重新实现garde函数,让它使用这个预计算的值。
头文件:
//
// Created by MacBook Pro on 2020-01-13.
//
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
//double grade(const Student_info&);
#endif
//
// Created by MacBook Pro on 2020-01-13.
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
//struct student_info{
// std::string name;
// double midterm, final;
// std::vector<double> homework;
//
// std::istream& read(std::istream&);
// double garde() const;
//};
class Student_info{
public:
Student_info();//构造一个空的Student_info对象
Student_info(std::istream&);//读一个流从而构造一个对象
// bool vaild() const{ return ! homework.empty();}//检查对象是否为空
double grade() const { return final_grade;}//存取器函数
std::istream& read(std::istream& );
std::string name() const {return n;}//存取器:容许对一部分数据结构的进行访问
private:
std::string n;
double final_grade;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
//std::istream& read(std::istream&, Student_info&);
#endif
主函数:
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :final_grade(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
bool compare(const Student_info& x, const Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
try {
double midterm, final;
vector<double> homework;
in >> n >> midterm >> final;
read_hw(in, homework);
final_grade = ::grade(midterm, final, homework);
}catch (domain_error e){//检测homework是否为空
cout << e.what() << endl;
}
return in;
}
istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
//double Student_info::grade() const {
// //::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
// return ::grade(midterm, final, 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));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
int main(int argc, char const *argv[]){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(record.read(cin)){//
maxlen = max(maxlen, record.name().size());//
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()//
<<string(maxlen + 1 - students[i].name().size(), ' ');
// try{
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }catch(domain_error e){
// cout << e.what() << endl;
// }
// if(students[i].vaild() == true){
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }else{
// cout << "homework is empty!"<< endl;
// }
// }
try {
double final_grade = students[i].grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << endl;
}catch (domain_error e){
cout << e.what() << endl;
}
}
return 0;
}
3 将name函数定义成一个简单、非常量的成员函数,其他函数该如何改动?
not constant objects can’t access functions that are not defined as constant
非常量对象无法访问未定义的常量的函数。
也就是非常量的成员无法被非成员的常量函数访问。
(如果将一个非常量对象传递给一个具有常量引用参数的函数,这个函数就会将这个对象当常量进行处理,编译器将只允许它调用这个对象的常量成员。)
总结来说,就是非常量非成员函数可以访问常量和非常量类成员,但是常量非成员函数只可以访问常量类成员函数。
头文件:
//
// grade.h
//
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
//double grade(const Student_info&);
#endif
//
// Student_info.h
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
//struct student_info{
// std::string name;
// double midterm, final;
// std::vector<double> homework;
//
// std::istream& read(std::istream&);
// double garde() const;
//};
class Student_info{
public:
Student_info();//构造一个空的Student_info对象
Student_info(std::istream&);//读一个流从而构造一个对象
// bool vaild() const{ return ! homework.empty();}//检查对象是否为空
double grade() const { return final_grade;}//存取器函数
std::istream& read(std::istream& );
//修改
std::string name() {return n;}//存取器:容许对一部分数据结构的进行访问
private:
std::string n;
double final_grade;
};
//bool compare(Student_info&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
//std::istream& read(std::istream&, Student_info&);
#endif
主函数:
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :final_grade(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
//修改
bool compare(Student_info& x, Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
try {
double midterm, final;
vector<double> homework;
in >> n >> midterm >> final;
read_hw(in, homework);
final_grade = ::grade(midterm, final, homework);
}catch (domain_error e){//检测homework是否为空
cout << e.what() << endl;
}
return in;
}
istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
//double Student_info::grade() const {
// //::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
// return ::grade(midterm, final, 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));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
int main(int argc, char const *argv[]){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(record.read(cin)){//
maxlen = max(maxlen, record.name().size());//
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()//
<<string(maxlen + 1 - students[i].name().size(), ' ');
// try{
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }catch(domain_error e){
// cout << e.what() << endl;
// }
// if(students[i].vaild() == true){
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }else{
// cout << "homework is empty!"<< endl;
// }
// }
try {
double final_grade = students[i].grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << endl;
}catch (domain_error e){
cout << e.what() << endl;
}
}
return 0;
}
3 捕获当未读入Student_ingo对象的值而调用grade函数引发的异常
//
// grade.h
//
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
//double grade(const Student_info&);
#endif
//
// Student_info.h
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
//struct student_info{
// std::string name;
// double midterm, final;
// std::vector<double> homework;
//
// std::istream& read(std::istream&);
// double garde() const;
//};
class Student_info{
public:
Student_info();//构造一个空的Student_info对象
Student_info(std::istream&);//读一个流从而构造一个对象
bool vaild() const{ return ! homework.empty();}//检查对象是否为空
double grade() const;
std::istream& read(std::istream& );
std::string name() const {return n;}//存取器:容许对一部分数据结构的进行访问
private:
std::string n;
double midterm, final;
std::vector<double> homework;
};
//bool compare(Student_info&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
//std::istream& read(std::istream&, Student_info&);
#endif
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
#include <exception>
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :midterm(0), final(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
bool compare(const Student_info& x, const Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
in >> n >> midterm >> final;
read_hw(in, homework);
return in;
}
istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
double Student_info::grade() const {
//::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
return ::grade(midterm, final, 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));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
int main(int argc, char const *argv[]){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
try {
record.grade();
}catch (std::exception e){
cout << e.what();
}
return 0;
}
4 使用vail函数避免异常发生
头文件同三
源文件:
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :midterm(0), final(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
bool compare(const Student_info& x, const Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
in >> n >> midterm >> final;
read_hw(in, homework);
return in;
}
istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
double Student_info::grade() const {
//::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
return ::grade(midterm, final, 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));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
int main(int argc, char const *argv[]){
Student_info record;
if(record.vaild()){
record.grade();
}else{
cout << "Invalid student input!"<< endl;
}
return 0;
}
5 编写一个类和相关函数为学生产生成绩,pass及格/fail不及格。假设只根据学生的期中和期末的平均个成绩计算,按字母顺序输出学生,成绩用P或F表示。
//
// Student_info.h
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
class Student_info{
public:
Student_info();
Student_info(std::istream&);
std::string name()const{ return n;}
std::istream& read(std::istream&);
char grade() const;
private:
std::string n;
double mid, final;
};
#endif
#include <iostream>
using std::cin; using std::cout;
using std::endl;
using std::istream;
#include <string>
using std::string;
#include "Student_info.h"
#include <stdexcept>
using std::domain_error;
#include <vector>
using std::vector;
#include <algorithm>
using std::max;
using std::sort;
Student_info::Student_info():mid(0), final(0){}
Student_info::Student_info(istream& is){ read(is); }
istream& Student_info::read(std::istream& in) {
in >> n >> mid >> final;
return in;
}
char Student_info::grade() const{
if(mid == 0 || final == 0){
throw domain_error("Grade is empty!");
}
double final_grade = (mid + final) /2;
if(final_grade >= 60){
return 'P';
}else{
return 'F';
}
}
bool cmp(const Student_info& a, const Student_info& b){
return a.name() < b.name();
}
int main(int argc, char **argv){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(record.read(cin)){
maxlen = max(maxlen, record.name().size());
students.push_back(record);
}
sort(students.begin(), students.end(), cmp);
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()
<< string(maxlen + 1 - students[i].name().size(),' ');
try{
char final_grade = students[i].grade();
cout << final_grade << endl;
}catch (domain_error e){
cout << e.what() <<endl;
}
}
return 0;
}
6 为及格和不及格的学生重新编写计算成绩的程序,输出时首先显示全部及格的学生,然后输出不及格的学生。
//
// Student_info.h
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
class Student_info{
public:
Student_info():mid(0),final(0){ }
Student_info(std::istream& is){ read(is);}
std::string name()const{ return n;}
std::istream& read(std::istream&);
double grade() const { return (mid + final)/2;}
bool passing () const { return grade() >= 60;}
private:
std::string n;
double mid, final;
};
class Sore{
public:
//构造函数
Sore():maxlen(0){}
Sore(std::istream& is);
//输出成绩报告
std::ostream& generate_report(std::ostream&);
private:
std::vector<Student_info> students;
//分区域输出
std::ostream& generate_report(std::ostream&,
std::vector<Student_info>::const_iterator,
std::vector<Student_info>::const_iterator);
string::size_type maxlen;//记录最长名字的长度
};
bool cmp(const Student_info& , const Student_info&);
#endif
#include <iostream>
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::ostream;
#include <string>
using std::string;
#include "Student_info.h"
#include <stdexcept>
using std::domain_error;
#include <vector>
using std::vector;
#include <algorithm>
using std::max;
using std::sort;
using std::stable_partition;
bool cmp(const Student_info& a, const Student_info& b){
return a.name() < b.name();
}
bool passing(const Student_info s){
return s.passing();
}
istream& Student_info::read(std::istream& in) {
in >> n >> mid >> final;
return in;
}
Sore::Sore(istream &is) {
Student_info record;
maxlen = 0;
while(record.read(cin)){
students.push_back(record);
maxlen = (maxlen, record.name().size());
}
sort(students.begin(), students.end(), cmp);
}
ostream& Sore::generate_report(std::ostream& os){
const vector<Student_info>::iterator iter = stable_partition(students.begin(), students.end(), passing);
generate_report(os, students.begin(), iter);
generate_report(os, iter, students.end());
}
std::ostream& Sore::generate_report(std::ostream& os,
std::vector<Student_info>::const_iterator begin,std::vector<Student_info>::const_iterator end){
while(begin != end){
os << begin->name()
<< string(maxlen + 1 - begin->name().size(), ' ')
<< (begin->passing() ? 'P' : 'F')
<< endl;
begin++;
}
return os;
}
int main(int argc, char **argv){
Sore g = Sore(cin);
g.generate_report(cout);
return 0;
}
7 把read_w不能被公共访问
把它写成类私有成员。
//
// tudent_info.h
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
//struct student_info{
// std::string name;
// double midterm, final;
// std::vector<double> homework;
//
// std::istream& read(std::istream&);
// double garde() const;
//};
class Student_info{
public:
Student_info();//构造一个空的Student_info对象
Student_info(std::istream&);//读一个流从而构造一个对象
bool vaild() const{ return ! homework.empty();}//检查对象是否为空
double grade() const;
std::istream& read(std::istream& );
std::istream& read_hw(std::istream& );//改变
std::string name() const {return n;}//存取器:容许对一部分数据结构的进行访问
private:
std::string n;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
//std::istream& read(std::istream&, Student_info&);
#endif
//
// grade.h
//
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
//double grade(const Student_info&);
#endif
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :midterm(0), final(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
bool compare(const Student_info& x, const Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
in >> n >> midterm >> final;
read_hw(in);//改变
return in;
}
//改变
istream& Student_info::read_hw(istream& in){
if(in){
in.clear();
double x;
while(in >> x){
homework.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
double Student_info::grade() const {
//::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
return ::grade(midterm, final, 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));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
int main(int argc, char const *argv[]){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(record.read(cin)){//
maxlen = max(maxlen, record.name().size());//
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()//
<<string(maxlen + 1 - students[i].name().size(), ' ');
// try{
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }catch(domain_error e){
// cout << e.what() << endl;
// }
if(students[i].vaild() == true){
double final_grade = students[i].grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << endl;
}else{
cout << "homework is empty!"<< endl;
}
}
return 0;
}