1.1 编写一个简单的C++程序
概述
本小节介绍了如何编写和运行一个简单的C++程序,帮助初学者了解C++程序的基本结构和编译运行过程。
编写第一个C++程序
我们从一个简单的C++程序开始,它的功能是在控制台输出 "Hello, World!"。这是学习任何编程语言的传统起点。
- 程序代码:
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
代码解析
- 预处理指令:
#include <iostream>
#include
是一个预处理指令,用于包含标准库头文件。<iostream>
是输入输出流库,用于处理输入和输出操作。
- 主函数:
int main() {
// ...
return 0;
}
int main()
是程序的入口点,每个C++程序都必须包含一个main
函数。- 函数返回类型为
int
,表示程序执行的状态,0
通常表示成功。
- 输出语句:
std::cout << "Hello, World!" << std::endl;
std::cout
是标准输出流对象,用于输出数据到控制台。<<
是插入运算符,将右侧的数据插入到输出流中。"Hello, World!"
是要输出的字符串。std::endl
是一个流操纵符,用于插入一个换行符并刷新输出缓冲区。
编译和运行
编写完第一个C++程序后,我们需要将其编译成可执行文件,然后运行它。
- 编译:
- 使用C++编译器将源代码编译成机器代码。
- 示例(使用
g++
编译器):
g++ -o hello hello.cpp
-o
选项指定生成的可执行文件名称,这里是hello
。
- 运行:
- 运行生成的可执行文件。
- 示例:
./hello
- 运行结果:
Hello, World!
C++程序的基本结构
通过这个简单的程序,我们可以看到一个C++程序的基本结构:
- 预处理指令
- 主函数
- 输出语句
这些是每个C++程序的基础,后续章节将会详细介绍更多复杂的语法和功能。
重点与难点分析
重点:
- 预处理指令:了解
#include
的作用,知道如何包含标准库头文件。 - 主函数结构:掌握
main
函数的基本结构和作用。 - 输出语句:理解
std::cout
、插入运算符<<
和std::endl
的使用。
难点:
- 编译过程:初学者可能对编译和链接过程不熟悉,需要多练习。
- 标准库:
<iostream>
是一个常用的标准库头文件,需要理解其基本功能。
练习题解析
- 练习1.1:编写并运行一个简单的C++程序,输出你的名字。
- 示例代码:
#include <iostream>
int main() {
std::cout << "Your Name" << std::endl;
return 0;
}
- 练习1.2:修改第一个C++程序,使其输出两行文字。
- 示例代码:
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
std::cout << "Welcome to C++ Programming!" << std::endl;
return 0;
}
- 练习1.3:尝试将
std::cout
替换为cout
,观察编译错误,并修改代码以正确编译。
- 示例代码:
#include <iostream>
using std::cout;
using std::endl;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
总结与提高
本节总结:
- 了解了一个简单的C++程序的基本结构,包括预处理指令、主函数和输出语句。
- 学会了如何编写、编译和运行一个简单的C++程序。
提高建议:
- 多编写简单程序:通过不断练习,熟悉C++程序的基本结构和编写流程。
- 探索更多标准库:除了
<iostream>
,C++还有许多有用的标准库,可以逐步学习和使用。 - 了解编译器和开发环境:熟悉编译器的使用和常见选项,掌握IDE或命令行的开发环境,提高开发效率。
1.2 初识输入输出
概述
本小节介绍了C++中基本的输入输出操作,通过标准库中的cin
和cout
对象实现。这些对象是iostream
库的一部分,用于处理控制台的输入输出。
使用cin
进行输入
在C++中,cin
对象用于从标准输入设备(通常是键盘)读取数据。cin
是iostream
库的一部分。
- 基本用法:
#include <iostream>
int main() {
int number;
std::cout << "Please enter a number: ";
std::cin >> number;
std::cout << "You entered: " << number << std::endl;
return 0;
}
代码解析
- 读取输入:
std::cin >> number;
std::cin
是标准输入流对象。>>
是提取运算符,用于从输入流中提取数据并存储到变量中。
- 输入提示:
std::cout << "Please enter a number: ";
- 使用
std::cout
输出提示信息,引导用户输入。
- 输出结果:
Please enter a number: 100
You entered: 100
处理多个输入
我们可以使用cin
一次读取多个输入,并将其存储在不同的变量中。
- 示例代码:
#include <iostream>
int main() {
int num1, num2;
std::cout << "Please enter two numbers: ";
std::cin >> num1 >> num2;
std::cout << "You entered: " << num1 << " and " << num2 << std::endl;
return 0;
}
代码解析
- 读取多个输入:
std::cin >> num1 >> num2;
- 使用提取运算符
>>
连续读取两个整数输入,并存储在num1
和num2
中。
- 输出多个输入:
Please enter two numbers: 10 20
You entered: 10 and 20
输入和输出的类型匹配
在使用cin
和cout
时,需要注意类型匹配。如果输入的数据类型与变量类型不匹配,会导致意外行为或错误。
- 示例代码:
#include <iostream>
int main() {
int num;
std::cout << "Please enter an integer: ";
std::cin >> num;
if (std::cin.fail()) {
std::cout << "Input error! Please enter a valid integer." << std::endl;
} else {
std::cout << "You entered: " << num << std::endl;
}
return 0;
}
代码解析
- 检查输入是否失败:
if (std::cin.fail()) {
std::cout << "Input error! Please enter a valid integer." << std::endl;
}
std::cin.fail()
用于检测输入是否失败。如果输入的数据类型与变量类型不匹配,fail()
返回true
。
- 重置输入流:
std::cin.clear(); // 重置输入流状态
std::cin.ignore(1000, '\n'); // 忽略输入缓冲区中的字符
std::cin.clear()
清除错误标志。std::cin.ignore()
忽略输入缓冲区中的字符,避免影响后续输入操作。
重点与难点分析
重点:
- 使用
cin
进行输入:掌握cin
对象和提取运算符>>
的基本用法。 - 处理多个输入:学习使用
cin
一次读取多个输入。 - 输入输出的类型匹配:理解类型匹配的重要性,学习如何处理输入错误。
难点:
- 处理输入错误:初学者可能对输入错误处理不熟悉,需要多练习。
- 输入输出流状态管理:理解输入输出流的状态管理方法,如清除错误标志和忽略输入缓冲区。
练习题解析
- 练习1.4:编写一个程序,读取两个整数并输出它们的和。
- 示例代码:
#include <iostream>
int main() {
int num1, num2;
std::cout << "Please enter two integers: ";
std::cin >> num1 >> num2;
int sum = num1 + num2;
std::cout << "The sum is: " << sum << std::endl;
return 0;
}
- 练习1.5:编写一个程序,读取三个浮点数并输出它们的平均值。
- 示例代码:
#include <iostream>
int main() {
float num1, num2, num3;
std::cout << "Please enter three floating-point numbers: ";
std::cin >> num1 >> num2 >> num3;
float average = (num1 + num2 + num3) / 3;
std::cout << "The average is: " << average << std::endl;
return 0;
}
- 练习1.6:编写一个程序,读取一个整数并检查输入是否合法。如果输入不是整数,输出错误信息。
- 示例代码:
#include <iostream>
int main() {
int num;
std::cout << "Please enter an integer: ";
std::cin >> num;
if (std::cin.fail()) {
std::cout << "Input error! Please enter a valid integer." << std::endl;
std::cin.clear(); // 重置输入流状态
std::cin.ignore(1000, '\n'); // 忽略输入缓冲区中的字符
} else {
std::cout << "You entered: " << num << std::endl;
}
return 0;
}
总结与提高
本节总结:
- 学习了C++中基本的输入输出操作,包括
cin
和cout
对象的使用。 - 掌握了使用
cin
进行输入,处理多个输入,以及输入输出的类型匹配。 - 了解了如何处理输入错误和管理输入输出流的状态。
提高建议:
- 多练习输入输出操作:通过不断练习,熟悉
cin
和cout
的基本用法和常见操作。 - 探索更多输入输出流功能:C++标准库提供了丰富的输入输出流功能,可以逐步学习和使用。
- 了解输入输出流的高级特性:如格式化输出、自定义流操纵符等,提升程序的灵活性和可读性。
1.3 注释简介
概述
注释是程序员在代码中加入的说明性文本,用于解释代码的功能、逻辑或特殊用法。注释不会被编译器执行,它们仅供阅读代码的人使用。合理的注释可以提高代码的可读性和可维护性。
C++支持两种注释方式:单行注释和多行注释。
单行注释
单行注释以 //
开头,直到行尾的所有内容都被视为注释。
- 示例:
#include <iostream>
int main() {
// 输出 "Hello, World!"
std::cout << "Hello, World!" << std::endl; // 单行注释
return 0; // 返回 0
}
代码解析
- 单行注释的使用:
// 输出 "Hello, World!"
是一条单行注释,解释了下一行代码的功能。// 返回 0
是一条单行注释,解释了return 0
语句。
- 注释位置:
- 单行注释可以放在代码行的上方,也可以放在代码行的末尾。
多行注释
多行注释以 /*
开头,以 */
结尾,之间的所有内容都被视为注释。
- 示例:
#include <iostream>
int main() {
/*
这是一段多行注释
解释了以下代码的功能:
输出 "Hello, World!" 并返回 0
*/
std::cout << "Hello, World!" << std::endl;
return 0;
}
代码解析
- 多行注释的使用:
/*
和*/
之间的所有内容都是注释,可以跨越多行。- 多行注释通常用于解释复杂的代码段或提供详细的说明。
- 嵌套注释的注意事项:
- 多行注释不能嵌套,即在一个多行注释内不能再包含另一个多行注释。
- 嵌套会导致编译错误。
注释的最佳实践
合理的注释可以显著提高代码的可读性和可维护性。以下是一些编写注释的最佳实践:
- 解释意图,而非解释语法:
- 注释应解释代码的目的和逻辑,而不是解释语法。例如,不要注释显而易见的语法,而是解释为什么这样写。
- 保持简洁明了:
- 注释应简洁明了,避免冗长。清晰的注释有助于快速理解代码。
- 及时更新注释:
- 代码修改后,应及时更新相应的注释,以确保注释与代码一致。
- 使用TODO注释:
- 对于需要进一步完善或修复的代码,可以使用
TODO
注释标记,提醒以后回顾和处理。 - 示例:
// TODO: 处理可能的错误情况
- 避免过度注释:
- 虽然注释很重要,但过多的注释可能会使代码显得杂乱无章。应在关键部分添加注释,而不是每行都注释。
练习题解析
- 练习1.7:编写一个简单的程序,使用单行注释解释每一行代码。
- 示例代码:
#include <iostream> // 包含输入输出流库
int main() {
int num; // 定义一个整数变量
std::cout << "Please enter a number: "; // 输出提示信息
std::cin >> num; // 从标准输入读取一个整数
std::cout << "You entered: " << num << std::endl; // 输出读取的整数
return 0; // 返回 0
}
- 练习1.8:编写一个程序,使用多行注释解释整个程序的功能。
- 示例代码:
#include <iostream>
int main() {
/*
这是一个简单的C++程序
它从用户那里读取一个整数
然后输出该整数
*/
int num;
std::cout << "Please enter a number: ";
std::cin >> num;
std::cout << "You entered: " << num << std::endl;
return 0;
}
- 练习1.9:编写一个复杂的代码段,使用注释解释每一步操作。
- 示例代码:
#include <iostream>
#include <vector>
int main() {
// 定义一个整数向量
std::vector<int> numbers;
// 向向量中添加数字
for (int i = 1; i <= 5; ++i) {
numbers.push_back(i); // 添加数字 i 到向量末尾
}
// 计算向量中数字的总和
int sum = 0;
for (int num : numbers) {
sum += num; // 将每个数字累加到 sum
}
// 输出结果
std::cout << "The sum is: " << sum << std::endl; // 输出总和
return 0;
}
总结与提高
本节总结:
- 学习了C++中的两种注释方式:单行注释和多行注释。
- 了解了如何在代码中添加注释,以提高代码的可读性和可维护性。
- 通过示例代码,掌握了注释的基本用法和最佳实践。
提高建议:
- 多练习编写注释:在编写代码时,养成良好的注释习惯,解释代码的功能和逻辑。
- 阅读他人的代码:通过阅读他人代码中的注释,学习如何编写清晰有效的注释。
- 及时更新注释:在修改代码时,确保相应的注释也得到更新,以保持代码和注释的一致性。
1.4 控制结构
概述
控制结构是编程语言中用于控制代码执行流程的语法元素。C++提供了多种控制结构,包括条件语句、循环语句和跳转语句。本小节将介绍C++中的基本控制结构,帮助初学者理解如何控制程序的执行流程。
条件语句
条件语句用于根据某个条件的真假来决定执行哪个代码块。C++中的条件语句主要包括if
语句、if-else
语句。
if语句
if
语句根据条件表达式的真假来决定是否执行相应的代码块。
- 语法:
if (condition) {
// 如果 condition 为真,执行这里的代码
}
- 示例:
#include <iostream>
int main() {
int value = 42;
if (value > 0) {
std::cout << "Value is positive" << std::endl;
}
return 0;
}
if-else语句
if-else
语句在条件为真时执行一个代码块,为假时执行另一个代码块。
- 语法:
if (condition) {
// 如果 condition 为真,执行这里的代码
} else {
// 否则,执行这里的代码
}
- 示例:
#include <iostream>
int main() {
int value = -10;
if (value > 0) {
std::cout << "Value is positive" << std::endl;
} else {
std::cout << "Value is not positive" << std::endl;
}
return 0;
}
if-else if-else语句
if-else if-else
语句用于检查多个条件,依次判断每个条件表达式。
- 语法:
if (condition1) {
// 如果 condition1 为真,执行这里的代码
} else if (condition2) {
// 如果 condition2 为真,执行这里的代码
} else {
// 如果前面的条件都不为真,执行这里的代码
}
- 示例:
#include <iostream>
int main() {
int value = 0;
if (value > 0) {
std::cout << "Value is positive" << std::endl;
} else if (value < 0) {
std::cout << "Value is negative" << std::endl;
} else {
std::cout << "Value is zero" << std::endl;
}
return 0;
}
循环语句
循环语句用于重复执行某段代码,直到满足某个条件。C++中的循环语句主要包括while
循环、do-while
循环和for
循环。
while循环
while
循环在每次迭代之前检查条件,如果条件为真,则执行循环体。
- 语法:
while (condition) {
// 如果 condition 为真,执行这里的代码
}
- 示例:
#include <iostream>
int main() {
int count = 0;
while (count < 5) {
std::cout << "Count is: " << count << std::endl;
++count;
}
return 0;
}
do-while循环
do-while
循环先执行循环体,然后检查条件,如果条件为真,则继续执行循环体。
- 语法:
do {
// 先执行这里的代码
} while (condition);
- 示例:
#include <iostream>
int main() {
int count = 0;
do {
std::cout << "Count is: " << count << std::endl;
++count;
} while (count < 5);
return 0;
}
for循环
for
循环在循环开始前初始化变量,在每次迭代前检查条件,并在每次迭代后更新变量。
- 语法:
for (initialization; condition; increment) {
// 如果 condition 为真,执行这里的代码
}
- 示例:
#include <iostream>
int main() {
for (int count = 0; count < 5; ++count) {
std::cout << "Count is: " << count << std::endl;
}
return 0;
}
重点与难点分析
重点:
- 条件语句:掌握
if
、if-else
、if-else if-else
语句的使用。 - 循环语句:理解
while
、do-while
和for
循环的用法。
难点:
- 条件和循环逻辑:初学者可能会对复杂的条件和循环逻辑感到困惑,需要通过实践加深理解。
- 避免滥用
goto
:尽量避免使用goto
,并学习更清晰的控制流程方法。
练习题解析
- 练习1.10:编写一个程序,使用
while
循环输出10到1的数字。
- 示例代码:
#include <iostream>
int main() {
int count = 10;
while (count > 0) {
std::cout << "Count is: " << count << std::endl;
--count;
}
return 0
}
- 练习1.11:编写一个程序,使用
for
循环输出1到10的数字。
- 示例代码:
#include <iostream>
int main() {
for (int count = 1; count <= 10; ++count) {
std::cout << "Count is: " << count << std::endl;
}
return 0;
}
- 练习1.12:编写一个程序,使用
if-else
语句检查输入的整数是正数、负数还是零。
- 示例代码:
#include <iostream>
int main() {
int number;
std::cout << "Please enter an integer: ";
std::cin >> number;
if (number > 0) {
std::cout << "The number is positive." << std::endl;
} else if (number < 0) {
std::cout << "The number is negative." << std::endl;
} else {
std::cout << "The number is zero." << std::endl;
}
return 0;
}
总结与提高
本节总结:
- 学习了C++中的基本控制结构,包括条件语句、循环语句和跳转语句。
- 掌握了
if
、if-else
语句的用法。 - 了解了
while
、do-while
、for
循环的不同用法。
提高建议:
- 多练习控制结构的使用:通过编写各种示例程序,熟悉控制结构的用法和逻辑。
- 理解和优化循环逻辑:在实际编程中,理解和优化循环逻辑,编写高效的代码。
1.5 类简介
概述
类是C++中的一种用户定义类型,它将数据和操作数据的方法封装在一起,是面向对象编程(OOP)的基础。类定义了一组对象的共同属性和行为,通过实例化类,可以创建具体的对象。
定义和使用类
一个类由成员变量(数据成员)和成员函数(方法)组成。成员变量用于存储对象的状态,成员函数用于定义对象的行为。
定义类
- 语法:
class ClassName {
public:
// 公有成员
// 成员变量
// 成员函数
private:
// 私有成员
// 成员变量
// 成员函数
};
- 示例:
#include <iostream>
#include <string>
class SalesItem {
public:
// 成员函数,声明和定义分离
std::string isbn() const { return bookNo; }
double avg_price() const;
// 成员变量
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
// 成员函数的定义
double SalesItem::avg_price() const {
if (units_sold) {
return revenue / units_sold;
} else {
return 0;
}
}
int main() {
SalesItem item;
item.bookNo = "12345";
item.units_sold = 100;
item.revenue = 1000.0;
std::cout << "ISBN: " << item.isbn() << std::endl;
std::cout << "Average Price: " << item.avg_price() << std::endl;
return 0;
}
- 注意,编译上面的代码采用如下的命令:
// 假如你将文件存储为test.cpp
// 需要加上参数 -std=c++11 表示使用C++11标准
g++ -std=c++11 test.cpp -o test
代码解析
- 类的定义:
- 类通过关键字
class
定义,后跟类名和类体。类体包含成员变量和成员函数。 public
和private
访问说明符用于控制成员的访问权限。
- 成员变量:
- 成员变量在类中声明,用于存储对象的状态。例如:
std::string bookNo;
。
- 成员函数:
- 成员函数定义了操作成员变量的方法。可以在类内声明,在类外定义。例如:
std::string isbn() const { return bookNo; }
double avg_price() const;
- 成员函数的定义:
- 成员函数可以在类外定义,使用
ClassName::FunctionName
语法。例如:
double SalesItem::avg_price() const {
if (units_sold) {
return revenue / units_sold;
} else {
return 0;
}
}
- 创建对象:
- 通过类名创建对象,访问对象的成员。例如:
SalesItem item;
item.bookNo = "12345";
item.units_sold = 100;
item.revenue = 1000.0;
重点与难点分析
重点:
- 类的定义和使用:理解类的基本结构,包括成员变量和成员函数的定义和使用。
难点:
- 成员函数的定义和调用:初学者需要熟悉成员函数在类外定义和调用的语法。
练习题解析
- 练习1.13:定义一个类
Book
,包含成员变量title
、author
和price
,以及相应的构造函数和成员函数。
- 示例代码:
#include <iostream>
#include <string>
class Book {
public:
// 默认构造函数
Book() = default;
// 带参数的构造函数
Book(const std::string &t, const std::string &a, double p)
: title(t), author(a), price(p) {}
// 成员函数
std::string getTitle() const { return title; }
std::string getAuthor() const { return author; }
double getPrice() const { return price; }
private:
// 成员变量
std::string title;
std::string author;
double price = 0.0;
};
int main() {
Book book1;
Book book2("C++ Primer", "Stanley B. Lippman", 59.99);
std::cout << "Book1 Title: " << book1.getTitle() << std::endl;
std::cout << "Book2 Title: " << book2.getTitle() << std::endl;
return 0;
}
- 练习1.14:修改
SalesItem
类,添加一个计算总销售额的成员函数。
- 示例代码:
#include <iostream>
#include <string>
class SalesItem {
public:
SalesItem() = default;
SalesItem(const std::string &book, unsigned sold, double rev)
: bookNo(book), units_sold(sold), revenue(rev) {}
std::string isbn() const { return bookNo; }
double avg_price() const;
double total_revenue() const { return revenue; }
private:
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
double SalesItem::avg_price() const {
if (units_sold) {
return revenue / units_sold;
} else {
return 0;
}
}
int main() {
SalesItem item("12345", 100, 1000.0);
std::cout << "ISBN: " << item.isbn() << std::endl;
std::cout << "Total Revenue: " << item.total_revenue() << std::endl;
return 0;
}
- 练习1.15:为
Book
类添加析构函数,输出书籍对象销毁时的信息。
- 示例代码:
#include <iostream>
#include <string>
class Book {
public:
Book() = default;
Book(const std::string &t, const std::string &a, double p)
: title(t), author(a), price(p) {}
std::string getTitle() const { return title; }
std::string getAuthor() const { return author; }
double getPrice() const { return price; }
~Book() {
std::cout << "Book object for " << title << " is being destroyed" << std::endl;
}
private:
std::string title;
std::string author;
double price = 0.0;
};
int main() {
Book book1("C++ Primer", "Stanley B. Lippman", 59.99);
return 0;
}
总结与提高
本节总结:
- 了解了类的基本概念和定义,包括成员变量和成员函数。
- 通过示例代码,掌握了类的基本用法和常见操作。
提高建议:
- 多练习定义和使用类:通过编写各种类,熟悉类的定义、构造函数和析构函数的使用。
- 理解面向对象编程的基本概念:学习封装、继承和多态等面向对象编程的基本概念,编写更复杂的类。
1.6 书店程序
概述
在本小节中,我们将使用之前学到的C++基础知识,编写一个简单的书店程序。这个程序的目标是处理书籍销售记录,通过对销售数据进行统计,计算销售的总额。
需求描述
书店程序需要完成以下功能:
- 读取一系列书籍的销售记录。
- 统计每种书籍的总销售量和总销售额。
- 输出每种书籍的ISBN、销售总量和总销售额。
数据结构
为了处理书籍销售记录,我们需要定义一个类来表示每一本书的销售数据。该类应该包括以下成员:
- ISBN(书籍编号)
- 销售量
- 总销售额
我们可以重用之前定义的SalesItem
类或定义一个新的类Sales_data
。
定义Sales_data
类
- 类定义:
#include <iostream>
#include <string>
class Sales_data {
public:
// 成员变量
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
// 成员函数
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
};
// 成员函数定义
Sales_data& Sales_data::combine(const Sales_data& rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
double Sales_data::avg_price() const {
if (units_sold) {
return revenue / units_sold;
} else {
return 0;
}
}
代码解析
- 成员变量:
std::string bookNo
:书籍的ISBN编号。unsigned units_sold
:销售量。double revenue
:总销售额。
- 成员函数:
std::string isbn() const
:返回书籍的ISBN编号。Sales_data& combine(const Sales_data&)
:将另一条销售记录的数据合并到当前对象。double avg_price() const
:计算平均售价。
- 成员函数定义:
combine
函数:将传入的Sales_data
对象的销售量和总销售额累加到当前对象。avg_price
函数:计算平均售价,如果销售量为零,则返回零。
实现书店程序
我们将编写一个主函数,用于读取销售记录、统计每种书籍的总销售量和总销售额,并输出结果。
- 主函数实现:
#include <iostream>
#include <string>
#include "Sales_data.h" // 包含Sales_data类定义
int main() {
Sales_data total; // 保存当前书籍的销售总记录
// 读取第一条销售记录
if (std::cin >> total.bookNo >> total.units_sold >> total.revenue) {
Sales_data trans; // 保存每次读取的新销售记录
// 读取并处理剩余的销售记录
while (std::cin >> trans.bookNo >> trans.units_sold >> trans.revenue) {
if (total.isbn() == trans.isbn()) {
total.combine(trans); // 更新当前书籍的总销售记录
} else {
// 输出结果
std::cout << total.isbn() << " "
<< total.units_sold << " "
<< total.revenue << " "
<< total.avg_price() << std::endl;
total = trans; // 处理下一本书的销售记录
}
}
// 输出最后一本书的销售记录
std::cout << total.isbn() << " "
<< total.units_sold << " "
<< total.revenue << " "
<< total.avg_price() << std::endl;
} else {
std::cerr << "No data?!" << std::endl;
return -1; // 表示失败
}
return 0;
}
代码解析
- 变量定义:
Sales_data total
:保存当前书籍的销售总记录。Sales_data trans
:保存每次读取的新销售记录。
- 读取第一条销售记录:
- 使用
std::cin
读取第一条销售记录,并存储到total
对象中。
- 处理剩余销售记录:
- 使用
while
循环读取剩余的销售记录,并存储到trans
对象中。 - 如果当前记录的ISBN与
total
对象的ISBN相同,则调用combine
函数更新总记录。 - 如果ISBN不同,则输出
total
对象的累计结果,并更新total
对象为当前记录。
- 输出最后一本书的销售记录:
- 循环结束后,输出
total
对象的最终累计结果。
- 错误处理:
- 如果没有读取到任何数据,输出错误信息,并返回失败状态。
重点与难点分析
重点:
- 类的定义和使用:复习和应用之前定义的
Sales_data
类,包括成员变量和成员函数。 - 输入输出操作:熟练使用
std::cin
和std::cout
进行数据读取和输出。 - 条件判断和循环控制:使用
if
语句和while
循环控制程序流程。
难点:
- 数据合并逻辑:正确理解和实现
combine
函数的逻辑,确保销售记录的准确累计。 - 输入数据处理:处理标准输入中的数据,并根据ISBN判断是否需要合并或输出结果。
练习题解析
- 练习1.16:编写一个程序,从标准输入读取多条销售记录,并计算每条记录的总和。
- 示例代码:
#include <iostream>
#include <string>
int main() {
Sales_data total;
while (std::cin >> total.bookNo >> total.units_sold >> total.revenue) {
std::cout << "ISBN: " << total.isbn() << ", "
<< "Units Sold: " << total.units_sold << ", "
<< "Revenue: " << total.revenue << ", "
<< "Average Price: " << total.avg_price() << std::endl;
}
return 0;
}
- 练习1.17:修改主程序,增加输入错误处理逻辑,当输入数据格式不正确时,输出错误信息。
- 示例代码:
#include <iostream>
#include <string>
int main() {
Sales_data total;
while (true) {
std::cout << "Enter bookNo, units_sold, and revenue: ";
if (!(std::cin >> total.bookNo >> total.units_sold >> total.revenue)) {
std::cerr << "Input error! Please enter valid data." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
std::cout << "ISBN: " << total.isbn() << ", "
<< "Units Sold: " << total.units_sold << ", "
<< "Revenue: " << total.revenue << ", "
<< "Average Price: " << total.avg_price() << std::endl;
}
}
return 0;
}
- 练习1.18:扩展程序,允许用户输入多组数据,每组数据包含多个销售记录,并计算每组数据的总和。
- 示例代码:
#include <iostream>
#include <string>
int main() {
Sales_data total;
while (true) {
std::cout << "Enter bookNo, units_sold, and revenue (enter 'end' to finish): ";
std::string bookNo;
if (!(std::cin >> bookNo)) break;
if (bookNo == "end") break;
total.bookNo = bookNo;
if (!(std::cin >> total.units_sold >> total.revenue)) {
std::cerr << "Input error! Please enter valid data." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
Sales_data trans;
while (true) {
std::cout << "Enter another record for the same book (enter 'done' to finish this book): ";
std::string transBookNo;
if (!(std::cin >> transBookNo)) break;
if (transBookNo == "done") break;
trans.bookNo = transBookNo;
if (!(std::cin >> trans.units_sold >> trans.revenue)) {
std::cerr << "Input error! Please enter valid data." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (total.isbn() == trans.isbn()) {
total.combine(trans);
} else {
std::cerr << "ISBN mismatch! Please enter the correct record." << std::endl;
}
}
std::cout << "Total for book " << total.isbn() << ": "
<< "Units Sold: " << total.units_sold << ", "
<< "Revenue: " << total.revenue << ", "
<< "Average Price: " << total.avg_price() << std::endl;
}
return 0;
}
总结与提高
本节总结:
- 通过实现书店程序,综合应用了类、输入输出、条件判断和循环控制等C++基础知识。
- 学习了如何定义和使用一个类来处理实际问题中的数据。
- 掌握了如何从标准输入读取数据,处理和统计这些数据,并输出结果。
提高建议:
- 多练习实际应用场景:通过更多实际应用场景的练习,巩固和加深对C++基础知识的理解和应用。
- 优化程序逻辑:在编写程序时,注重代码的结构和逻辑,提高代码的可读性和可维护性。
- 处理输入错误和异常情况:在实际应用中,输入数据可能会有错误,需要学习如何处理这些错误和异常情况,编写健壮的程序。
本主页会定期更新,为了能够及时获得更新,敬请关注我:点击左下角的关注。也可以关注公众号:请在微信上搜索公众号“iShare爱分享”并关注,或者扫描以下公众号二维码关注,以便在内容更新时直接向您推送。