如果是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
类型。
它在代码中的具体作用是:
-
time(0)
:time
函数来自<ctime>
或<time.h>
库,它返回当前时间(从1970年1月1日到现在的秒数)。- 传递
0
作为参数意味着请求当前的日历时间。
-
static_cast<unsigned int>(...)
:static_cast
是C++中的类型转换操作符,用于显式地将一种类型转换为另一种类型。- 在这里,它将
time(0)
返回的时间值转换为unsigned int
类型。这是因为srand
函数需要一个无符号整数(unsigned int
)作为种子值。
-
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
是类的属性,它们被设置为私有,以避免直接从类的外部访问和修改。 - 公有成员函数:包括构造函数、
deposit
、withdraw
、getBalance
和displayAccountDetails
,用于执行银行账户的各种操作。 - 主函数 (
main
):在这里创建并操作BankAccount
类的实例。
这个项目展示了C++的面向对象编程基础,包括类的定义、对象的创建、方法的调用等。您可以通过添加更多功能(如交易历史记录、多个账户管理、密码保护等)来扩展此项目,从而更深入地理解和实践C++编程。
部分代码片段详细介绍
BankAccount(std::string accountNumber, std::string accountHolder)
BankAccount
是类名,这里用作构造函数的名称。构造函数用于初始化对象的新实例。- 括号内的
std::string accountNumber
和std::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
用于存储城市名称,temp
和hum
分别用于存储温度和湿度。 -
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_back
是vector
的一个方法,用于在容器末尾添加新元素。 -
file.close();
在读取完所有数据后关闭文件。 -
return true;
数据加载成功后返回true
。
好了,今天的小项目就到此为止辣,欢迎继续关注小白的C++成长之旅。之前我有试过学习C++,在外网的一个学习网站,但是每次都是重新开始,不是从新开始,昨晚和学长聊天,他建议我一段时间内注重一个知识的学习,所以接下来我可能都会发布关于C++的项目,希望大家也能给我一点关于学习的经验💌💌谢谢了