C++输入输出:iostream还是cstdio?

本来博客的题目是 <iostream>还是<cstdio>?结果回头一看题目变成了 还是? 气死了(╯#-_-)╯(难道<>里面的被当做注释了吗)

经常说<cstdio>里面的函数比<iostream>里面的运算符快,事实真的如此吗?本蒟蒻今天亲自测试了一下。

环境:Win7 64bit,CPU主频:2.30GHz

说明:以下程序中,主函数返回值是I/O操作花费的时间,单位:ms(可以参考clock()函数的用法 )(另外,别喷控制台背景颜色和Dev-C++qwq)

思路:用一个1~100000的for循环重复进行I/O操作,并计时,就像把一塌纸摞起来以测一张纸的厚度一样。

一、输出

1.不加优化的cout:

循环十万次,输出i,用时15585ms。

2.加优化的cout:

用时仅为6867ms,测得ios::sync_with_stdio用时0ms。

3.加优化的cerr:

cerr不加缓冲区,所以较慢:10961ms。

4.至于printf:

足足用了31秒!还是不要用了。。。原因应该是cout输出的数据类型是编译时确定的,而printf是根据%d、%c、%p、%s等在运行时确定的,要花更多的时间。不过和电脑性能可能也有关系。

5.顺便说一下,加优化的cout再用

for(register int i=1;i<=100000;++i)

(register)优化用时6772ms,快了95ms;另外,觉不要自己写递归版的输出优化...不信可以试试。

二、输入

没办法一个一个数敲,果断决定从文件输入。

文件1.txt内容如下(内容为1~100000的每个整数):

1.不加优化的cin:

只用了132ms。

2.加优化的cin:

只用了21ms!

3.scanf:

用时93ms。

4.目前市面上有一种读入优化,本蒟蒻亲自试了试:

(1)使用getchar():

①不判断负号:

只用了31ms。

②判断负号:

差别不大,30ms。

(2)使用加ios::sync_with_stdio(false)的cin.get():

用时32ms。

综上所述,输入输出都不要自己写优化了,原生的就是最好的,用了万能的

ios::sync_with_stdio(false);

后,cin、cout就可以带OIer们起飞了。(建议32位系统的julao们自己也测试一下。QAQ)

后记一:

所谓

ios::sync_with_stdio(false);

,指的是让cin、cout放飞自我,不用与stdio同步(sync,synchronize/ˈsɪŋkrənaɪz/,同步)。后果是:如果一边用cin、cout,一边用scanf、printf,就像这样:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
	ios::sync_with_stdio(false);
	for(int i=1;i<=100000;++i)cout<<i<<' ',printf("%d\n",i);
	return 0;
}

期望结果:

......
99993 99993
99994 99994
99995 99995
99996 99996
99997 99997
99998 99998
99999 99999
100000 100000

但是实际结果是这样的:

各按各的套路出牌。。。完全不在一个频道上。。。(虽然都向stdout写入)

看清楚“同步”的作用了吧!所以,要抛弃stdio,就要抛地彻底,不留痕迹!qwq

后记二:

还有一个意想不到的事实!对于输出时换行这件事情,本蒟蒻又有了新的发现:

这是不换行的结果:

用时629ms;

这是用'\n'换行的结果:

用时2068ms;

这是用endl换行的结果:

就像前面提到的,用时6s多(同一个代码不同时间测试结果稍有不同)。

发现'\n'快了好多!

原因大概是endl调用了flush(冲厕所|刷新缓冲区)函数,浪费了一些时间:

所以换行不要用endl啦!

(此外,把'\n'改为"\n",稍稍慢了一点,约100ms)

后记三:

有同学说cout重定向到文件,效率会大打折扣?本蒟蒻又试了一下。

这次数据规模1e6。输出文件:1.txt。

(一)一开始文件不存在

1.cout+ios::sync_with_stdio(false)+endl:

13.65s。

2.printf:

只用了0.9112s!什么?cout跌落神坛?这究竟是人性的泯灭还是道德的沦丧?

3.别急,我说过,endl是个坑,不要故意往里跳。

cout+ios::sync_with_stdio(false)+'\n':

哈哈,printf败下阵来!0.4732s!

(二)一开始已经有1.txt文件

这种情况下花的时间要多,大概是因为要把原文件地址重新标记为可写,就像彻底删除文件,虽然只是标记为可写,但也需要一定的时间。

我们只需比较cout+'\n'和printf。

但是遇到了一些问题,由于每次结果不同,出现了有时cout快、有时printf快的情况,不过无伤大雅,因为CSP中不存在评测前就有*.out的情况。

总之,cout才是王道,又笨又慢还不安全的printf,再见啦!

要点总结:

1.用cin、cout,而不是scanf、printf;

2.用ios::sync_with_stdio(false),而不是nothing;

3.用'\n',而不是endl。

其他关于卡常的技巧可以参观:

玄学卡常


完结撒花!(觉得有帮助别忘了点个赞哦!^_^)

  • 32
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
以下是两种C++文件输入输出字符串的例子: 1. 从标准输入中读取一行字符串,然后输出该字符串及其长度,并将该字符串转换为C风格字符串,最后输出C风格字符串及其长度减去3的子串。 ```cpp #include <iostream> #include <cstdio> // printf #include <cstring> // strlen using namespace std; int main(int argc, char const *argv[]) { string str1; getline(cin, str1, '!'); // 读取一行字符串,以感叹号为结束符 cout << str1 << '\n'; // 输出该字符串 cout << "str1.size(): " << str1.size() << '\n'; // 输出该字符串的长度 const char * cstr = str1.c_str(); // 将该字符串转换为C风格字符串 printf("%s\n", cstr); // 输出C风格字符串 printf("strlen(cstr): %lu\n", strlen(cstr)); // 输出C风格字符串的长度 string str2(cstr, strlen(cstr) - 3); // 截取C风格字符串的长度减去3的子串 cout << str2 << '\n'; // 输出子串 return 0; } ``` 2. 从文件中读取一个字符串,然后向另一个文件中输出一些文本和该字符串。 ```cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main(int argc, char const *argv[]) { ifstream fin; fin.open("1.txt", ifstream::in); // 打开输入文件 ofstream fout("2.txt", ios_base::out); // 打开输出文件 string str; fin >> str; // 从输入文件中读取一个字符串 fout << "hey, there\n"; // 向输出文件中输出一些文本 fout << str << '\n'; // 向输出文件中输出该字符串 fin.close(); // 关闭输入文件 fout.close(); // 关闭输出文件 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值