《Accelerated C++中文版》学习配套编程(一)

《Accelerated C++中文版》学习配套编程(一)

本书的第三章中,我们看到很多处理批量数据的方法,通过编写一个程序,读取学生的考试和家庭作业成绩,并且计算出一个最终的成绩。并且在这个过程中,我们还学习了如何储存所有数据,即使我们开始并不知道有多少成绩需要储存。
第四章中,提供了两个来组织大型程序的基本办法:函数(有时候我们叫子程序)和数据结构。
通过第三章和第四章的学习,我们将书本中的程序进行汇总,可得到一个完整的学生成绩统计与计算的小程序,下面我简单讲所学所编进行记录:

1.grade.cpp

#include <stdexcept>
#include <vector>
#include "grade.h"
#include "median.h"
#include "Student_info.h"

using namespace std;
//重载就是函数名相同,但是由于形参不同,所以机器分别的出来
//用方法1计算最终个人成绩
double grade(double midterm, double final, double homework)
{
    return 0.2*midterm + 0.4*final + 0.4*homework;
}

//如果没有家庭作业成绩就报警,再用方法2(家庭成绩取中值)计算个人最终成绩
//该函数的形参需要注意四点
//1.const vector<double>& hw   该形参的类型是vector<double>,所以对应的实参也必须是这个类型的
//2.double final               当调用grade函数时,对应double final的实参对象就会被复制到 final 中,
//                             而不会改变原来的实参double对象
//3.const vector<double>& hw   注意 & 的这个东西,& 是用做别名(引用)的意思,这时候就不同于第二点(复制),
//                             这里不复制,直接用实参对象,并且能够改变实参内容
//4.const vector<double>& hw   注意 const ,这又不同于第三点,这个时候函数的形参也是直接用实参,但是不能改变其内容
double grade(double midterm, double final, const vector<double>& hw)
{
    if (hw.size() == 0)
        throw domain_error("学生没有家庭作业成绩");
    return grade(midterm, final, median(hw));
}


//利用Student_info这个结构,返回函数grade(方法2)计算的值
double grade(const Student_info& s)
{
    return grade(s.midterm, s.final, s.homework);
}

2.median.cpp

#include "median.h"
#include <vector>
#include <algorithm>
#include <stdexcept>//包含异常类 domain_error

using namespace std;

//中间排序函数,用来找到中间值

//当调用median函数时,用作实参的vector对象就会被复制到vec中,从而不会改变原来的实参vector对象
double median(vector<double> vec)
{
    typedef vector<double>::size_type vec_sz;

    vec_sz size = vec.size();
    if (size == 0)
        throw domain_error("是一个空数据");
    //如果size为0,则会抛出一个异常throw,终止当前函数,并进行错误提示。这次抛出的异常是 domain_error。
    sort(vec.begin(), vec.end());//排序函数,比较的元素类型必须要相同
    vec_sz mid = size / 2; 
    return size % 2 == 0 ? (vec[mid] + vec[mid + 1]) / 2 : vec[mid];//判断时偶数还是奇数,并最后返回一个中间值
}

3.Student_info.cpp

#include "Student_info.h"  //引用Student_info.h头文件

using namespace std;

//比较Student_info结构中name的大小,返回一个bool值,为sort()函数排序当参数用的
 bool compare(const Student_info& x, const Student_info& y)
{
    return x.name < y.name;
}

//用于程序输入姓名,期中,期末考试和家庭成绩
istream& read(istream& is, Student_info& s)
{
    is >> s.name >> s.midterm >> s.final;
    cout << "读取家庭成绩" << endl;
    //注意在读取家庭作业时,由于read_hw内使用的while 来收集某个同学家庭成绩的,所以需要用ctrl+z来跳出某个同学的家庭作业循环
    read_hw(is,s.homework);
    return is;
}

//用于程序输入家庭成绩
//这里多讲几句
//1.首先read_hw函数中有两个形参,均因为&引用,所以都直接用的是实参的内容(不复制,可改内容)
//2.其次,形参istream& in 为什么要用引用,因为从标准输入文件中读取会改变文件的状态,所以也要改变cin的值
//3.最后read_hw函数返回的是形参 in ,而且形参还是一个引用,也就是说,调用程序给read_hw函数一个对象,最后返回同一个对象。
istream& read_hw(istream& in, vector<double>& hw)
{
    if (in){
        hw.clear();//因为不清楚定义vector类的hw时里面有没有其他值,所以先清除一下hw
        double x;
        while (in>>x)
            hw.push_back(x);//push_back成员用于将x值压入hw(vector)中,且hw(vector)的数量+1
        in.clear();//因为可能我们输入的不是成绩,可能错误的敲了一个字母,这时候会结束我们的程序,
                       //而这时候的in(istream类)的clear就会把错误清除,恢复正常读取过程,
                     //而且不用这个清除函数的话,会影响后面的结构体的输入
        }  
   
    return in;
}

4.主程序

#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include "grade.h"
#include "Student_info.h"

using namespace std;

int main()
{
    vector<Student_info> students;
    Student_info record;
    string::size_type maxlen = 0;
    int k = 1;
    cout << "请输入第" << k << "个同学的信息" << endl;
    while (read(cin,record))
    {
        
        maxlen = max(maxlen, record.name.size());
        k++;
        students.push_back(record);
        cout << "请输入第" << k << "个同学的信息" << endl;
    }

    sort(students.begin(), students.end(),compare);
    //不要忘记begin后面的括号
    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 = grade(students[i]);
          //double final_grade = grade(students[i].midterm, students[i].final, students[i].homework);
            streamsize prec = cout.precision();
            cout << setprecision(3) << final_grade << setprecision(prec);
        }
        catch (domain_error e)
        {
            cout << e.what();
        }
        cout << endl;
    }
    system("pause");   //如果没有这个,控制台就直接跳出,不会停留
    return 0;

}

已经打包上传,可见:https://download.csdn.net/download/baidu_38346905/19114932

上一篇:android访问应用程序第2步:实现hal层


下一篇:php添加excel更新数据表数据