【C++】Accelerated C++(4)

185 阅读3分钟

1. 计算单个学生的总成绩

读入某个学生的姓名,某门课的期中考试成绩、期末考试成绩和平时作业成绩

期中占20%,期末占40%,平时的中位数占40%

求该学生的该门课的总成绩

头文件和对应的using声明

#include <iostream>
#include <iomanip>
#include <ios>
using std::cin;
using std::cout;
using std::endl;
using std::istream;	
using std::streamsize;   // 和输出格式有关
using std::setprecision; // 和输出格式有关

#include <string>
#include <vector>
using std::string;
using std::vector;

#include <stdexcept>
using std::domain_error;	// 一种异常

#include <algorithm>
using std::sort;

函数声明与重载

void read_hw(istream &, vector<double> &);

double grade(double, double, double);  // 第三个double是通过Median算出的平时中位数

double grade(double, double, const vector<double> &);  

double Median(vector<double>);

main函数第一部分:读入数据

    string name;
    double Final, midterm, hw_median;
    vector<double> homework;

    cout << "Please enter your first name: ";
    cin >> name;
    cout << "Hello, " << name << '!' << endl;

    cout << "Please enter your midterm and final exam grades: ";
    cin >> midterm >> Final;

    cout << "Enter all your homework grades, "
        "followed by end-of-file: ";
    read_hw(cin, homework);

main函数第二部分:计算学生成绩

    try
    {
        double final_grade = grade(midterm, Final, homework);
        streamsize prec = cout.precision();
        cout << "Your final grade is " << setprecision(3)
             << final_grade << setprecision(prec) << endl;
    }
    catch (domain_error)
    {
        cout << endl
             << "You must enter your grades."
                "Please try again."
             << endl;
        return 1;
    }
    return 0;

read_hw函数

void read_hw(istream &in, vector<double> &hw)
{
    if (in)
    {
        hw.clear();
        double x;
        // 到达文件末尾或碰到非double就退出
        while (in >> x)
            hw.push_back(x);
        // 不是清除流的意思!后面有解释
        in.clear();
    }
}

grade函数

double grade(double midterm, double Final, double median)
{
    return 0.2 * midterm + 0.4 * Final + 0.4 * median;
}

double grade(double midterm, double Final, const vector<double> &hw)
{
    return grade(midterm, Final, Median(hw));
}

Median函数

double Median(vector<double> hw)
{
    typedef string::size_type vec_sz;
    vec_sz size = hw.size();
    if (size == 0)
    {
        throw domain_error("student has done no homework.");
    }
    int mid = size / 2;
    sort(hw.begin(), hw.end());
    return size % 2 == 0 ? (hw[mid] + hw[mid - 1]) / 2 : hw[mid];
}

2. 计算每个学生的总成绩

文件格式
第一个是期中,第二个是期末,其余平时
Smith	   93  91  47  90  92  73  100  87
Carpenter  75  90  87  92  93  60  0    98
    
输出
按名字字典序排序,计算总成绩
Carpenter  		86.8
Smith			90.4

头文件1:Student_info.h

头文件

#ifndef GUARD_Student_info
#define GUARD_Student_info

#include <string>
#include <vector>
#include <iostream>

/* ... */

#endif

学生信息结构体

  • 学生名字
  • 期中、期末成绩
  • 平时成绩

结构体需要在声明用到结构体的函数前面

struct Student_info
{
    std::string name;
    double midterm, fin;
    std::vector<double> homework;
};

compare函数

对学生名字按字典序排列

bool compare(const Student_info &x, const Student_info &y)
{
    return x.name < y.name;
}

读入数据

read函数返回值类型不能为void,因为要利用它作循环条件给出布尔值

std::istream &read(std::istream &, Student_info &);  
void read_hw(std::istream &, std::vector<double> &);

std::istream &read(std::istream &in, Student_info &record)
{
    in >> record.name >> record.midterm >> record.fin;
    read_hw(in, record.homework);
    return in;
}

void read_hw(std::istream &in, std::vector<double> &hw)
{
    if (in)
    {
        hw.clear();
        double x;
        while (in >> x)
            hw.push_back(x);
        in.clear();
    }
}

头文件2:median.h

#ifndef GUARD_median_h
#define GUARD_median_h

#include <vector>
#include <algorithm>
#include <stdexcept>

double median(std::vector<double> hw)
{
    typedef std::vector<double>::size_type vec_sz;
    vec_sz size = hw.size();
    if (size == 0)
        throw std::domain_error("Student has no homework!");
    std::sort(hw.begin(), hw.end());
    int mid = size / 2;
    return size % 2 == 0 ? (hw[mid] + hw[mid - 1]) / 2 : hw[mid];
}

#endif

头文件3:grade.h

三个重载函数,层层深入

#ifndef GUARD_grade_h
#define GUARD_grade_h

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

double grade(const Student_info &);
double grade(double, double, const std::vector<double> &);
double grade(double, double, double);

double grade(const Student_info &student)
{
    return grade(student.midterm, student.fin, student.homework);
}

double grade(double midterm, double fin, const std::vector<double> &hw)
{
    return grade(midterm, fin, median(hw));
}

double grade(double midterm, double fin, double med)
{
    return 0.2 * midterm + 0.4 * fin + 0.4 * med;
}

#endif

源文件

include 和 using

#include <iostream>
#include <iomanip>
#include <ios>
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::setprecision;
using std::streamsize;

#include <string>
#include <vector>
using std::string;
using std::vector;

#include <stdexcept>
using std::domain_error;

#include <algorithm>
using std::max;
using std::sort;

#include "grade.h"
#include "Student_info.h"
#include "median.h"

main函数第一部分:读入数据

    vector<Student_info> students;
    Student_info record;
    string::size_type maxLen = 0;

    while (read(cin, record)) // 不能是void
    {
        maxLen = max(maxLen, record.name.size());
        students.push_back(record);
    }

main函数第二部分:按学生名字字典序从小到大排序

    sort(students.begin(), students.end(), compare);

main函数第三部分:计算成绩并按格式输出数据

    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]);
            streamsize prec = cout.precision();
            cout << setprecision(3) << final_grade
                 << setprecision(prec);
        }
        catch (domain_error e)
        {
            cout << e.what() << endl;
        }
        cout << endl;
    }

    return 0;