//计算学生成绩
//版本1:
#include<iostream>
#include<string>
#include<iomanip> //定义了控制器setprecision,这个控制器允许我们指明输出所包含的有效位数。
#include<ios> //定义了一个类型streamsize,输入/输出库就是用这个类型来表示长度的。
using namespace std;
int main(){
//请求输入并读入学生的姓名
cout << "Please enter your first name: ";
string name;
cin >> name;
cout << "Hello, "<< name <<" ! " << endl;
//请求输入并读入期中和期末成绩
cout << "Please enter your midterm and final exam grades: ";
double midterm , final;
cin >> midterm >> final;
//请求输入家庭作业成绩
cout << "Please enter your homework grades, "
"followed by end_of_file: ";
//到目前为止,读到的家庭作业成绩的个数及总和
int count = 0;
double sum = 0;
//将家庭作业成绩读到变量x中
double x;
//不变式
//到目前为止,我们已经读到了count个家庭作业成绩
//而且sum等于头count个成绩的总和
while(cin >>x){
++count;
sum+=x;
}
//输出结果
streamsize prec = cout.precision();
cout << "Your final grade is " <<setprecision(3)
<<0.2*midterm + 0.4*final + 0.4*sum/count
<<setprecision(prec) << endl;
return 0;
}
//用中值代替平均值
//版本2:
//原来的程序部分
int count = 0;
double sum = 0;
double x;
//不变式:
//到目前为止,我们已经读入了count个家庭作业成绩
//sum计算家庭作业成绩的总和
while(cin>>x){
sum+=x;
count++;
}
*/
/*计算中值需要解决的问题:
1.存储大量的数值,将每次读取一个数值,而且在读数值的时候我们并不会预先知道数值的个数
2.读取了所有的数值之后对他们进行排序。
3.高效获取中间的一个或两个数值。
*/
//标准库提供了一种名为vector(向量)的类型,我们可以使用这种类型非常轻松地解决左右这些问题
//vector保存了一系列具有特定类型的数值,它的大小可根据需要增长以容纳添加的数值,还可让我们高效地访问每一个独立的数值。
//修改版本:
double x;
vector<double> homework;
//不变式:到目前为止,homework包含了所有读到的家庭作业成绩
while(cin>>x){
homework.push_back(x);
}
//这里的push_back就像greeting_size()一样,是一个成员函数,其作用是添加一个新的元素到向量的末尾,它会给新元素一个值,这个值
//就是我们传递给它的那个参数。因此,push_back会将它的参数压进尾部,但副作用是它会将向量的长度加1。
//原来程序部分
streamsize prec = cout.precision();
cout << "Your final grade is " <<setprecison(3)
<< 0.2 * midterm +0.4 * final + 0.4 * sum / count
<< setprecision(prec) << endl;
//为了找出中值,我们至少要在两个地方得到向量homework的长度:
// 1.检测长度是否为0;
// 2.计算中间元素的位置。
//如果我们将长度存储在一个变量中,就不必两次计算长度了
typedef vector<double>::size_type vec_sz;
vec_sz size = homework.size();
//vector类型定义了一个名为vector<double>::size_type的类型和一个名为size的函数。这些成员的操作方式和string类型中的相似:类型
//size_type是一个unsigned类型,它必须大到可以用于保存向量可能容纳的最大长度;size()则返回一个size_type类型的值,我们使用
//该值表示向量中的元素个数。
//由此,我们要养成使用库定义的size_type表示容器的长度的良好的编程习惯
//检测是否有输入的数据
if(size==0){
cout << "You must enter your grades. "
"Please enter again. " << endl;
return 1;
}
//对数据进行排列,为此我们要调用一个库函数:
sort(homework.begin(),homework.end());
//对homework进行排序后,就要找出一个或者两个中间元素
vec_sz mid = size / 2;
double median;
median = size %2 == 0 ? (homework[mid] + homework[mid+1])/2 : homework[mid] ;
//得到了中值,最后是计算和输出结果
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3)
<< 0.2*midterm + 0.4*final + 0.4*median
<< setprecision(prec) << endl;
//版本2完整程序
#include<string>
#include<iomanip>
#include<ios>
#include<algorithm>
#include<iostream>
#include<vector>
using std::string;
using std::cout;
using std::cin;
using std::sort;
using std::endl;
using std::vector;
using std::streamsize;
using std::setprecision;
int main(){
//请求输入名字
cout << "Please enter your name: "
string name;
cin >> name;
cout<< "Hello, "<< name <<" ! ";
//请求输入期中和期末成绩
cout << "Please enter your midterm and final exam grades: ";
double midterm,final;
cin >> midterm >> final;
//请求输入家庭作业成绩
cout >> "Enter all your homework grades, "
"Followed by end-of-file: ";
vector<double> homework;
double x;
//不变式:homework包含所有的家庭作业成绩
while(cin >> x)
homework.push_back(x);
//检测homework是否为空
typedef vector<double>::size_type vec_sz;
vec_sz size = homework.size();
if(size == 0){
cout << "You must enter your grades. "
"Please try enter again."<<endl;
return 1;
}
//对成绩进行排序
sort(homework.begin(),homework.end());
//就算家庭作业的中值
vec_sz mid = mid/2;
double median;
median = size%2==0 ? (homework[mid]+homework[mid+1])/2 : homework[mid];
//计算并输出总成绩
streamsize prec = cout.precision();
cout << "Your final grades is " << setprecision(3)
<< 0.2 * midterm + 0.4 * final + 0.4 * median
<< setprecision(prec) << endl;
return 0;
}