C++ 编程语法
与用户"对话"是程序的基本能力。本章涵盖 cin/cout 的流控制格式化、scanf/printf 的精确控制,以及竞赛 I/O 加速技巧和常用数学库。
3.1
使用 cin 搭配提取运算符 >> 可以从控制台获取键盘输入。语法是:cin >> 变量;
| 1 | // 读取单个变量 |
| 2 | int age; |
| 3 | cin >> age; // 等待用户输入一个整数,存入 age |
| 4 | |
| 5 | // 同时读取多个变量(用空格或回车分隔) |
| 6 | int a, b; |
| 7 | cin >> a >> b; // 输入"3 5"→ a=3, b=5 |
cin 默认以空白字符(空格、换行、制表符)作为输入的分隔符。读取字符串时,cin 遇到空格就会停止。要读取含空格的整行内容,需要使用 getline()(详见后续章节)。3.2
使用 cout 搭配插入运算符 << 可以将内容输出到控制台。语法是:cout << 输出内容;
| 1 | cout << "Hello, World"; // 输出字符串 |
| 2 | cout << 123; // 输出数字 |
| 3 | cout << 3.14; // 输出小数 |
| 4 | |
| 5 | // 用 << 连接多项内容 |
| 6 | int age = 15; |
| 7 | cout << "我今年" << age << "岁"; // 输出:我今年15岁 |
| 8 | |
| 9 | // 两种换行方式 |
| 10 | cout << "第一行" << endl; // endl:换行 + 刷新缓冲区(较慢) |
| 11 | cout << "第二行" << "\n"; // \n:只换行,速度更快 ✓ 推荐 |
endl 会额外刷新输出缓冲区,速度稍慢;\n 只换行不刷新,速度更快。竞赛编程中大量输出时,推荐用 \n 替代 endl。<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 |
| 指令 | 功能 | 示例 | 输出 |
|---|---|---|---|
| 进制输出 | |||
| 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"读到空格 |
| 指令 | 功能 | 示例 | 输出 |
|---|---|---|---|
| 对齐方式 | |||
| 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 |
3.3
scanf() 是 C 语言的格式化输入函数,在 C++ 中同样可用。相比 cin,scanf() 在大量数据输入时效率更高。
语法:scanf("格式字符", &变量); 注意变量名前必须加取址符 &。
| 1 | int year, month; |
| 2 | scanf("%d %d", &year, &month); // 注意:变量前必须加 & |
| 格式符 | 数据类型 | 示例 | 输出 |
|---|---|---|---|
| %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 返回成功读取的变量个数。例如 while(scanf("%d", &n) == 1) 可以持续读入直到输入结束(EOF),这在竞赛中处理不定量输入时非常实用。3.4
printf() 是 C 语言的格式化输出函数,在 C++ 中同样可用。格式控制比 cout 更简洁直观,执行效率也更高。
语法:printf("格式化字符串", 变量1, 变量2, ...); 其中 % 开头的占位符会被对应变量的值替换,变量数量必须与占位符个数一致。
| 1 | int age = 15; |
| 2 | printf("我今年%d岁\n", age); // %d 对应整数 |
| 3 | float score = 98.5; |
| 4 | printf("成绩是%f分\n", score); // %f 对应 float |
| 格式符 | 含义 | 示例 | 输出 |
|---|---|---|---|
| %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 |
| 1 | printf("int指定宽度:%5d\n", 123); // " 123" |
| 2 | printf("int用零填充:%05d\n", 123); // "00123" |
| 3 | printf("float保留3位小数:%.3f\n", 1.23456f); // "1.235" |
| 4 | printf("double保留3位小数:%.3lf\n", 1.23456); // "1.235" |
printf 输出浮点数默认保留 6 位小数,不足 6 位以 0 补齐,超出 6 位的四舍五入。3.5
这是竞赛中极其重要的知识点,大量 I/O 时选错方式可能直接超时!
scanf / printf 慢很多,因为 C++ 为了兼容 C 的 I/O,默认让 cin / cout 与 scanf / printf 的缓冲区同步,同步本身有开销。cin / cout 速度通常可以反超 scanf / printf,且代码更简洁易读。| 1 | int main() |
| 2 | { |
| 3 | ios::sync_with_stdio(false); // 关闭 C/C++ I/O 同步 |
| 4 | cin.tie(0); // 解除 cin 与 cout 的绑定 |
| 5 | // ... 你的代码 ... |
| 6 | return 0; |
| 7 | } |
cin / cout 与 scanf / printf,否则可能导致输出顺序混乱。选择一种 I/O 方式并坚持使用。cin / cout(代码简洁);大输入量时用 scanf / printf,或在加上两行加速代码后用 cin / cout。3.6
读取小时和分钟,格式化输出为 HH:MM 的形式(不足两位时补零)。这是竞赛中常见的输入输出格式化需求。
| 1 | #include <cstdio> // printf / scanf |
| 2 | using namespace std; |
| 3 | |
| 4 | int 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 | } |
3.7
<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 |
| 1 | #include <iostream> |
| 2 | #include <cmath> |
| 3 | using namespace std; |
| 4 | |
| 5 | int 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 | } |
pow 和 sqrt 返回 double 类型,赋值给整数时可能因浮点误差出错。例如 int x = sqrt(25) 理论上得 5,但浮点精度问题可能得到 4.999999,截断后变成 4。int x = (int)round(sqrt(25));<cmath> 中的 abs 已针对 double、float、long double 做了重载,可以直接对浮点数使用 abs(),不再需要单独用 fabs()。绝大多数现代 OJ 平台支持 C++11,直接用 abs 即可。