标准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版)》