cin/cout与scanf/printf
中等12让程序“开口说话”和“听懂指令”:C++的输入输出两套神功
我们的程序就像一个有智能的机器人,需要跟人类交流。它要把计算结果“说”给我们听(输出),也要接收我们从键盘敲进去的指令(输入)。C++为我们准备了两种主流方式:一种是C++自带的 cin/cout(像用标准普通话交谈,简单自然),另一种是从C语言继承来的 scanf/printf(像用摩斯密码,需要对照表,但速度快)。
不管哪种方法,都是为了实现同一个目标:人与程序的数据交换。
一、C++风格:cin 和 cout —— “聊天式”输入输出
1. 它长什么样?
- 输出:
cout << "内容" << 变量;(符号<<像是一个“数据流动的管道”,把数据从程序内部送到屏幕) - 输入:
cin >> 变量;(符号>>像是一个“数据流入的管道”,把键盘敲的内容存入变量)
2. 使用步骤
第一步:在代码开头包含头文件 <iostream>(iostream = input output stream 输入输出流)
第二步:写一句 using namespace std; 就可以直接写 cin 和 cout,不用每次加上 std::(就像你去朋友家玩,先打招呼“我不客气了”,后面就能随便拿零食吃)
3. 生活例子:计算零花钱
小明每周有零花钱 20 元,他想知道自己一个月的零花钱总和。程序像这样和他聊天:
#include <iostream>
using namespace std;
int main() {
int week_money; // 每周零花钱(整数)
cout << "请输入你每周的零花钱(元): "; // 程序主动提问
cin >> week_money; // 用户输入数字,按回车
int total = week_money * 4; // 一个月按4周算
cout << "你一个月共有 " << total << " 元零花钱!" << endl; // 输出结果
return 0;
}
运行示例:
请输入你每周的零花钱(元): 20
你一个月共有 80 元零花钱!
endl 的作用是换行并刷新输出缓冲区,可以理解成“说完一句话后按回车,让下一句话另起一行”。也可以用 "\n" 代替。
4. cin和cout的优势
- 类型安全:不需要记住格式符。你声明
int它就当整数读,声明double它就当小数读。 - 直观好记:
>>和<<像箭头,指向数据流动方向。cout <<往屏幕流,cin >>往变量流。 - 连续操作:可以一次输入多个数据。比如:
int a, b; // 两个整数
cin >> a >> b; // 输入:10 20 会分别存入a和b
cout << a << " + " << b << " = " << a+b << endl; // 输出:10 + 20 = 30
二、C风格:scanf 和 printf —— “电报式”输入输出
1. 它长什么样?
- 输出:
printf("格式字符串", 变量1, 变量2, ...);
格式字符串里放占位符,比如%d表示整数位置,%lf表示双精度小数位置。 - 输入:
scanf("格式字符串", &变量1, &变量2, ...);
注意!变量前面必须加&(取地址符),表示“请把数据放到这个变量的地址里”。(可以想象成快递员送包裹,他需要知道你的家庭地址,&就是告诉它地址)
2. 使用步骤
头文件:<cstdio>(C++版本)或 <stdio.h>。同样建议写 using namespace std;。
3. 生活例子:考试平均分
班里有两科考试成绩,想算平均分:
#include <cstdio>
using namespace std;
int main() {
double math, english; // 数学和英语成绩(小数)
printf("请输入数学和英语成绩(用空格隔开): ");
scanf("%lf %lf", &math, &english); // %lf读取double类型
double avg = (math + english) / 2.0;
printf("平均分是 %.2f\n", avg); // %.2f 表示保留两位小数
return 0;
}
运行示例:
请输入数学和英语成绩(用空格隔开): 88.5 92.0
平均分是 90.25
4. 常见格式符对照表(一定要记熟!)
| 数据类型 | 格式符 | 示例 |
|---|---|---|
| int (整数) | %d | scanf("%d", &age); |
| long long (长整数) | %lld | scanf("%lld", &big); |
| float (单精度小数) | %f | scanf("%f", &height); |
| double (双精度小数) | %lf | 输入用%lf,输出用%f(C++中可混用) |
| char (字符) | %c | scanf("%c", &ch); |
| 字符串 (char数组) | %s | scanf("%s", str); 此时不用加& |
5. scanf和printf的优势
- 速度极快:专门为竞赛设计,当输入/输出几万、几十万个数据时,比cin/cout快好几倍。
- 格式控制灵活:可以精确控制输出宽度、小数位数(比如
%5d占5个字符宽度,右对齐;%.2f保留两位小数)。
三、两者对比:什么时候用哪个?
| 对比项 | cin / cout | scanf / printf |
|---|---|---|
| 速度 | 较慢(尤其大量数据) | 极快(竞赛首选) |
| 类型安全 | 自动匹配,不易出错 | 格式符写错可能读取乱码 |
| 代码简洁性 | 自然流畅,适合初学者 | 需要记忆格式符,需要写& |
| 调试友好 | 配合调试器更舒服 | 输出格式不小心会崩 |
| 竞赛建议 | 可以用,但注意关闭同步流(后面讲) | 大量数据时推荐 |
初学者建议:平时练习多用 cin/cout,理解清楚了再挑战 scanf/printf。但如果你要参加CSP-J/S,务必熟练掌握 scanf/printf,因为比赛数据量大,快一点是一点。
四、新手最容易犯的错误(一定注意!)
错误1:scanf里忘记写 &
int score;
scanf("%d", score); // 错误!应该写 &score
后果:程序会崩溃,或者读入一个莫名其妙的值。因为 scanf 不知道把数据存到哪里。
错误2:格式符和变量类型不匹配
double pi = 3.14159;
printf("%d", pi); // 错误!double应该用%f或%lf
后果:屏幕会输出一个无意义的数字。因为 %d 按照整数的格式去取内存里的字节,结果完全错位。
错误3:cin和cout与某些同步设置(进阶)
如果你在竞赛中坚持用cin/cout,可以在代码开头加一句:
ios::sync_with_stdio(false);
cin.tie(0);
这能大大加快cin/cout的速度,让它几乎赶上scanf/printf。否则遇到 10万 个数据,cin可能超时。
五、完整示例:计算全班总成绩和平均分
我们用两种方式写同一个功能,展示完整体验。
#include <iostream> // 用于cin/cout
#include <cstdio> // 用于scanf/printf
using namespace std;
int main() {
// 第一部分:用cin/cout处理
int count; // 学生人数
cout << "请输入班级学生人数: ";
cin >> count;
// 假设输入5个成绩,计算总和和平均分
double sum = 0.0; // 总成绩
double score; // 当前成绩
cout << "请依次输入 " << count << " 个成绩(用空格或回车分隔): ";
for (int i = 0; i < count; i++) { // 循环读取
cin >> score;
sum += score;
}
cout << "cin/cout 计算的结果:" << endl;
cout << "总成绩 = " << sum << endl;
cout << "平均分 = " << sum / count << endl;
// 第二部分:用scanf/printf处理(再读一次数据,演示另一种方式)
printf("\n现在用 scanf/printf 再来一次:\n");
int n; // 学生人数
printf("请输入班级学生人数: ");
scanf("%d", &n);
double total = 0.0; // 总成绩
double s; // 当前成绩
printf("请依次输入 %d 个成绩: ", n);
for (int i = 0; i < n; i++) {
scanf("%lf", &s); // 注意double用%lf
total += s;
}
printf("总成绩 = %.0f\n", total); // %.0f 表示不保留小数
printf("平均分 = %.2f\n", total / n); // 保留两位小数
return 0;
}
运行效果(用户输入一样):
请输入班级学生人数: 5
请依次输入 5 个成绩(用空格或回车分隔): 88 92 76 85 90
cin/cout 计算的结果:
总成绩 = 431
平均分 = 86.2
现在用 scanf/printf 再来一次:
请输入班级学生人数: 5
请依次输入 5 个成绩: 88 92 76 85 90
总成绩 = 431
平均分 = 86.20
可以看到,两种方式得到的结果完全相同,只是写法不同。
scanf读double时必须用%lf,但printf输出double用%f或%lf都可以(C++允许)。printf可以用%.2f控制小数位数,这是cout不容易直接做到的事。
六、相关知识点指引
- 格式化输出更高阶:
printf的宽度控制(如%5d、%-5d)能对整齐表格,适合输出商品价格、成绩单。 - 字符串输入:
cin >> string只能读取不含空格的单词;scanf("%s", ...)也类似。要读取一整行(包括空格),需要学习cin.getline()或gets()(已废弃)。 - 文件输入输出:当数据量极大时,可以重定向
freopen从文件读取或写入文件,这在竞赛中非常常见。 - 输入输出的缓冲区:为什么
printf比cout快?可以了解缓冲区刷新机制,以及如何用endl或flush控制刷新。 - 各种数据类型:
int、long long、double、char等如何选择,决定了该用哪种格式符。
总结:
cin/cout像和蔼的老师,耐心又直观;scanf/printf像特快专递,快但需要小心填写地址(格式符)。两种方法都很重要,先学懂一种,再对比掌握另一种。多写几个小程序,比如计算器、猜数字、成绩统计,你就再也不怕输入输出了!
例题精讲
在C++中,要输出浮点数变量x(double类型)并保留三位小数,以下哪种写法是正确的?
关于C++的cin/cout与C的scanf/printf,下列说法错误的是?
在C++中,使用cin语句读取变量时,需要传递变量的地址。
使用printf函数输出字符串时,可以使用%s格式说明符,并传入字符串数组名。
以下程序读入两个整数a和b,输出它们的乘积,输出格式为 "Product: 乘积" 并换行。请使用C风格的输入输出函数填空。
#include <cstdio>
using namespace std;
int main() {
int a, b;
___; // 输入a和b
___; // 输出乘积并换行
return 0;
}