实验四

任务一:

GradeCalc.hpp

#pragma once
#include <vector>
#include <array>
#include <string>
class GradeCalc {
public:
    GradeCalc(const std::string& cname);
    void input(int n);                         // 录入n个成绩
    void output() const;                      // 输出成绩
    void sort(bool ascending = false);        // 排序 (默认降序)
    int min() const;                          // 返回最低分(如成绩未录入,返回-1)
    int max() const;                          // 返回最高分 (如成绩未录入,返回-1)
    double average() const;                   // 返回平均分 (如成绩未录入,返回0.0)
    void info();                      // 输出课程成绩信息
private:
    void compute();     // 成绩统计
private:
    std::string course_name;     // 课程名
    std::vector<int> grades;     // 课程成绩
    std::array<int, 5> counts;      // 保存各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100]     std::array<double, 5> rates;    // 保存各分数段人数占比 
    std::array<double, 5> rates;
    bool is_dirty;
};

GradeCalc.cpp

  1 #include <algorithm>
  2 #include <array>
  3 #include <cstdlib>
  4 #include <iomanip>
  5 #include <iostream>
  6 #include <numeric>
  7 #include <string>
  8 #include <vector>
  9 #include "GradeCalc.hpp"
 10 GradeCalc::GradeCalc(const std::string& cname) :course_name{ cname }, is_dirty{ true } {
 11     counts.fill(0);
 12     rates.fill(0);
 13 }
 14 void GradeCalc::input(int n) {
 15     if (n < 0) {
 16         std::cerr << "无效输入! 人数不能为负数\n";
 17         std::exit(1);
 18     }
 19 
 20     grades.reserve(n);
 21     int grade;
 22     for (int i = 0; i < n;) {
 23         std::cin >> grade;
 24         if (grade < 0 || grade > 100) {
 25             std::cerr << "无效输入! 分数须在[0,100]\n";
 26             continue;
 27         }
 28 
 29         grades.push_back(grade);
 30         ++i;
 31     }
 32     is_dirty = true;  // 设置脏标记:成绩信息有变更
 33 }
 34 void GradeCalc::output() const {
 35     for (auto grade : grades)
 36         std::cout << grade << ' ';
 37     std::cout << std::endl;
 38 }
 39 
 40 void GradeCalc::sort(bool ascending) {
 41     if (ascending)
 42         std::sort(grades.begin(), grades.end());
 43     else
 44         std::sort(grades.begin(), grades.end(), std::greater<int>());
 45 }
 46 int GradeCalc::min() const {
 47     if (grades.empty())
 48         return -1;
 49     auto it = std::min_element(grades.begin(), grades.end());
 50     return *it;
 51 }
 52 int GradeCalc::max() const {
 53     if (grades.empty())
 54         return -1;
 55     auto it = std::max_element(grades.begin(), grades.end());
 56     return *it;
 57 }
 58 double GradeCalc::average() const {
 59     if (grades.empty())
 60         return 0.0;
 61     double avg = std::accumulate(grades.begin(), grades.end(), 0.0) / grades.size();
 62     return avg;
 63 }
 64 void GradeCalc::info() {
 65     if (is_dirty)
 66         compute();
 67     std::cout << "课程名称:\t" << course_name << std::endl;
 68     std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() <<
 69         std::endl;
 70     std::cout << "最高分:\t" << max() << std::endl;
 71     std::cout << "最低分:\t" << min() << std::endl;
 72     const std::array<std::string, 5> grade_range{ "[0, 60) ",
 73                                            "[60, 70)",
 74                                            "[70, 80)",
 75                                            "[80, 90)",
 76                                             "[90, 100]" };
 77 
 78     for (int i = grade_range.size() - 1; i >= 0; --i)
 79         std::cout << grade_range[i] << "\t: " << counts[i] << "人\t"
 80         << std::fixed << std::setprecision(2) << rates[i] * 100 << "%\n";
 81 }
 82 void GradeCalc::compute() {
 83     if (grades.empty())
 84         return;
 85     counts.fill(0);
 86     rates.fill(0.0);
 87     // 统计各分数段人数
 88     for (auto grade : grades) {
 89         if (grade < 60)
 90             ++counts[0];        // [0, 60)
 91         else if (grade < 70)
 92             ++counts[1];        // [60, 70)
 93         else if (grade < 80)
 94             ++counts[2];        // [70, 80)
 95         else if (grade < 90)
 96             ++counts[3];        // [80, 90)
 97         else
 98             ++counts[4];        // [90, 100]
 99     }
100     // 统计各分数段比例
101     for (int i = 0; i < rates.size(); ++i)
102         rates[i] = counts[i] * 1.0 / grades.size();
103 
104     is_dirty = false;  // 更新脏标记
105 }

test1.cpp

 1 #include <iostream>
 2 #include <string>
 3 #include "GradeCalc.hpp"
 4 void test() {
 5     GradeCalc c1("OOP");
 6     std::cout << "录入成绩:\n";
 7     c1.input(5);
 8     std::cout << "输出成绩:\n";
 9     c1.output();
10     std::cout << "排序后成绩:\n";
11     c1.sort(); c1.output();
12     std::cout << "*************成绩统计信息*************\n";
13     c1.info();
14 }
15 int main() {
16     test();
17 }

 

屏幕截图 2025-11-26 083454

问题一:

std::string course_name;记录课程的名称

std::vector<int> grades;记录下每个人的成绩

std::array<int,5> counts;记录5个分数段各自的人数

std::array<double,5> rates;记录5个分数段各自的人数占比

问题二:

不合法, grades是私有类型

问题三:

(1)一次,判断整体的打印信息是否有修改

(2)需要,打印信息改变

问题四:
直接在info函数中添加,

int count = grades.size()/2 ;

if(grades.size()%2  == 0){

  std::cout<<(gardes[count - 1] +grades[count])/2.0<<std::endl;

}

else{

  std::cout<<grade[count]/2.0<<std::endl;

}

问题五:

不能,再次统计时

问题六:

(1)无

(2)有,避免元素复制

 

 

任务二:

GradeCalc.hpp

#pragma once

#include <array>
#include <string>
#include <vector>

class GradeCalc : private std::vector<int> {
public:
    GradeCalc(const std::string& cname);
    void input(int n);                        // 录入n个成绩
    void output() const;                      // 输出成绩
    void sort(bool ascending = false);        // 排序 (默认降序)
    int min() const;                          // 返回最低分
    int max() const;                          // 返回最高分
    double average() const;                   // 返回平均分
    void info();                              // 输出成绩统计信息 

private:
    void compute();               // 计算成绩统计信息

private:
    std::string course_name;     // 课程名
    std::array<int, 5> counts;   // 保存各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100]
    std::array<double, 5> rates; // 保存各分数段占比
    bool is_dirty;      // 脏标记,记录是否成绩信息有变更
};

GradeCalc.cpp

#include <algorithm>
#include <array>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
#include "GradeCalc1.hpp"


GradeCalc::GradeCalc(const std::string& cname) : course_name{ cname }, is_dirty{ true } {
    counts.fill(0);
    rates.fill(0);
}

void GradeCalc::input(int n) {
    if (n < 0) {
        std::cerr << "无效输入! 人数不能为负数\n";
        return;
    }

    this->reserve(n);

    int grade;

    for (int i = 0; i < n;) {
        std::cin >> grade;
        if (grade < 0 || grade > 100) {
            std::cerr << "无效输入! 分数须在[0,100]\n";
            continue;
        }

        this->push_back(grade);
        ++i;
    }

    is_dirty = true;
}

void GradeCalc::output() const {
    for (auto grade : *this)
        std::cout << grade << ' ';
    std::cout << std::endl;
}

void GradeCalc::sort(bool ascending) {
    if (ascending)
        std::sort(this->begin(), this->end());
    else
        std::sort(this->begin(), this->end(), std::greater<int>());
}

int GradeCalc::min() const {
    if (this->empty())
        return -1;

    return *std::min_element(this->begin(), this->end());
}

int GradeCalc::max() const {
    if (this->empty())
        return -1;

    return *std::max_element(this->begin(), this->end());
}

double GradeCalc::average() const {
    if (this->empty())
        return 0.0;

    double avg = std::accumulate(this->begin(), this->end(), 0.0) / this->size();
    return avg;
}

void GradeCalc::info() {
    if (is_dirty)
        compute();

    std::cout << "课程名称:\t" << course_name << std::endl;
    std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl;
    std::cout << "最高分:\t" << max() << std::endl;
    std::cout << "最低分:\t" << min() << std::endl;

    const std::array<std::string, 5> grade_range{ "[0, 60) ",
                                           "[60, 70)",
                                           "[70, 80)",
                                           "[80, 90)",
                                           "[90, 100]" };

    for (int i = static_cast<int>(grade_range.size()) - 1; i >= 0; --i)
        std::cout << grade_range[i] << "\t: " << counts[i] << "人\t"
        << std::fixed << std::setprecision(2) << rates[i] * 100 << "%\n";
}

void GradeCalc::compute() {
    if (this->empty())
        return;

    counts.fill(0);
    rates.fill(0);

  
    for (int grade : *this) {
        if (grade < 60)
            ++counts[0];        
        else if (grade < 70)
            ++counts[1];        
        else if (grade < 80)
            ++counts[2];        
        else if (grade < 90)
            ++counts[3];        
        else
            ++counts[4];        
    }

   
    for (size_t i = 0; i < rates.size(); ++i)
        rates[i] = counts[i] * 1.0 / this->size();

    is_dirty = false;
}

test2.cpp

 1 #include <iostream>
 2 #include <string>
 3 #include "GradeCalc1.hpp"
 4 
 5 void test() {
 6     GradeCalc c1("OOP");
 7 
 8     std::cout << "录入成绩:\n";
 9     c1.input(5);
10 
11     std::cout << "输出成绩:\n";
12     c1.output();
13 
14     std::cout << "排序后成绩:\n";
15     c1.sort(); c1.output();
16 
17     std::cout << "*************成绩统计信息*************\n";
18     c1.info();
19 
20 }
21 
22 int main() {
23     test();
24 }

 

屏幕截图 2025-11-26 080753

问题一:
class GradeCalc:private std::vector<int>;

问题二:
会,不能,私有继承

问题三:

组合方式在内部通过grades接口进行访问。

继承方式在内部用this指针直接通过使用基类的接口来进行访问。

 问题四:
组合,安全高效

任务三:

Graph.hpp

 1 #pragma once
 2 
 3 #include <string>
 4 #include <vector>
 5 
 6 enum class GraphType { circle, triangle, rectangle };
 7 
 8 // Graph类定义
 9 class Graph {
10 public:
11     virtual void draw() {}
12     virtual ~Graph() = default;
13 };
14 
15 // Circle类声明
16 class Circle : public Graph {
17 public:
18     void draw();
19 };
20 
21 // Triangle类声明
22 class Triangle : public Graph {
23 public:
24     void draw();
25 };
26 
27 // Rectangle类声明
28 class Rectangle : public Graph {
29 public:
30     void draw();
31 };
32 
33 // Canvas类声明
34 class Canvas {
35 public:
36     void add(const std::string& type);   // 根据字符串添加图形
37     void paint() const;                  // 使用统一接口绘制所有图形
38     ~Canvas();                           // 手动释放资源
39 
40 private:
41     std::vector<Graph*> graphs;
42 };
43 
44 // 4. 工具函数
45 GraphType str_to_GraphType(const std::string& s);  // 字符串转枚举类型
46 Graph* make_graph(const std::string& type);  // 创建图形,返回堆对象指针

Graph.cpp

 1 #include <algorithm>
 2 #include <cctype>
 3 #include <iostream>
 4 #include <string>
 5 
 6 #include "Graph.hpp"
 7 
 8 // Circle类实现
 9 void Circle::draw() { std::cout << "draw a circle...\n"; }
10 
11 // Triangle类实现
12 void Triangle::draw() { std::cout << "draw a triangle...\n"; }
13 
14 // Rectangle类实现
15 void Rectangle::draw() { std::cout << "draw a rectangle...\n"; }
16 
17 // Canvas类实现
18 void Canvas::add(const std::string& type) {
19     Graph* g = make_graph(type);
20     if (g)
21         graphs.push_back(g);
22 }
23 
24 void Canvas::paint() const {
25     for (Graph* g : graphs)
26         g->draw();
27 }
28 
29 Canvas::~Canvas() {
30     for (Graph* g : graphs)
31         delete g;
32 }
33 
34 // 工具函数实现
35 // 字符串 → 枚举转换
36 GraphType str_to_GraphType(const std::string& s) {
37     std::string t = s;
38     std::transform(s.begin(), s.end(), t.begin(),
39         [](unsigned char c) { return std::tolower(c); });
40 
41     if (t == "circle")
42         return GraphType::circle;
43 
44     if (t == "triangle")
45         return GraphType::triangle;
46 
47     if (t == "rectangle")
48         return GraphType::rectangle;
49 
50     return GraphType::circle;   // 缺省返回
51 }
52 
53 // 创建图形,返回堆对象指针
54 Graph* make_graph(const std::string& type) {
55     switch (str_to_GraphType(type)) {
56     case GraphType::circle:     return new Circle;
57     case GraphType::triangle:   return new Triangle;
58     case GraphType::rectangle:  return new Rectangle;
59     default: return nullptr;
60     }
61 }

test3.cpp

 1 #include <string>
 2 #include "Graph.hpp"
 3 
 4 void test() {
 5     Canvas canvas;
 6 
 7     canvas.add("circle");
 8     canvas.add("triangle");
 9     canvas.add("rectangle");
10     canvas.paint();
11 }
12 
13 int main() {
14     test();
15 }

屏幕截图 2025-11-26 083802

问题一:

(1)std::vector<Graph*> graphs,表示不同的图形。

(2)class Circle:public Graph;

class Triangle:public Graph;

class Rectangle:public Graph

问题二:

(1)无输出结果

(2)报错

(3)内存泄漏

问题三:

Graph.hpp类声明、enum添加

Graph.cpp类定义

问题四:
(1)Canvas调用析构函数时

(2)利:比智能指针更简单,且节省内存;

弊:原始指针需要自己写new/delete,容易出现内存泄漏

 

任务四:

功能:玩具名的查找、玩具类型的查找、玩具功能的查找、添加玩具、删除玩具

使用场景:工厂对玩具的统计与查找

ToyFactory类与Toy类组合,便于整理与查找

Toy.hpp

 1 #include<string>
 2 #include<vector>
 3 enum kind {name,type,function };
 4 
 5 class Toy {
 6 public:
 7     Toy(const std::string& name, const std::string& type, const std::string& function);
 8     Toy(const Toy& x);
 9     ~Toy();
10     const std::string& get_name()const;
11     const std::string& get_type()const;
12     const std::string& get_function()const;
13     void display()const;
14 private:
15     std::string toy_name;
16     std::string toy_type;
17     std::string toy_function;
18 };
19 
20 class ToyFactory {
21 public:
22     void add(const std::string& name, const std::string& type,const std::string& function);
23     void remove(const std::string& name);
24     bool find(const std::string& name,int func = 0 ) const;
25     void display() const;
26     size_t size() const;
27 private:
28     std::vector<int> index(const std::string &name, int func = 0) const;
29     void sort();
30 private:
31     std::vector <Toy> toys;
32 
33 };

Toy.cpp

  1 #include<iostream>
  2 #include<string>
  3 #include<vector>
  4 #include<algorithm>
  5 #include"Toy.hpp"
  6 
  7 
  8 Toy::Toy(const std::string& name, const std::string& type, const std::string& function) : toy_name{ name }, toy_type{ type }, toy_function{function} {};
  9 
 10 Toy::Toy(const Toy& x) :toy_name{ x.toy_name }, toy_type{ x.toy_type }, toy_function{x.toy_function} {};
 11 
 12 Toy::~Toy() {};
 13 
 14 const std::string& Toy::get_name()const {
 15     return toy_name;
 16 }
 17 
 18 const std::string& Toy::get_type() const{
 19     return toy_type;
 20 }
 21 
 22 const std::string& Toy::get_function() const {
 23     return toy_function;
 24 }
 25 
 26 void Toy::display()const {
 27     std::cout << toy_name << " , " << toy_type <<" , "<<toy_function<< std::endl;
 28 }
 29 void ToyFactory::add(const std::string& name, const std::string& type,const std::string &function) {
 30     if (index(name).size() == 0) {
 31         toys.push_back(Toy(name, type, function));
 32         sort();
 33         return;
 34     }
 35     else {
 36         std::cout <<name<< "已经存在" << std::endl;
 37     }
 38 }
 39 
 40 void ToyFactory::remove(const std::string& name) {
 41     std::vector<int> i = index(name);
 42     if (i.size() == 0) {
 43         std::cout <<name<< "不存在" << std::endl;
 44         return;
 45     }
 46     else {
 47         for (auto j : i) {
 48             toys.erase(toys.begin() + j);
 49         }
 50         std::cout << "已移除" << name << std::endl;
 51     }
 52 }
 53 
 54 bool ToyFactory::find(const std::string &name,int func) const {
 55     std::vector<int> i = index(name,func);
 56     if (i.size() == 0) {
 57         std::cout << "未找到" << name << std::endl;
 58         return false;
 59     }
 60     else {
 61         for (auto j : i) {
 62             toys[j].display();
 63         }
 64     }
 65     return true;
 66 }
 67 
 68 void ToyFactory::display() const{
 69     for (auto& i : toys) {
 70         i.display();
 71     }
 72 }
 73 
 74 size_t ToyFactory::size() const{
 75     return toys.size();
 76 }
 77 
 78 std::vector<int> ToyFactory::index(const std::string &name,int func)const {
 79     std::vector<int> count;
 80     int counts = 0;
 81     for (const auto& i : toys) {
 82         if (i.get_name() == name&&func == 0) {
 83             count.push_back(counts);
 84         }
 85         else if (i.get_type() == name && type == 1) {
 86             count.push_back(counts);
 87         }
 88         else if (i.get_function() == name && func == 2) {
 89             count.push_back(counts);
 90         }
 91         counts++;
 92     }
 93     return count;
 94 }
 95 
 96 void ToyFactory::sort() {
 97     std::sort(toys.begin(), toys.end(), [](const Toy& a, const Toy& b) {
 98         return a.get_name() < b.get_name();
 99         });
100 }

test4.cpp

 1 #include<iostream>
 2 #include"Toy.hpp"
 3 
 4 void test() {
 5     ToyFactory toys;
 6     std::cout << "添加玩具" << std::endl;
 7     toys.add("Elysia", "badge","pendant");
 8     toys.add("Kiana", "cushion","household_supplies");
 9     toys.add("Bronya", "model","decoration");
10     toys.add("FeiXiao", "sign","ornament");
11     std::cout << "共有" << toys.size() << "个玩具" << std::endl;
12     toys.display();
13     std::cout << "查找玩具(名称)" << std::endl;
14     toys.find("Elysia");
15     toys.find("Kiana");
16     std::cout << "查找玩具(类型)" << std::endl;
17     toys.find("model",1);
18     std::cout << "查找玩具(功能)" << std::endl;
19     toys.find("ornament",2);    
20     std::cout << "删除玩具" << std::endl;
21     toys.remove("FeiXiao");
22     toys.remove("WangTY");
23 
24 }
25 
26 int main() {
27     test();
28 }

屏幕截图 2025-12-02 162910

 

posted @ 2025-12-02 17:00  Little_Zcy  阅读(0)  评论(0)    收藏  举报