【2024最新】C++读写优化超具体分析(cin优化+平常快读+fread)_输入输出优化_快读快写_算法比赛

[复制链接]
发表于 2026-4-24 09:00:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在算法比赛中,读入速率和输出速率不绝是卡常的紧张本领。也有不少人履历过被标题卡 cin 的情况。本日我给各人先容一下算法比赛中常用的读写方法及其优化。
声明:大部门情况下,只用读入优化就行。对于输出量大的标题再思量利用输出优化。
一、scanf/printf

这两个函数泉源于传统的 C,在 <stdio.h> 和 <cstdio>(仅 C++)中。利用方法:scanf("%占位符",&var); printf("%占位符\n",var);。如许比传统的 cin/cout 快,但由于誊写复杂而很少被人接纳。
   scanf/printf 用法参考文章:详解c++中scanf和printf用法
  二、cin/cout 优化

cin 和 cout是 C++ 的尺度输入输出流,在 <iostream> 头文件中,利用方法也非常简朴:cin>>var; cout<<var<<endl; 以是深受人们的喜欢。
在时间要求不高的标题中,用它们既省事,又可以让代码更雅观。
缺点:cin/cout 在不加优化的情况下速率慢于 scanf 和 printf。
缘故原由:C++ 为了和 C 保持同步、在混用 printf&scanf 和 cin&cout时的时间不发生紊乱,将它的输入/输出流绑到了一起。
办理方案:可以手动关闭同步,从而进步 cin 和 cout 的服从。std::ios::sync_with_stdio(false); 同时,还可以通过std::cin.tie(nullptr); 来清除 cin 和 cout之间的绑定,进一步减轻 cin 的负担。
   cin/cout 用法:C++ 底子的输入输出先容:把握cin与cout的奥秘
  三、endl 优化

有一个被人忽略的“大杀手”:endl。这一个语句和 \n 的效果类似,但更方便誊写,因此被人们广泛接纳。实在它的速率也特殊慢。大概会导致某些标题超时。
缘故原由:endl 输出时会清空缓冲区,这是为了让用户能实时看到输出,但会拖慢速率。而且由于它自己的功能界说,很难举行优化。
办理方案:打不外就不消呗 对于输出量大且须要换行的标题,利用 endl 有超时的风险,发起利用 cout<<'\n'。(平常刷题也发起用 \n,比力保险)
在实测中,C++14 的版本下,cin/cout 优化 + endl 优化的速率已经远快于 scanf/printf,发起在新评测机上利用上面两种方法优化
  1. #include<iostream>
  2. using namespace std;
  3. int a[105];
  4. int main(){
  5.    
  6.    
  7.         ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
  8.         int n;
  9.         cin>>n;
  10.         for(int i=1;i<=n;i++){
  11.    
  12.    
  13.             cin>>a[i];
  14.         }
  15.         for(int i=1;i<=n;i++){
  16.    
  17.    
  18.                 cout<<"a["<<i<<"]="<<a[i]<<"\n";
  19.         }
  20.     return 0;
  21. }
复制代码
四、传统快读、快写

原理:单个字符的输入输出速率要比读入数字快,因此我们以字符的情势先读入,然后处置处罚盘算转为数字,再用字符输出。
关于 isdigit()

在判定某个字符是不是整数时用的 isdigit() 函数,在差别编译器上的速率不一样。
在 这篇文章 中的测试效果:自己写比 VS 中的 isdigit() 快,但比 g++ 中的 isdigit() 慢。而且 g++ 中的 isdigit() 比 VS 中的 isdigit() 更快。
这篇文章 给我们展示了 Linux 内核中该函数王者级别的实现,各人可以学习。
自己写的话:
  1. #define my_isdigit(c) ( (c)>='0'&&(c)<='9' ) // C语言
  2. inline bool my_isdigit(char c){
  3.    
  4.     return (c>='0'&&c<='9'); } // C++
复制代码
快读

原理是先用单个字符读入全部零散的数字,再拼起来。拼数和判定字符见 这篇文章。
  1. template<typename T>
  2. inline void read(T &x){
  3.    
  4.    
  5.         T w=1; x=0;
  6.         char c=getchar();
  7.         while(!isdigit(c)){
  8.    
  9.     if(c=='-'){
  10.    
  11.    w=-1;} c=getchar();}  
  12.         while(isdigit(c)){
  13.    
  14.     x=x*10+(c-'0'); c=getchar();}
  15.         x=x*w;
  16. }
复制代码
快写

原理是把原来完备的数字拆成一个个字符输出。用递归的常数会略大,可以用模仿栈的方法时限。
递归代码:
  1. template<typename T>
  2. inline void write(T x){
  3.    
  4.    
  5.     if(x<0){
  6.    
  7.     putchar('-'); x=-x;}
  8.     if(x>=10){
  9.    
  10.     write(x/10);}
  11.     write(x%10+'0'); //+'0'是为了让数字类型的x%10变成字符输出
  12. }
复制代码
模仿栈代码:(不能用模板了,要自己指定范例)
  1. inline void write(int x){
  2.    
  3.    
  4.     static int st[35] = {
  5.    
  6.    0};</
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表