From cf6f6e15a75f55cd3317f09135c011626ba2af0a Mon Sep 17 00:00:00 2001 From: Anguei <42708316+Anguei@users.noreply.github.com> Date: Fri, 2 Nov 2018 09:30:22 +0800 Subject: [PATCH] Update io.md --- docs/misc/io.md | 52 +++++++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/docs/misc/io.md b/docs/misc/io.md index 00ed75c7..bf6737a7 100644 --- a/docs/misc/io.md +++ b/docs/misc/io.md @@ -1,27 +1,27 @@ -在默认情况下,`cin(cout)` 是极为迟缓的读入(输出)方式,而 `scanf(printf)` 比 `cin(cout)` 快得多。 +在默认情况下,`std::cin(std::cout)` 是极为迟缓的读入(输出)方式,而 `scanf(printf)` 比 `std::cin(std::cout)` 快得多。 可是为什么会这样呢?有没有什么办法解决读入输出缓慢的问题呢? -## 关闭同步 +## 关闭同步 / 解除绑定 -### sync_with_stdio +### std::ios::sync_with_stdio(false) -这个函数是一个 “是否兼容 stdio” 的开关,C++ 为了兼容 C,保证程序在使用了 `std::printf` 和 `std::cout` 的时候不发生混乱,将输出流绑到了一起。 +这个函数是一个 “是否兼容 stdio” 的开关,C++ 为了兼容 C,保证程序在使用了 `printf` 和 `std::cout` 的时候不发生混乱,将输出流绑到了一起。 -这其实是 C++ 为了兼容而采取的保守措施。我们可以在 IO 之前将 stdio 解除绑定,这样做了之后要注意不要同时混用 `cout` 和 `printf` 之类 +这其实是 C++ 为了兼容而采取的保守措施。我们可以在 IO 之前将 stdio 解除绑定,这样做了之后要注意不要同时混用 `std::cout` 和 `printf` 之类 ### tie tie 是将两个 stream 绑定的函数,空参数的话返回当前的输出流指针。 -在默认的情况下 `cin` 绑定的是 `cout`,每次执行 `<<` 操作符的时候都要调用 `flush`,这样会增加 IO 负担。可以通过`tie(0)`(0 表示 NULL)来解除 `cin` 与 `cout` 的绑定,进一步加快执行效率。 +在默认的情况下 `std::cin` 绑定的是 `std::cout`,每次执行 `<<` 操作符的时候都要调用 `flush()`,这样会增加 IO 负担。可以通过 `std::cin.tie(0)`(0 表示 NULL)来解除 `std::cin` 与 `std::cout` 的绑定,进一步加快执行效率。 ### 代码实现 ```cpp std::ios::sync_with_stdio(false); - std::cin.tie(0); +// 如果编译开启了 C++11 或更高版本,建议使用 std::cin.tie(nullptr); ``` ## 读入优化 @@ -46,23 +46,17 @@ std::cin.tie(0); int read() { int x = 0, w = 1; char ch = 0; - - while (ch < '0' || ch > '9') { // ch不是数字时 - - if (ch == '-') w = -1; //判断是否为负 - - ch = getchar(); //继续读入 + while (ch < '0' || ch > '9') { // ch 不是数字时 + if (ch == '-') w = -1; // 判断是否为负 + ch = getchar(); // 继续读入 } - - while (ch >= '0' && ch <= '9') { // ch是数字时 - - x = (x << 3) + (x << 1) + ch - '0'; //将新读入的数字’加’在x的后面 - // x<<3==x*8 x<<1==x*2 所以(x<<3)+(x<<1)相当于x*10 - // x是int - // 类型,char类型的ch和’0’会被自动转为其ASCII表中序号,相当于将ch转化为对应数字 - ch = getchar(); //继续读入 + while (ch >= '0' && ch <= '9') { // ch 是数字时 + x = (x << 3) + (x << 1) + ch - '0'; // 将新读入的数字’加’在 x 的后面 + // x<<3==x*8 x<<1==x*2 所以 (x<<3)+(x<<1) 相当于 x*10 + // x 是 int 类型,char 类型的 ch 和 ’0’ 会被自动转为其 ASCII 表中序号,相当于将 ch 转化为对应数字 + ch = getchar(); // 继续读入 } - return x * w; //数字*正负号==实际数值 + return x * w; // 数字 * 正负号 = 实际数值 } ``` @@ -84,20 +78,16 @@ int read() { ```cpp int write(int x) { - if (x < 0) { //判负+输出负号+变原数为正数 - + if (x < 0) { // 判负 + 输出负号 + 变原数为正数 x = -x; - putchar('-'); } - - if (x > 9) write(x / 10); //递归,将除最后一位外的其他部分放到递归中输出 - - putchar(x % 10 + '0'); //已经输出(递归)完x末位前的所有数字,输出末位 + if (x > 9) write(x / 10); // 递归,将除最后一位外的其他部分放到递归中输出 + putchar(x % 10 + '0'); // 已经输出(递归)完 x 末位前的所有数字,输出末位 } ``` -但是递归实现是很慢的,我们可以写一个栈来实现这个过程 +但是递归实现常数是较大的,我们可以写一个栈来实现这个过程 ```cpp inline void write(int x) { @@ -120,7 +110,7 @@ inline void write(int x) { 更通用的是 `fread`,因为 `mmap` 不能在 Windows 使用。 -`fread`类似于`scanf("%s")`,不过它更为快速,而且可以一次性读入若干个字符(包括空格换行等制表符),如果缓存区足够大,甚至可以一次性读入整个文件。 +`fread` 类似于 `scanf("%s")`,不过它更为快速,而且可以一次性读入若干个字符(包括空格换行等制表符),如果缓存区足够大,甚至可以一次性读入整个文件。 对于输出,我们还有对应的 `fwrite` 函数 -- 2.11.0