scanf 和printf 是C语言中的标砖输入输出函数,而cin 和cout 是C++语言中的必遭护照那输入输出流对象。它们各自有优缺点,整体上来说cin 和cout 会更方便,但有时候我们也不得不使用scanf 和printf 。
1. 格式控制差异
sacnfhe1printf不能自动识别输入数据的类型,选哟手动指定格式字符串,容易出现格式错误。我们需要确保格式字符串与变量类型匹配,否则会导致未定义行为。cin和cout会根据变量类型自动处理输入输出,避免格式错误。相对scanf和pintf来说,C++的cin和cout更加易用。scanf和printf:格式化输出更精确直观,特别适合复杂格式的输入输出,比如:在要求指定格式输出的时候,printf函数就比cout更加方便和灵活。
#include <iostream>
#include <string>
using namespace std;
int main()
{
float a = 3.50;
double d = 16.50;
cout << "cout" << a << " " << d << endl;
printf("printf: %f %lf\n", a, d);
return 0;
}
输入结果如下:

区别:
cout默认不会输出六位小数,自动忽略小数点后多余的0,printf函数打印浮点数的时候,小数点默认打印6位。cout在输出的时候不与要指定格式,printf则需要明确的格式。
2. 性能差异
2.1 案例演示
结论:scanf 和printf 通常比cin 和cout 快。
**原因:**cin和cout由于要考虑兼容C语言的输入和输出,封装实现更加复杂,通常比scanf和printf稍慢,这种差异在大多数应用场景中可以忽略不计。
但是在竞赛题目中,尤其是当输入、输出数据量较大时,使用cin和cout完成输入输出,经常会出现超时。而scanf 和printf 就不存在类似的问题。
请看下面案例,我们来对比一下:
案例:数字游戏
使用cin 和cout :
#include <iostream>
using namespace std;
int t, x;
int main()
{
cin >> t;
while (t--)
{
cin >> x;
int ret = 0;
while (x)
{
int count = 0, high = 0;
int tmp = x;
while (tmp)
{
//计算最右边的1代表的值
int low = tmp & -tmp;
//如果low中剩余的1就是最后一个1
//就是最左边的1
if (tmp == low)
{
high = low;
}
//去掉最右边的1
tmp -= low;
count++;
}
if (count % 2 == 0)
{
x -= high;
}
else
{
x ^= 1;
}
ret++;
}
cout << ret <<endl;
}
return 0;
}
使用scanf 和printf
#include <iostream>
using namespace std;
int t, x;
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &x);
int ret = 0;
while (x)
{
int count = 0, high = 0;
int tmp = x;
while (tmp)
{
//计算最右边的代表的值
int low = tmp & - tmp;
//如果low中剩余的1就是最后一个1
//就是最左边的1
if (tmp == low)
{
high = low;
}
//去掉最右边的1
tmp -= low;
count++;
}
if (count % 2 == 0)
{
x -= high;
}
else
{
x ^= 1;
}
ret++;
}
printf("%d\n", ret);
}
return 0;
}
可以看出,在这个案例中输入的数据量是比较大的。在输入数据的时候如果使用cin ,会出现超时的问题,但是换成scanf 的方式就能正确的通过。这就是因为两者性能上的差异导致的。
为什么cin/cout 的性能要低于scanf/printf 呢?
有什么办法能优化吗?
参考这篇:
【提高】std::ios::sync_with_stdio(false)的作用和原理
总结:
- C++中为了支持混合使用
cin/cout和scanf/printf,C++标准库默认会将cin、cout等C++流对象与stdin、stdout等C标准库的流对象同步在一起。这种同步操作意味着每次使用cin或cout时,都会自动刷新C便准库的缓冲区,。以确保C++和C的I/O是一致的。这就导致了性能的下降。 - 在默认情况下,
cin和cout之间存在一种绑定关系。这种绑定意味着,每当从cin读取数据时,任何之前通过cout输出的内容都hi被强制刷新到屏幕上。这种绑定也看了能导致性能问题,特别是在需要频繁读取大量数据的情况下。
2.2 优化方案
下面我们看一下scanf 和cin 的差异,然后看看如何进行优化。
代码:
#include <iostream>
#include <ctime>
#include <cstdio>
using namespace std;
const int num = 10000000;
int main()
{
int i, x;
//freopen是将stdin重定向到文件
//意思是scanf可以文件中读取数据
freopen("data.txt", "r", stdin);
clock_t t1, t2;
t1 = clock();
for (i = 0; i < num; i++)
{
scanf("%d", &x);
}
t2 = clock();
cout << "Runtime of scanf: " << t2 - t1 << " ms" << endl;
return 0;
}
#include <iostream>
#include <ctime>
#include <cstdio>
using namespace std;
const int num = 10000000;
int main()
{
//freopen是将stdin重定向到文件
//意思是scanf可以文件中读取数据
freopen("data.txt", "r", stdin);
int i, x;
clock_t t1, t2;
t1 = clock();
for (i = 0; i < num; i++)
{
cin >> x;
}
t2 = clock();
cout << "Runtime of cin: " << t2 - t1 << " ms" << endl;
return 0;
}


用一个测试数据文件举例。
对cin 进行优化,代码如下:
#include <iostream>
#include <ctime>
#include <cstdio>
using namespace std;
const int num = 10000000;
int main()
{
ios::sync_with_stdio(false); //取消C语言输入输出区的同步
cin.tie(0); //取消cin和cout的绑定
freopen("data.txt", "r", stdin);
int i, x;
clock_t t1, t2;
t1 = clock();
for (i = 0; i < num; i++)
{
cin >> x;
}
t2 = clock();
cout << "Runtime of cin: " << t2 - t1 << " ms" << endl;
return 0;
}
运行结果:

所以我们在使用sanf /printf 和cin /cout 抉择的时候,如果要追求性能,那就用scanf /printf ,或者优化后的cin /cout ,如果不追求性能,直接用cin /cout 就行。
Tips:
- 如果输入的数据量比较小(10^6以内),用
cin和cout或者scanf和printf都行; - 如果输入的数据量比较大(10^9左右),更推荐使用
scanf和printf,避免因为输入输出的开销,导致代码超时; - 在大多数场景下
printf/scanf和cin/cout的使用根据个人习惯进行选择即可。
这里我们讨论了scanf/printf 和cin/cout 性能的差异,我们知道scanf/printf 是更快的,其实有一些极端情况下,输入输出的规模非常大的时候,scanf 和printf 也不能满足的时候,会使用快速读写的方式(后续更新)。
——scanfprintf和cincout对比&spm=1001.2101.3001.5002&articleId=155613115&d=1&t=3&u=c4c4164fac054639afded6975a08d07f)

被折叠的 条评论
为什么被折叠?



