C++学习之旅(二)运行四个小项目 (Ubuntu使用Vscode)

news2024/11/17 14:53:12
如果是c语言学的比较好的同学 可以直接跟着代码敲一遍,代码附有详细语法介绍,不可错过

一,猜数字游戏

#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
    srand(static_cast<unsigned int>(time(0)));
    int secretNumber = rand() % 100 + 1;
    int guess = 0;
    int tries = 0;
    const int MAX_TRIES = 7;

    std::cout << "Welcome to guess number game!\n";
    std::cout << "I have a number from 1 to 100, you have " << MAX_TRIES << " times to try it. ";

    while ( guess != secretNumber && tries < MAX_TRIES)
    {
        std::cout << "guess what number is it: ";
        std::cin >> guess;
        tries ++;

        if (guess > secretNumber) {
            std::cout << "too hign\n";
        } else if (guess < secretNumber) {
            std::cout << "too low\n";
        } else {
            std::cout << "Congratulations!";
        }
          
    }

    if (guess != secretNumber) {
        std::cout << "Sorry, you die. the number is " << secretNumber << ". \n";

    }

    return 0;    
}

写了一个猜数字的小游戏,首先要配置任务运行编译器:

  • 按下Ctrl + Shift + P打开命令面板,输入Configure Task,然后选择Tasks: Configure Task
  • 选择C/C++: g++.exe build active file(可能会有轻微的名称差异)以自动生成一个tasks.json文件。这个文件定义了编译任务。
  • 你可能需要根据需要修改tasks.json中的命令,例如指定不同的编译器标志。
  • 我使用的是g++, tasks.json应该是类似于下面的代码:
  • {
    	"version": "2.0.0",
    	"tasks": [
    		
    		{
    			"type": "cppbuild",
    			"label": "C/C++: g++ 生成活动文件",
    			"command": "/usr/bin/g++",
    			"args": [
    				"-fdiagnostics-color=always",
    				"-g",
    				"${file}",
    				"-o",
    				"${fileDirname}/${fileBasenameNoExtension}"
    			],
    			"options": {
    				"cwd": "${fileDirname}"
    			},
    			"problemMatcher": [
    				"$gcc"
    			],
    			"group": {
    				"kind": "build",
    				"isDefault": true
    			},
    			"detail": "编译器: /usr/bin/g++"
    		}
    	]
    }

  • 按下Ctrl + Shift + D打开调试视图,然后点击“创建 launch.json 文件”链接。
  • 选择“C++ (GDB/LLDB)”。
  • 选择“g++ - 生成并调试活动文件”配置。
  • 这将自动生成一个launch.json文件,你可以根据需要调整这个文件。

在Vscode的终端中运行文件就可以正常运行你的代码了

由于本人长时间使用c语言,所以对C++的语法不大熟悉,下面来解释以下令我疑惑的代码片段:

srand(static_cast<unsigned int>(time(0)));
  • srand() 用于设置随机数生成器的种子。
  • time(0) 获取当前时间作为种子。
  • static_cast<unsigned int>time(0) 的返回值转换为 unsigned int 类型。

 它在代码中的具体作用是:

  1. time(0)

    • time 函数来自 <ctime><time.h> 库,它返回当前时间(从1970年1月1日到现在的秒数)。
    • 传递 0 作为参数意味着请求当前的日历时间。
  2. static_cast<unsigned int>(...)

    • static_cast 是C++中的类型转换操作符,用于显式地将一种类型转换为另一种类型。
    • 在这里,它将 time(0) 返回的时间值转换为 unsigned int 类型。这是因为 srand 函数需要一个无符号整数(unsigned int)作为种子值。
  3. srand(...)

    • srand 是 “set random” 的缩写,来自 <cstdlib><stdlib.h> 库。
    • 它用于设置随机数生成器的初始种子值。
    • 种子决定了随机数生成器产生的伪随机数序列。不同的种子会产生不同的序列。
    • 如果你每次运行程序时使用相同的种子,将会得到相同的随机数序列。这在某些情况下是有用的,比如在需要可重复测试的场景中。

因此,srand(static_cast<unsigned int>(time(0))); 这行代码的作用是使用当前时间作为种子来初始化随机数生成器,确保每次运行程序时都能产生不同的随机数序列。这对于任何需要随机性的程序,如游戏、模拟或安全相关的应用,都是非常重要的。

二,银行账户管理系统

项目概述

  • 类名BankAccount
  • 属性
    • accountNumber (账户号码)
    • accountHolder (账户持有人名称)
    • balance (账户余额)
  • 方法
    • 构造函数 (用于创建账户)
    • deposit (存款)
    • withdraw (取款)
    • getBalance (查看余额)
    • displayAccountDetails (显示账户详情)

代码实现

#include <iostream>
#include <string>


class BankAccout {
private:
    std::string accountNumber;
    std::string accountHolder;
    double balance;

public:
    BankAccout(std::string accountNumber, std::string accountHolder)
        : accountNumber(accountNumber), accountHolder(accountHolder), balance(0) {}


    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        }
    }

    double getBalance() const {
        return balance;
    }

    void displayAccountDetails() const {
        std::cout << "Account Number: " << accountNumber << "\n"
                  << "Account Holder: " << accountHolder << "\n"
                  << "balance: " << balance << "\n";
    }


};

int main() {
    BankAccout account("12345678", "John Doe");

    account.displayAccountDetails();

    account.deposit(1000);
    account.withdraw(500);

    account.displayAccountDetails();

    return 0;
}

项目解析

  • 类定义:定义了一个名为 BankAccount 的类,其中包含账户的基本信息和操作。
  • 私有成员变量accountNumber, accountHolder, 和 balance 是类的属性,它们被设置为私有,以避免直接从类的外部访问和修改。
  • 公有成员函数:包括构造函数、depositwithdrawgetBalancedisplayAccountDetails,用于执行银行账户的各种操作。
  • 主函数 (main):在这里创建并操作 BankAccount 类的实例。

这个项目展示了C++的面向对象编程基础,包括类的定义、对象的创建、方法的调用等。您可以通过添加更多功能(如交易历史记录、多个账户管理、密码保护等)来扩展此项目,从而更深入地理解和实践C++编程。

部分代码片段详细介绍

BankAccount(std::string accountNumber, std::string accountHolder)
  • BankAccount 是类名,这里用作构造函数的名称。构造函数用于初始化对象的新实例。
  • 括号内的 std::string accountNumberstd::string accountHolder 是构造函数的参数。当创建 BankAccount 类的对象时,你需要提供这些参数。
  • : accountNumber(accountNumber), accountHolder(accountHolder), balance(0)
    
  • 成员初始化列表以冒号 : 开始,后面紧跟类成员的初始化。
  • accountNumber(accountNumber) 表示用构造函数接收的 accountNumber 参数来初始化类的 accountNumber 成员变量。
  • accountHolder(accountHolder) 同理,表示用参数 accountHolder 初始化类成员 accountHolder
  • balance(0) 表示类成员 balance 被初始化为 0

为什么使用成员初始化列表

成员初始化列表在构造函数体执行前初始化类的成员变量。这比在构造函数体内赋值更有效率,特别是对于复杂类型的成员变量(如对象)。在这个特定例子中,使用成员初始化列表初始化字符串成员变量和一个浮点数是一种标准做法。

完整的构造函数

将这些部分组合在一起,构造函数的意思是:当创建 BankAccount 类的对象时,需要提供账户号码和持有人姓名。这些值将被用来初始化对象的相应成员变量,同时账户余额被初始化为0。

三,学生信息管理系统

当然可以。让我们构建一个稍微复杂一些的C++项目,这次我们将实现一个简单的学生信息管理系统。在这个系统中,我们将创建两个类:一个是Student类,用来表示单个学生的信息;另一个是StudentManager类,用来管理多个学生的信息。

这个项目将展示如何使用C++来处理更复杂的数据结构,以及如何在类之间进行交互。

项目概述

  • Student

    • 属性
      • name (学生姓名)
      • id (学生ID)
      • grade (学生成绩)
    • 方法
      • 构造函数
      • 显示学生信息 (displayInfo)
  • StudentManager

    • 属性
      • students (一个存储多个 Student 对象的容器)
    • 方法
      • 添加学生 (addStudent)
      • 显示所有学生信息 (displayAllStudents)

代码实现

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

class Student {
private:
    std::string name;
    std::string id;
    double grade;

public:
    Student(std::string name, std::string id, double grade)
    : name(name), id(id), grade(grade) {}

    void displayInfo() const {
        std::cout << "Student Name: " << name
                  << ", ID: " << id
                  << ", Grade: " << grade << "\n";
    }
};

class StudentManager {
private:
    std::vector<Student> students;

public:
    void addStudent(const Student& student) {
        students.push_back(student);
    }

    void displayAllStudent() const {
        for (const auto& student : students) {
            student.displayInfo();
        }
    } 
};

int main() {
    StudentManager manager;

    manager.addStudent(Student("Alice", "A001", 91.5));
    manager.addStudent(Student("Bob", "B002", 88.5));
    manager.addStudent(Student("Charlie", "C003", 79.5));

    manager.displayAllStudent();

    return 0;

}

部分代码片段分析

class StudentManager {
private:
    std::vector<Student> students;

public:
    void addStudent(const Student& student) {
        students.push_back(student);
    }

    void displayAllStudent() const {
        for (const auto& student : students) {
            student.displayInfo();
        }
    } 
};
private:
    std::vector<Student> students;
  • private 关键字指明紧随其后的成员是私有的,只能被 StudentManager 类的成员函数访问。
  • std::vector<Student> students; 声明了一个 std::vector,这是C++标准库中的一个动态数组,用来存储 Student 对象。students 是此向量的名称。
public:
    void addStudent(const Student& student) {
        students.push_back(student);
    }
  • public 关键字指明紧随其后的成员是公有的,可以被任何访问 StudentManager 对象的代码访问。
  • addStudent 函数接收一个对 Student 类型的引用(const Student& student)作为参数。使用引用可以避免复制整个 Student 对象,而 const 确保传递的 Student 对象不会在这个函数中被修改。引用 (&):在 C++ 中,引用相当于是另一个变量的别名。使用引用可以避免在函数调用时复制数据,从而提高效率。当你用引用作为函数参数时,实际上是传递了对原始数据的直接访问权,而不是其副本。
  • students.push_back(student); 将传入的 Student 对象添加到 students 向量的末尾。
    void displayAllStudents() const {
        for (const auto& student : students) {
            student.displayInfo();
        }
    }
  • displayAllStudents 函数用于显示所有学生的信息。const 关键字表示这个函数不会修改 StudentManager 对象。
  • for (const auto& student : students) 是一个范围基于的 for 循环,用于遍历 students 向量中的每个 Student 对象。这里使用 auto 关键字让编译器自动推断 student 的类型。
  • 在循环内部,student.displayInfo(); 调用了每个 Student 对象的 displayInfo 函数,以显示其信息。

这个类的设计展示了C++面向对象编程的一些关键概念,如封装、数据隐藏和接口公开。通过 StudentManager 类的公有接口,外部代码可以向管理器添加学生对象和显示所有学生的信息,而无需直接操作内部的 students 向量。这是一种良好的设计实践,因为它保持了类的内部状态的完整性和安全性。

四,小型天气预报应用

这个项目将涉及自定义数据结构、文件输入输出以及一些基本的字符串操作。在这个项目中,我们将创建一个 WeatherReport 类来处理和存储关于特定城市的天气数据,并从文件中读取数据,然后生成报告。

项目概述

  • WeatherData

    • 属性
      • cityName (城市名称)
      • temperature (温度)
      • humidity (湿度)
    • 方法
      • 构造函数
      • 显示天气信息 (display)
  • WeatherReport

    • 属性
      • weatherData (存储多个 WeatherData 对象的容器)
    • 方法
      • 从文件加载天气数据 (loadDataFromFile)
      • 显示所有天气报告 (displayReport)

代码实现

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>

class WeatherData {
private:
    std::string cityName;
    double temperature;
    double humidity;

public:
    WeatherData(std::string cityName, double temperature, double humidity)
        : cityName(cityName), temperature(temperature), humidity(humidity) {}

    void display() const {
        std::cout << "City: " << cityName
                  << "Temperature: " << temperature
                  << "`C, Humidity: " << humidity << "%\n";
    }
};

class WeatherReport {
private:
    std::vector<WeatherData> weatherData;

public:
    bool loadDataFromFile(const std::string& filename) {
        std::ifstream file(filename);
        if (!file.is_open()) return false;

        std::string line, city;
        double temp, hum;
        while (getline(file, line)) {
            std::istringstream iss(line);
            if (!(iss >> city >> temp >> hum)) break;
            weatherData.emplace_back(city, temp, hum);
        }
        file.close();
        return true;
    }

    void displayReport() const {
        for (const auto& data : weatherData) {
            data.display();
        }
    }
   
 };

int main() {
    WeatherReport report;
    if (report.loadDataFromFile("weather_data.txt")) {
        report.displayReport();
    } else {
        std::cout << "Failed to load data. \n";
    }

    return 0;
}

文件 weather_data.txt

创建一个文本文件 weather_data.txt,格式如下:

London 15.5 60
NewYork 22.3 55
Paris 18.9 65

项目解析

  • WeatherData 存储单个城市的天气信息,包括城市名称、温度和湿度,并提供一个方法来显示这些信息。
  • WeatherReport 用于从文件中读取多个城市的天气数据,并存储在一个 WeatherData 对象的向量中。它还提供了一个方法来显示所有加载的天气数据。
  • main 函数中,我们创建了一个 WeatherReport 对象,尝试从文件中加载数据,如果成功,就显示天气报告。

这个项目展示了文件输入输出的处理,字符串流的使用(std::istringstream),以及如何使用STL容器来存储和管理数据。这些是在C++编程中经常会用到的重要概念和技术。通过实现这样的项目,你可以更好地理解如何在C++中处理更复杂的数据流和数据结构。

部分代码片段分析

public:
    bool loadDataFromFile(const std::string& filename) {
        std::ifstream file(filename);
        if (!file.is_open()) return false;

        std::string line, city;
        double temp, hum;
        while (getline(file, line)) {
            std::istringstream iss(line);
            if (!(iss >> city >> temp >> hum)) break;
            weatherData.emplace_back(city, temp, hum);
        }
        file.close();
        return true;
    }

    void displayReport() const {
        for (const auto& data : weatherData) {
            data.display();
        }
    }
};
  • bool loadDataFromFile(const std::string& filename) 定义了一个名为 loadDataFromFile 的成员函数,它接受一个字符串引用作为参数,这个字符串代表要加载数据的文件名。该函数返回一个布尔值,表示数据加载是否成功。

  • std::ifstream file(filename); 使用给定的文件名创建了一个输入文件流 file。这个流用于读取文件内容。‘std::ifstream 类‘:这是 C++ 标准库中的一个类,专门用于处理文件输入。它是 istream 类的子类,专门用于从文件读取数据。ifstream 代表 "input file stream",即输入文件流。

  • if (!file.is_open()) return false; 检查文件是否成功打开。如果没有,函数返回 false

  • std::string line, city; double temp, hum; 定义了一些变量来存储从文件中读取的数据。line 用于存储文件中的每一行,city 用于存储城市名称,temphum 分别用于存储温度和湿度。

  • while (getline(file, line)) { ... } 是一个循环,它一行一行地读取文件。每次循环,它读取文件的下一行到 line 变量中。

  • std::istringstream iss(line); 创建了一个字符串输入流,它从 line 变量中读取数据。std::istringstream 类: std::istringstream 属于 C++ 标准库中的 <sstream> 头文件。它提供了基于字符串的输入流功能。简单来说,std::istringstream 允许你像处理输入文件流(如 std::ifstream)那样处理一个 std::string 对象。通过 std::istringstream iss 语句,你创建了一个名为 iss 的 std::istringstream 类型的对象。这个对象用于读取和解析字符串中的数据。一旦 iss 被初始化,它就可以像任何其他输入流一样使用,允许你从中读取和解析数据。例如,你可以使用 >> 运算符从 iss 中提取基本数据类型的值,或者使用 getline 函数从中读取字符串。

  • if (!(iss >> city >> temp >> hum)) break; 使用字符串流从 line 中提取城市名、温度和湿度。如果提取失败,循环将中断。

  • weatherData.emplace_back(city, temp, hum); 将读取的数据作为新 WeatherData 对象添加到 weatherData 向量中。emplace_backvector 的一个方法,用于在容器末尾添加新元素。

  • file.close(); 在读取完所有数据后关闭文件。

  • return true; 数据加载成功后返回 true

好了,今天的小项目就到此为止辣,欢迎继续关注小白的C++成长之旅。之前我有试过学习C++,在外网的一个学习网站,但是每次都是重新开始,不是从新开始,昨晚和学长聊天,他建议我一段时间内注重一个知识的学习,所以接下来我可能都会发布关于C++的项目,希望大家也能给我一点关于学习的经验💌💌谢谢了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1540809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常用类一(包装类)

目录 基本数据类型的包装类 包装类基本知识 包装类的用途 自动装箱和拆箱 自动装箱&#xff1a; 自动拆箱&#xff1a; 包装类的缓存问题 基本数据类型的包装类 八种基本数据类型并不是对象&#xff0c;为了将基本类型数据和对象之间实现互 相转化&#xff0c;JDK 为每一…

java 高级面试题(借鉴)(下)

雪花算法原理 第1位符号位固定为0&#xff0c;41位时间戳&#xff0c;10位workId&#xff0c;12位序列号&#xff0c;位数可以有不同实现。 优点&#xff1a;每个毫秒值包含的ID值很多&#xff0c;不够可以变动位数来增加&#xff0c;性能佳&#xff08;依赖workId的实现…

《自动机理论、语言和计算导论》阅读笔记:p1-p4

《自动机理论、语言和计算导论》学习第1天&#xff0c;p1-p4&#xff0c;总计4页。这只是个人的学习记录&#xff0c;因为很多东西不懂&#xff0c;难免存在理解错误的地方。 一、技术总结 1.有限自动机(finite automata)示例 1.software for checking digital circuits。 …

数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)

和我一起学编程呀&#xff0c;大家一起努力&#xff01; 这篇文章耗时比较久&#xff0c;所以大家多多支持啦 链表的结构及结构 概念&#xff1a;链表是⼀种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的。 理解&a…

【HarmonyOS】ArkUI - 状态管理

在声明式 UI 中&#xff0c;是以状态驱动视图更新&#xff0c;如图1所示&#xff1a; 图1 其中核心的概念就是状态&#xff08;State&#xff09;和视图&#xff08;View&#xff09;&#xff1a; 状态&#xff08;State&#xff09;&#xff1a;指驱动视图更新的数据&#xf…

Linux安装Nginx及配置TCP负载均衡

目录 1、安装编译工具及库文件2、下载解压Nginx压缩包3、Ngnix配置Tcp负载均衡4、配置Ngnix的文件5、Nginx启动 1、安装编译工具及库文件 yum -y install make zlib zlib-devel gcc-c libtool openssl openssl-devel pcre-devel2、下载解压Nginx压缩包 wget https://nginx.o…

腾讯云服务器如何购买?图文全流程,2024最新整理

腾讯云服务器购买流程很简单&#xff0c;有两种购买方式&#xff0c;直接在官方活动上购买比较划算&#xff0c;在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动…

“架构(Architecture)” 一词的定义演变历史(依据国际标准)

深入理解“架构”的客观含义&#xff0c;不仅能使IT行业的系统架构设计师提升思想境界&#xff0c;对每一个积极的社会行动者而言&#xff0c;也具有长远的现实意义&#xff0c;因为&#xff0c;“架构”一词&#xff0c;不只限于IT系统&#xff0c;而是指各类系统(包括社会系统…

ClickHouse部署安装

准备工作 确定防火墙处于关闭状态 CentOS取消打开文件数限制 在hadoop102的 /etc/security/limits.conf文件的末尾加入以下内容 注意&#xff1a;以下操作会修改 Linux 系统配置&#xff0c;如果操作不当可能导致虚拟机无法启动&#xff0c;建议在执行以下操作之前给…

鸿蒙一次开发,多端部署(十五)常见问题

如何查询设备类型 设备类型分为default&#xff08;默认设备&#xff09;、tablet、tv、wearable、2in1等&#xff0c;有多种查询设备类型的方式。 通过命令行的方式查询设备类型。 通过命令行查询指定系统参数&#xff08;const.product.devicetype&#xff09;进而确定设备…

手撕算法-三数之和

描述 分析 排序双指针直接看代码。 代码 public static List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);List<List<Integer>> res new ArrayList<>();for(int k 0; k < nums.length - 2; k){if(nums[k] > 0) break; …

pandas的综合练习

事先说明&#xff1a; 由于每次都要导入库和处理中文乱码问题&#xff0c;我都是在最前面先写好&#xff0c;后面的代码就不在写了。要是copy到自己本地的话&#xff0c;就要把下面的代码也copy下。 # 准备工作import pandas as pd import numpy as np from matplotlib impor…

【Java程序设计】【C00341】基于Springboot的药品管理系统(有论文)

基于Springboot的药品管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及idea&…

修复公众号订阅消息改版金媒v10.3_v10.4和奥壹oelove 10.1处理方式有不同

首先我截图让大家看下自从微信官方弃用历史消息模板改用订阅号消息模板后&#xff0c;两个厂家是怎么针对程序修复的&#xff01; 一.金媒v10.3_v10.4 列出了类目标注了说明&#xff0c;然后参数需要自己申请和对接&#xff0c;对于新手来说一头雾水比较懵&#xff0c;也就是说…

②零基础MySQL数据库-MySQL约束

作用 表在设计的时候加入约束的目的就是为了保证表中的记录完整性和有效性&#xff0c;比如用户表有些列的值&#xff08;手机号&#xff09;不能为空&#xff0c;有些列的值&#xff08;身份证号&#xff09;不能重复 分类 主键约束(primary key) PK 自增长约束(auto_increme…

LabVIEW比例流量阀自动测试系统

LabVIEW比例流量阀自动测试系统 开发了一套基于LabVIEW编程和PLC控制的比例流量阀自动测试系统。通过引入改进的FCMAC算法至测试回路的压力控制系统&#xff0c;有效提升了压力控制效果&#xff0c;展现了系统的设计理念和实现方法。 项目背景&#xff1a; 比例流量阀在液压…

docker desktop 登录不上账号

配置走代理&#xff08;系统全局&#xff09;也没用 解决方法 参考博文&#xff1a; https://blog.csdn.net/weixin_37477009/article/details/135797296 https://adoyle.me/Today-I-Learned/docker/docker-desktop.html 下载 Proxifiler 配置 Proxifiler

使用 Web Components 实现输入法更换皮肤 (vue)

更换皮肤 (界面外观) 是拼音输入法的常见功能. 要实现更换皮肤, 有许多种不同的具体技术方案可以使用. 本文选择 Web Components 技术 (vue) 来实现这个功能. 目录 1 效果展示 1.1 发布新版本 2 Web Components 简介3 vue 使用 Web Components 3.1 使用 vue 实现 Web Compon…

软件测试 -- Selenium常用API全面解答(java)

写在前面 // 如果文章有问题的地方, 欢迎评论区或者私信指正 目录 什么是Selenium 一个简单的用例 元素定位 id定位 xpath定位 name定位 tag name 定位和class name 定位 操作元素 click send_keys submit text getAttribute 添加等待 显示等待 隐式等待 显示等…

立体统计图表绘制方法(分离式环图)

立体统计图表绘制方法&#xff08;分离式环形图&#xff09; 记得我学统计学的时候&#xff0c;那些统计图表大都是平面的框框图&#xff0c;很呆板&#xff0c;就只是表现出统计的意义就好了。在网络科技发展进步的当下&#xff0c;原来一些传统的统计图表都有了进一步的创新。…