输入输出优化——防止TLE

cin cout优化

在默认情况下,std::cin/std::cout 是极为迟缓的输入/输出方式,而 scanf/printf 比 std::cin/std::cout 快得多

如果习惯了C++的输入输出方式,想加快速度,就可以用如下方法解决!

关闭同步/解除绑定

cin效率低的原因一是在于默认cin与stdin总是保持同步,cin会把要输出的东西先存入缓冲区,进而消耗时间。通过关闭同步,可以有效提高cin效率;

std::ios::sync_with_stdio(false)

这个函数是一个“是否兼容 stdio”的开关,C++ 为了兼容 C,保证程序在使用了 printf 和 std::cout 的时候不发生混乱,将输出流绑到了一起。

这其实是 C++ 为了兼容而采取的保守措施。我们可以在进行 IO 操作之前将 stdio 解除绑定,但是在这样做之后要注意不能同时使用 std::cin/std::cout 和 scanf/printf。更严格的来说:关闭之后C++ IO和C IO 两者不能混用,否则会造成IO混乱。

tie函数加速

默认情况下cin绑定的是cout,每次执行<<的时候都要调用flush(),进而增加IO负担。

tie 是将两个 stream 绑定的函数,空参数的话返回当前的输出流指针。 可以通过std::cin.tie(0)std:cout.tie(0)(0 表示 NULL)来解除 std::cin与 std::cout的绑定,进一步加快执行效率。

在这两种情况优化下,std::cin和std::cout的速度就和scanf和printf基本一样了,甚至更快。

代码实现

#include <iostream>
using namespace std;
 
int main(){
    ios::sync_with_stdio(false);
    ios_bast::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}

如果在同一个流上使用两组 I/O 函数(头文件<stdio.h>/<cstdio>和<iostream>)(例如stdin流同时关联cin与scanf),那么最好让它们保持同步;

如果任何一个流只使用一个 I/O 系列,则可以关闭同步(比如在各自涉及单独的流的情况下,可以同时使用scanf与cin)。

保险起见,关闭同步之后不要同时使用C与C++的读写方式,避免不必要的麻烦。

比如print,scanf,gets(),pus(),getchar()不要与cin,cout共用

cout中不要使用endl

每次使用endl,都要flush缓冲区,造成大量时间耗费。推荐cout << << "\n"的写法。

输入优化getchar() ——针对整型数据

getchar 是用来读入 1 byte 的数据并将其转换为 char 类型的函数,且速度很快,故可以用“读入字符——转换为整型”来代替缓慢的读入;

每个整数由两部分组成——符号和数字,整数的 ‘+’ 通常是省略的,且不会对后面数字所代表的值产生影响,而 ‘-’ 不可省略,因此要进行判定。

10 进制整数中是不含空格或除 0~9 和正负号外的其他字符的,因此在读入不应存在于整数中的字符(通常为空格)时,就可以判定已经读入结束

C 和 C++ 语言分别在 ctype.h 和 cctype 头文件中,提供了函数 isdigit , 这个函数会检查传入的参数是否为十进制数字字符,是则返回 true ,否则返回 false 。对应的,在下面的代码中,可以使用 isdigit(ch) 代替 ch >= ‘0’ && ch <= ‘9’ ,而可以使用 !isdigit(ch) 代替 ch <‘0’ || ch> ‘9’。

代码实现

int read() {
  int x = 0, w = 1;
  char ch = 0;
  //我们判断是否为十进制数字字符可以使用isdight()函数来判断,这里不再展示。
  while (ch < '0' || ch > '9') {  // ch 不是数字时
    if (ch == '-') w = -1;        // 判断是否为负
    ch = getchar();               // 继续读入
  }
  while (ch >= '0' && ch <= '9') {  // ch 是数字时,我们输入结束标志为空格或回车。
    x = x * 10 + (ch - '0');  // 将新读入的数字’加’在 x 的后面
    // 此处也可以使用 (x<<3)+(x<<1) 的写法来代替 x*10 即:x=(x<<3)+(x<<1)+(ch-'0');用位运算效率更高,这里相当于x*8+x*2+(ch-'0');
    //利用ASCII码转换为对应数字。
    ch = getchar();  // 继续读入
  }
  return x * w;  // 数字 * 正负号 = 实际数值
}

我们输入数据时可以这样调用read函数:num=read()。

输出优化putchar()

负号要单独判断输出,并且每次 %(mod)取出的是数字末位,因此要倒序输出

代码实现

递归版
void write(int x) {
  if (x < 0) {  // 判负 + 输出负号 + 变原数为正数
    x = -x;
    putchar('-');
  }
  if (x > 9) write(x / 10);  // 递归,将除最后一位外的其他部分放到递归中输出
  putchar(x % 10 + '0');  // 已经输出(递归)完 x 末位前的所有数字,输出末位
}
非递归版
inline void write(int x) {//此处inline总感觉用的有些问题。。
  static int sta[35];
  int top = 0;
  do {
    sta[top++] = x % 10, x /= 10;//将取出的元素入栈。
  } while (x);
  while (top) putchar(sta[--top] + 48);  //由于我们要输出字符,这里进行转换: 48 是 '0'
}

常用宏定义

#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)

那么,在主函数直接使用IOS;语句即可实现优化功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值