C++ 编程语法

三、输入与输出

与用户"对话"是程序的基本能力。本章涵盖 cin/cout 的流控制格式化、scanf/printf 的精确控制,以及竞赛 I/O 加速技巧和常用数学库。

输入语句 cin

使用 cin 搭配提取运算符 >> 可以从控制台获取键盘输入。语法是:cin >> 变量;

⌨️ 键盘输入
cin >>
变量
C++ · cin 输入
1// 读取单个变量
2int age;
3cin >> age; // 等待用户输入一个整数,存入 age
4
5// 同时读取多个变量(用空格或回车分隔)
6int a, b;
7cin >> a >> b; // 输入"3 5"→ a=3, b=5
⚠️
注意:cin 默认以空白字符(空格、换行、制表符)作为输入的分隔符。读取字符串时,cin 遇到空格就会停止。要读取含空格的整行内容,需要使用 getline()(详见后续章节)。

输出语句 cout

使用 cout 搭配插入运算符 << 可以将内容输出到控制台。语法是:cout << 输出内容;

变量 / 字符串
cout <<
🖥️ 屏幕输出
C++ · cout 输出
1cout << "Hello, World"; // 输出字符串
2cout << 123; // 输出数字
3cout << 3.14; // 输出小数
4
5// 用 << 连接多项内容
6int age = 15;
7cout << "我今年" << age << "岁"; // 输出:我今年15岁
8
9// 两种换行方式
10cout << "第一行" << endl; // endl:换行 + 刷新缓冲区(较慢)
11cout << "第二行" << "\n"; // \n:只换行,速度更快 ✓ 推荐
endl vs \n:endl 会额外刷新输出缓冲区,速度稍慢;\n 只换行不刷新,速度更快。竞赛编程中大量输出时,推荐用 \n 替代 endl

3.2.1 浮点数精度、域宽、填充 <iomanip>

使用 cout 输出时,可以通过流控制指令精确控制格式。使用这些功能需引入头文件 <iomanip>

流控制指令 功能说明 示例 输出
setprecision(n) 控制浮点数精度。默认设置有效数字位数;配合 fixed 使用时,设置小数点后位数。持续有效,直到再次修改。 cout<<setprecision(2)<<3.141
cout<<fixed<<setprecision(2)<<3.1415
3.1
3.14
setw(n) 设置下一次输出的字段宽度。宽度不足时用填充字符补齐(默认空格右对齐)。一次性,输出后自动恢复。 cout<<setw(5)<<42 42
setfill(c) 设置 setw 补齐时的填充字符,默认是空格。持续有效,直到再次修改。 cout<<setfill('0')<<setw(5)<<7 00007

3.2.2 进制与格式控制

指令功能示例输出
进制输出
oct 整数以八进制输出 cout<<oct<<10 12
dec 整数以十进制输出(默认) cout<<dec<<10 10
hex 整数以十六进制输出 cout<<hex<<10 a
uppercase 配合 hex,字母大写显示 cout<<hex<<uppercase<<255 FF
缓冲区控制
endl 插入换行符并刷新输出缓冲区 cout<<"Hi"<<endl 换行立即显示
flush 刷新缓冲区,插入换行 cout<<"..."<<flush 立即显示不换行
空白字符处理(cin)
skipws 跳过前导空白字符(默认行为) cin>>skipws>>ch 输入" A"读到A
noskipws 不跳过空白,空格也会被读入 cin>>noskipws>>ch 输入" A"读到空格

3.2.3 对齐与显示格式

指令功能示例输出
对齐方式
left setw 宽度内左对齐,右侧填充 cout<<left<<setw(5)<<42 42
right setw 宽度内右对齐(默认) cout<<right<<setw(5)<<42 42
浮点数格式
scientific 浮点数以科学计数法输出 cout<<scientific<<1234.5 1.234500e+03
fixed 浮点数以定点小数方式输出 cout<<fixed<<1.2 1.200000
showpoint 始终显示小数点,即使小数部分为 0 cout<<showpoint<<10.0 10.0000
符号与前缀
showbase 显示进制前缀(八进制加 0,十六进制加 0x cout<<hex<<showbase<<255 0xff
showpos 正数前显示 + cout<<showpos<<42 +42

格式化输入 scanf()

scanf() 是 C 语言的格式化输入函数,在 C++ 中同样可用。相比 cinscanf() 在大量数据输入时效率更高。

语法:scanf("格式字符", &变量); 注意变量名前必须加取址符 &

C++ · scanf 示例
1int year, month;
2scanf("%d %d", &year, &month); // 注意:变量前必须加 &

3.3.1 常见类型格式符

格式符数据类型示例输出
%c char scanf("%c", &ch) 读取单个字符
%d int scanf("%d", &n) 读取整数
%lld long long scanf("%lld", &n) 读取长整型
%f float scanf("%f", &x) 读取单精度浮点
%lf double scanf("%lf", &x) 读取双精度浮点
💡
scanf 的返回值:scanf 返回成功读取的变量个数。例如 while(scanf("%d", &n) == 1) 可以持续读入直到输入结束(EOF),这在竞赛中处理不定量输入时非常实用。

格式化输出 printf()

printf() 是 C 语言的格式化输出函数,在 C++ 中同样可用。格式控制比 cout 更简洁直观,执行效率也更高。

语法:printf("格式化字符串", 变量1, 变量2, ...); 其中 % 开头的占位符会被对应变量的值替换,变量数量必须与占位符个数一致。

C++ · printf 基本用法
1int age = 15;
2printf("我今年%d岁\n", age); // %d 对应整数
3float score = 98.5;
4printf("成绩是%f分\n", score); // %f 对应 float

3.4.1 数字位数与精度控制

格式符含义示例输出
%nd 整数占 n 位宽,右对齐,不足补空格 printf("%5d", 123) 123
%0nd 整数占 n 位宽,右对齐,不足补 0 printf("%05d", 1) 00001
%.nf float 保留 n 位小数(四舍五入) printf("%.3f", 3.14159f) 3.142
%.nlf double 保留 n 位小数(四舍五入) printf("%.5lf", 3.14) 3.14000
C++ · printf 格式控制示例
1printf("int指定宽度:%5d\n", 123); // " 123"
2printf("int用零填充:%05d\n", 123); // "00123"
3printf("float保留3位小数:%.3f\n", 1.23456f); // "1.235"
4printf("double保留3位小数:%.3lf\n", 1.23456); // "1.235"
📌
默认精度:printf 输出浮点数默认保留 6 位小数,不足 6 位以 0 补齐,超出 6 位的四舍五入。

cin / cout 与 scanf / printf 的效率对比与优化

这是竞赛中极其重要的知识点,大量 I/O 时选错方式可能直接超时!

🐢 默认 cin / cout
scanf / printf 慢很多,因为 C++ 为了兼容 C 的 I/O,默认让 cin / coutscanf / printf 的缓冲区同步,同步本身有开销。
加速后 cin / cout
关闭同步后,cin / cout 速度通常可以反超 scanf / printf,且代码更简洁易读。

优化方法:在 main() 开头加两行

C++ · I/O 加速模板
1int main()
2{
3 ios::sync_with_stdio(false); // 关闭 C/C++ I/O 同步
4 cin.tie(0); // 解除 cin 与 cout 的绑定
5 // ... 你的代码 ...
6 return 0;
7}
🚫
警告:关闭同步后,不要混用 cin / coutscanf / printf,否则可能导致输出顺序混乱。选择一种 I/O 方式并坚持使用。
🏆
竞赛习惯:输入输出量不大时用 cin / cout(代码简洁);大输入量时用 scanf / printf,或在加上两行加速代码后用 cin / cout

综合示例 — 读取并格式化输出时间

读取小时和分钟,格式化输出为 HH:MM 的形式(不足两位时补零)。这是竞赛中常见的输入输出格式化需求。

C++ · 时间格式化输出
1#include <cstdio> // printf / scanf
2using namespace std;
3
4int main()
5{
6 int h, m;
7 scanf("%d%d", &h, &m); // 输入:9 5
8 printf("%02d:%02d\n", h, m); // 输出:09:05(不足两位补 0)
9 return 0;
10}

cmath 数学库

<cmath> 内置了许多常用的数学计算函数,使用前需要先引入头文件 #include <cmath>

函数功能说明示例结果
abs(x) 返回 x 的绝对值(C++11 起同时支持整数和浮点数) abs(-5) 5
ceil(x) 向上取整(不小于 x 的最小整数) ceil(1.123) 2
floor(x) 向下取整(不大于 x 的最大整数) floor(1.91) 1
fabs(x) 浮点数 x 的绝对值(C 语言遗留,C++11 后可直接用 abs fabs(-3.14) 3.14
pow(x, y) 返回 x 的 y 次幂(返回 double) pow(2, 3) 8
round(x) 四舍五入为最近整数(C++11) round(1.5) 2
sqrt(x) 返回 x 的算术平方根(返回 double) sqrt(9) 3
cos(x) 计算 x(弧度制)的余弦值 cos(0) 1
sin(x) 计算 x(弧度制)的正弦值 sin(0) 0
tan(x) 计算 x(弧度制)的正切值 tan(0) 0
C++ · cmath 示例
1#include <iostream>
2#include <cmath>
3using namespace std;
4
5int main()
6{
7 cout << abs(-42) << endl; // 42
8 cout << ceil(4.1) << endl; // 5
9 cout << floor(4.9) << endl; // 4
10 cout << pow(2, 8) << endl; // 256
11 cout << round(4.5) << endl; // 5
12 cout << sqrt(16) << endl; // 4
13 return 0;
14}
⚠️
浮点精度陷阱:powsqrt 返回 double 类型,赋值给整数时可能因浮点误差出错。例如 int x = sqrt(25) 理论上得 5,但浮点精度问题可能得到 4.999999,截断后变成 4。
安全做法:int x = (int)round(sqrt(25));
📖
C++11 中 abs 的改进:C++11 起,<cmath> 中的 abs 已针对 doublefloatlong double 做了重载,可以直接对浮点数使用 abs(),不再需要单独用 fabs()。绝大多数现代 OJ 平台支持 C++11,直接用 abs 即可。