CC++ & Algorithm

cin/cout与scanf/printf

中等12
语言版本:C++
概述:学会两种让程序“说话”和“听话”的方法:C++风格和C风格。

让程序“开口说话”和“听懂指令”:C++的输入输出两套神功

我们的程序就像一个有智能的机器人,需要跟人类交流。它要把计算结果“说”给我们听(输出),也要接收我们从键盘敲进去的指令(输入)。C++为我们准备了两种主流方式:一种是C++自带的 cin/cout(像用标准普通话交谈,简单自然),另一种是从C语言继承来的 scanf/printf(像用摩斯密码,需要对照表,但速度快)。
不管哪种方法,都是为了实现同一个目标:人与程序的数据交换


一、C++风格:cin 和 cout —— “聊天式”输入输出

1. 它长什么样?

  • 输出cout << "内容" << 变量; (符号 << 像是一个“数据流动的管道”,把数据从程序内部送到屏幕)
  • 输入cin >> 变量; (符号 >> 像是一个“数据流入的管道”,把键盘敲的内容存入变量)

2. 使用步骤

第一步:在代码开头包含头文件 <iostream>(iostream = input output stream 输入输出流)
第二步:写一句 using namespace std; 就可以直接写 cincout,不用每次加上 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 (整数)%dscanf("%d", &age);
long long (长整数)%lldscanf("%lld", &big);
float (单精度小数)%fscanf("%f", &height);
double (双精度小数)%lf输入用%lf,输出用%f(C++中可混用)
char (字符)%cscanf("%c", &ch);
字符串 (char数组)%sscanf("%s", str); 此时不用加&

5. scanf和printf的优势

  • 速度极快:专门为竞赛设计,当输入/输出几万、几十万个数据时,比cin/cout快好几倍。
  • 格式控制灵活:可以精确控制输出宽度、小数位数(比如 %5d 占5个字符宽度,右对齐;%.2f 保留两位小数)。

三、两者对比:什么时候用哪个?

对比项cin / coutscanf / 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

可以看到,两种方式得到的结果完全相同,只是写法不同。

  • scanfdouble 时必须用 %lf,但 printf 输出 double%f%lf 都可以(C++允许)。
  • printf 可以用 %.2f 控制小数位数,这是 cout 不容易直接做到的事。

六、相关知识点指引

  • 格式化输出更高阶printf 的宽度控制(如 %5d%-5d)能对整齐表格,适合输出商品价格、成绩单。
  • 字符串输入cin >> string 只能读取不含空格的单词;scanf("%s", ...) 也类似。要读取一整行(包括空格),需要学习 cin.getline()gets()(已废弃)。
  • 文件输入输出:当数据量极大时,可以重定向 freopen 从文件读取或写入文件,这在竞赛中非常常见。
  • 输入输出的缓冲区:为什么 printfcout 快?可以了解缓冲区刷新机制,以及如何用 endlflush 控制刷新。
  • 各种数据类型intlong longdoublechar 等如何选择,决定了该用哪种格式符。

总结:cin/cout 像和蔼的老师,耐心又直观;scanf/printf 像特快专递,快但需要小心填写地址(格式符)。两种方法都很重要,先学懂一种,再对比掌握另一种。多写几个小程序,比如计算器、猜数字、成绩统计,你就再也不怕输入输出了!

例题精讲

1单选题

在C++中,要输出浮点数变量x(double类型)并保留三位小数,以下哪种写法是正确的?

Acout << fixed << setprecision(3) << x;
Bcout << setprecision(3) << x;
Cprintf("%.3d", x);
Dprintf("%3f", x);
2单选题

关于C++的cin/cout与C的scanf/printf,下列说法错误的是?

Acin/cout是类型安全的,而scanf/printf不是。
B默认情况下,cin/cout与scanf/printf的速度相同。
C可以通过取消同步来提高cin/cout的速度。
D混用cin/cout和scanf/printf可能导致输入输出顺序错乱。
3判断题

在C++中,使用cin语句读取变量时,需要传递变量的地址。

4判断题

使用printf函数输出字符串时,可以使用%s格式说明符,并传入字符串数组名。

5填空题
以下程序读入两个整数a和b,输出它们的乘积,输出格式为 "Product: 乘积" 并换行。请使用C风格的输入输出函数填空。

#include <cstdio>
using namespace std;
int main() {
    int a, b;
    ___; // 输入a和b
    ___; // 输出乘积并换行
    return 0;
}