C++ Primer / 第 01 章 / 开始
学习首页 知识地图 速查表
CHAPTER 01 / C++ 基础

开始

从一个最小程序开始,认识编译、运行、输入输出、控制流和函数。·9 个细分单元·建议分 2-3 次阅读
教材对应印刷页:1-23 页 · 本书主线按 C++11 讲解;遇到更新标准的写法会特别注明。
本章先回答一个问题: 程序先经过编译,再在运行时产生输出。把这两步分开,调试时才知道问题在哪里。
下面每个单元包含概念解释、代码、易错点与阅读提示。
零基础读法:先读概念,再预测代码会做什么;然后逐行追踪输入和变量状态,最后不看示例自己复述。遇到陌生词,可以回到第 1-3 章查类型、作用域和对象生命周期。

详细课程

01 · 程序是怎样跑起来的

把源文件想成一份菜谱:预处理器展开头文件,编译器把 C++ 翻译成目标文件,链接器把库函数接进来,最后操作系统才启动可执行文件。遇到错误时先判断它属于哪一阶段。

#include <iostream>
int main() {
  std::cout << "Hello, C++\n";
}
容易踩坑:编译错误通常没有生成可执行文件;运行时错误说明程序已经编译成功,但执行过程出了问题。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

02 · 输入、输出与流

std::cout 是输出流,std::cin 是输入流。<< 把数据送进输出流,>> 从输入流取出数据。一次读取失败后,流会记住失败状态,后面的读取也会停止,直到清除状态。

int age{};
std::cout << "Age: ";
if (std::cin >> age) std::cout << age + 1;
else std::cerr << "请输入整数";
容易踩坑:用 {} 初始化变量,避免未初始化的垃圾值;向用户显示错误时优先使用 cerr。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

03 · 控制流:让程序做决定

if 适合二选一,switch 适合一个值对应多个固定分支,while 适合“只要条件成立就继续”,for 适合有明确计数或遍历范围的任务。每个大括号都可以建立自己的作用域。

for (int i = 1; i <= 3; ++i) {
  if (i == 2) continue;
  std::cout << i << "\n";
}
容易踩坑:循环必须有可变的退出条件;continue 只跳过本轮,break 才会离开整个循环。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

04 · 函数与 Sales_item 思路

把重复的计算提炼成函数,调用者只需要知道参数和返回值。书中的 Sales_item 例子还展示了如何把一个销售记录对象读入、比较 ISBN,并累计销售数量。

int add(int a, int b) { return a + b; }
int main() {
  std::cout << add(2, 3);
}
容易踩坑:先写能工作的 main,再把一段有名字的逻辑搬进函数;函数名应说明动作或结果。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

05 · 小练习

写一个程序,读取若干整数,输出它们的和、平均值和最大值。先用 while 读取,再用函数分别完成统计,最后故意输入一个字母观察流状态。

int x{}, sum{};
while (std::cin >> x) sum += x;
std::cout << sum;
参考思路:练习重点不是代码量,而是观察“输入失败如何结束循环”。
展开参考代码
int x{}, sum{};
while (std::cin >> x) sum += x;
std::cout << sum;

06 · 注释与可读性

注释应该解释“为什么”,而不是把代码逐字翻译成中文。好的命名、短函数和清晰的控制流通常比大段注释更有价值。

// 只解释意图:输入失败时停止统计
while (std::cin >> value) total += value;
容易踩坑:过时的注释比没有注释更危险:代码改了,注释却没改。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

07 · 文件重定向

同一个程序可以从键盘读,也可以从文件读。命令行重定向让测试数据与程序分离,非常适合验证输入输出程序。

std::ifstream in("data.txt");
std::streambuf* old = std::cin.rdbuf(in.rdbuf());
run();
std::cin.rdbuf(old);
容易踩坑:文件打开失败时不要继续假装读到了数据,先检查流状态。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

08 · 从单词统计建立模型

把问题拆成“读取一个单词、更新状态、输出结果”三个动作,能把看似复杂的程序变成一个循环和一个计数器。

std::string word;
std::map<std::string, int> counts;
while (std::cin >> word) ++counts[word];
容易踩坑:先画出状态变化表,再写循环;不要一开始就追求短代码。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。

09 · 本章检查点

你应该能解释源文件、编译器、链接器、可执行文件的关系;能写输入输出和循环;能说出一个类把数据和操作放在一起的原因。

int main() {
  // 入口:组织调用,而不是塞进所有细节
  return 0;
}
容易踩坑:如果只能背语法,说明需要回到“对象、状态、控制流”三个问题重新练习。
自测读法:先遮住代码口述它会做什么;再指出关键变量、边界条件和可能失效的对象。若说不清,回到上面的概念逐句追踪。
REVIEW

本章理解检查

先自己回答,再展开解释。

编译、链接和运行分别做什么?

编译把源代码翻译为目标文件;链接把目标文件和库组合;运行才由操作系统执行程序。

为什么 while (cin >> x) 能结束?

读取成功时流可转换为 true;读到文件末尾或格式错误时流进入失败状态,条件为 false。

main 函数为什么返回 int?

返回值是程序向操作系统报告的结束状态;通常 0 表示成功,非 0 表示遇到问题。

输入读取失败后,变量里一定有新值吗?

不一定。格式不匹配时提取失败,目标变量可能保持原值,因此要先判断流状态再使用读取结果。
NEXT

继续学习

完成本章后,建议进入第 2 章;也可以回到首页查看知识地图或打开交互实验。

LEARN BY CHANGING ONE THING

把“我懂了”,变成一次可验证的预测。

实验都在浏览器中运行,无需安装和上传。·使用教学模型,专注理解规则
LAB 01 / SEQUENCE CONTAINER

vector 会怎样长大?

输入一组整数,逐个 push_back,观察 size、capacity 和重新分配次数。

35711
size = 4capacity ≈ 4扩容次数 = 3
margin-bottom:10px; font-size:18px; }

html.cafe - a realtime HTML editor and host

Edit the html in the top panel, see the result here.
Save your page and get a link to view it live, anywhere.