C/Cppnote_3_浅析C与C++的输入输出

标准I/O (C语言)

C程序会自动打开三个标准文件:标准输入、标准输出、标准错误输出,而标准IO头文件 stdio.h ,会将标准文件与三个文件指针 (FILE * 类型)相关联,分别为 stdin, stdout, stderr。这些标准文件是 scanf, printf, putchar 等不指定文件的函数的默认使用文件。

不同于操作系统的底层IO函数,标准IO会创建读/写的缓冲区,以及一个包含文件与缓冲区数据的结构(包含一些IO信息)。


iostream库 (C++)

C++中没有定义任何IO语句,而是利用IO类标准库提供IO机制,这提高了C++输入输出的可扩展性,同时也使其更加复杂。

C与C++的输入输出都是流式的(字节流),而 iostream库定义了两个类型 istream, ostream(还有wistream等),以及对于类型的两个对象 cin, cout(还有cerr, clog等)。cin 会严格地保证读取类型与存储类型一致,这一点与C语言的 %类型转换 是不同的。如果不一致会发生错误,使得这个流对象后续的IO操作都失败,且读取语句返回 0。

提高 cin 与 cout 的效率

直接用C++的 cin 与 cout 是比 scanf 与 printf 慢很多的,它为了与C语言中 ( std:: ) scanf 和 printf 的兼容性(允许混用),要与 stdin, stdout 同步,将输入输出流绑定在一起,共享同一块缓冲区;否则会造成 FILE 指针的错乱,输入输出的顺序也会混乱。添加下面的语句以取消iostream 与 stdio 的同步,可提高效率:

std::ios::sync_with_stdio(0);  // synchronized with stdio

在实际测试中关闭同步的效果也因编译器而异,不过至少对 MinGW 影响还是比较大的。注意!取消同步后就别再用 printf, scanf 等标准IO包里的函数了。

另外,默认情况下还存在 cin 和 cout 两个 stream 之间的绑定,cin >> 会刷新 cout 的缓冲区,cout << 会刷新 cin 的缓冲区。添加下面第二行语句取消绑定,可提高效率:

std::ios::sync_with_stdio(0);
cin.tie(0);

不过取消绑定不意味着就是手动刷新的,操作系统只要有余力就会自动刷新。

补充知识:缓冲区(buffer)

缓冲机制允许操作系统将多个输出操作组合为单一的设备(屏幕)写操作,通常可以带来很大的性能提升(具体有全缓冲、行缓冲与无缓冲)。要注意程序崩溃并不在刷新缓冲的条件里面,也就是说利用输出来 debug 时可能会误以为并没有执行,其实只是数据被挂起了没打印而已。

C标准规定可以使用 fflush(stdout) 来刷新输出缓冲区的,但是否可以同样地刷新输入缓冲取决于编译器(GCC不行= =)。

而C++中则有一些操纵符(manipulator)。endl:输出并换行、ends:输出并空格、flush:直接输出

cout << ans << endl;
cout << unitbuf  // 关闭缓冲机制,任何输出操作后立即调用 flush
//无缓冲输出
cout << nounitbif  // 重置流,回到正常的缓冲机制

文件I/O (C语言)

文件输入输出便于查看与分析大量数据(windows中比较文件内容用命令:fc file2.txt file1.txt),输入输出效率似乎也更快。C语言通过文件指针 (FILE * 类型) 与相关函数来实现文件操作, C++ 中则使用 fstream 库中的文件流来实现。

重定向 Redirect

一个简单的实现:加入I/O重定向语句

freopen("inp.txt", "r", stdin);
freopen("outp.txt", "w", stdout);

利用条件编译方便在提交前去除文件输入输出

#define LOCAL
...
int main() {
#ifdef LOCAL
   	freopen("inp.txt", "r", stdin);
	freopen("outp.txt", "w", stdout);
#endif
	...
}

使用 fopen 函数

若禁止使用重定向则使用如下方式实现文件IO:

FILE* fin  = fopen("inp,txt", "rb");
FILE* fout = fopen("outp,txt", "wb");

fscanf(fin, "%d", %n);
fprintf(fout, "%d", ans);

fclose(fin);
fclose(fout);

文件改为标准IO只需:

fin = stdin;
fout = stdout;

调用 fopen 函数实际上是在打开一个流(文本流与二进制流内容暂省略)。而使用 “rb”, “wb” 切换为二进制流(与 fread(), fwrite 等价?),能比文本流节省信息的存储空间,尤其是数字信息,且不用进行对 \n 的转换,通常效率都会更高。


fstream库 (C++)

待更新 (✪ω✪)

Reference

https://byvoid.com/zhs/blog/fast-readfile/

《C Primer Plus (第六版)》

《C++ Primer(第5版)》

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值