【2024最新】C++读写优化超详细解析(cin优化+普通快读+fread)_输入输出优化_快读快写_算法竞赛

在算法竞赛中,读入速度和输出速度一直是卡常的重要手段。也有不少人经历过被题目卡 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,建议在新评测机上使用上面两种方法优化

#include<iostream>
using namespace std;
int a[105];
int main(){ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=1;i<=n;i++){cout<<"a["<<i<<"]="<<a[i]<<"\n";}return 0;
}

四、传统快读、快写

原理:单个字符的输入输出速度要比读入数字快,因此我们以字符的形式先读入,然后处理计算转为数字,再用字符输出。

关于 isdigit()

在判断某个字符是不是整数时用的 isdigit() 函数,在不同编译器上的速度不一样。

在 这篇文章 中的测试结果:自己写比 VS 中的 isdigit() 快,但比 g++ 中的 isdigit() 慢。而且 g++ 中的 isdigit() 比 VS 中的 isdigit() 更快。

这篇文章 给我们展示了 Linux 内核中该函数王者级别的实现,大家可以学习。

自己写的话:

#define my_isdigit(c) ( (c)>='0'&&(c)<='9' ) // C语言
inline bool my_isdigit(char c){ return (c>='0'&&c<='9'); } // C++

快读

原理是先用单个字符读入所有零散的数字,再拼起来。拼数和判断字符见 这篇文章。

template<typename T>
inline void read(T &x){T w=1; x=0; char c=getchar(); while(!isdigit(c)){ if(c=='-'){w=-1;} c=getchar();}  while(isdigit(c)){ x=x*10+(c-'0'); c=getchar();} x=x*w;
}

快写

原理是把原来完整的数字拆成一个个字符输出。用递归的常数会略大,可以用模拟栈的方法时限。

递归代码:

template<typename T>
inline void write(T x){if(x<0){ putchar('-'); x=-x;}if(x>=10){ write(x/10);}write(x%10+'0'); //+'0'是为了让数字类型的x%10变成字符输出
}

模拟栈代码:(不能用模板了,要自己指定类型)

inline void write(int x){static int st[35] = {0}; // int 最多32位int top = 0; // 指向栈顶的指针do{st[top++]=x%10;x/=10;}while(x>0);while(top>0){ putchar(st[--top]+'0');}
}

这里有一个细节,把 st 数组声明为 static 静态类型,可以在申请空间时只申请一次,同时降低常数。static 关键字详细用法见 这篇文章。

五、位运算优化快读、快写

原理:通过位运算加速拼数、取数及转换数字的过程。

实现如下:

template<typename T>
inline void read(T &x){T w=1; x=0; char c=getchar(); while(!isdigit(c)){ w|=(c=='-'); c=getchar();}  while(isdigit(c)){ x=(x<<1)+(x<<3)+(c^48); c=getchar();} x=x*w;
}template<typename T>
inline void write1(T x){if(x<0){ putchar('-'); x=(~x)+1;}if(x>=10){ write(x/10);}write(x%10^48); //+'0'是为了让数字类型的x%10变成字符输出
}inline void write2(int x){static int st[35] = {0}; // int 最多32位int top = 0; // 指向栈顶的指针do{st[top++]=x%10;x/=10;}while(x>0);while(top>0){ putchar(st[--top]^48);}
}

上面一些位运算优化的解释参见:这篇文章

六、优化快读、快写 plus

原理:使用 C 中的 fread()fwrite() 函数,把数据当作字符串 直接从文件中读入/向文件中输出。加快 getchar() 函数。
注:文件也可以是标准输入输出流 stdinstdout

fread、fwrite 用法

fread 函数:从一个文件流中读取数据
函数原型如下:

size_t fread(void *buffer, size_t size, size_t count, FILE *stream);-- buffer:指向数据块的指针,读取的数据存储在此-- size:每个数据的大小,单位为Byte 例如:sizeof(int)就是4-- count:要读入的数据个数-- stream:文件指针,指向要读入的数据

fwrite 函数:将一块内存区域中的数据写入到本地文本
函数原型如下:

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);-- buffer:指向数据块的指针,待写入的数据存储在此-- size:每个数据的大小,单位为Byte 例如:sizeof(int)就是4-- count:要写入数据个数-- stream:文件指针,指向待写入的数据

拓展:两个函数随着传入参数不同,返回值的意义也不同。

  1. fread(buf,sizeof(buf),1,file):读取数据量正好是 sizeof(buf) 个 Byte 时,返回值为 1(为 count)。
  2. fread(buf,1,sizeof(buf),file):读取成功返回值为实际读入的数据个数(单位为Byte)。
  3. fwrite(buf,sizeof(buf),1,file):成功写入返回值为 1(为 count)。
  4. fwrite(buf,1,sizeof(buf),file):成功写入则返回实际写入的数据个数(单位为Byte)。

更具体的详细用法参见 这篇文章。

优化快读

char buf[1<<20],*p1,*p2;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin), p1 == p2) ? 0 : *p1++)
template <typename T>
inline void read(T &x){T w=1; x=0;char c=gc();while(!isdigit(c)){ w|=(c=='-'); c=gc();}while(isdigit(c)){ x=(x<<1)+(x<<3)+(c^48); c=gc();}  x=x*w; 
}

优化快写

int sta[30];
char buf[1<<20], pbuf[1<<20], *p = pbuf, *s = buf, *t = buf;#define put1(ch) (p - pbuf == bsiz ? fwrite(pbuf, 1, bsiz, stdout), p = pbuf, *p++ = ch : *p++ = ch)inline void putint(int x){register int top = 0;if (x<0) pu1t('-'), x = -x;do{sta[top++]=x%10;x/=10;}while(x>0);while (top) put1(sta[--top]^48);
}

End

本文就到这里啦~ 有不完善的地方日后会加以完善的(咕了几篇文章

这里是 YLCHUP,拜拜ヾ(•ω•`)o

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Base64实现传输图片

1. Base64简介 Base64是一种基于64个可打印字符来表示二进制数据的表示方法。通常用于在URL、Cookie和邮件等场景中&#xff0c;将二进制数据转换为字符串形式进行传输。 代码实现 public class ImageUtils {/*** 得到图片的Base64编码* param imagePath 图片路径* return …

手机删除的文件能恢复吗?删除不等于永别,3个技巧助你找回

安卓手机中的文件&#xff0c;就像是数字世界里的繁星&#xff0c;记录着我们的点点滴滴。然而&#xff0c;有时我们可能会不小心删除了某些重要的文件&#xff0c;让我们感到惋惜和困惑。删除的文件能恢复吗&#xff1f;别担心&#xff0c;删除并不等于永别&#xff0c;我们也…

Maven报错 NullPointerException as JavaCompiler.readSourceFile

1. 报错详情 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project xxx-web: Fatal error compiling: CompilerException: NullPointerException -> [Help 1] org.apache.maven.lifecycle.Lifecycl…

CentOS 停服后,服务器 OS 路在何方?

2024 年 6 月 30 日&#xff0c;CentOS Linux 7 终止其生命周期&#xff08;EOL&#xff09;&#xff0c;至此 CentOS 全系列版本也已停止维护&#xff0c;属于 CentOS 的时代彻底终结。CentOS 停止维护后&#xff0c;用户将无法获得包括问题修复和功能更新在内的任何软件维护和…

小程序里面使用vant ui中的vant-field组件,如何使得输入框自动获取焦点

//.wxml <van-fieldmodel:value"{{ userName }}"placeholder"请输入学号"focus"{{focusUserName}}"/>// .js this.setData({focusUserName: true});vant-field

LLMs之RAG:GraphRAG(本质是名词Knowledge Graph/Microsoft微软发布)的简介、安装和使用方法、案例应用之详细攻略

LLMs之RAG&#xff1a;GraphRAG(本质是名词Knowledge Graph/Microsoft微软发布)的简介、安装和使用方法、案例应用之详细攻略 导读&#xff1a;2024年7月3日&#xff0c;微软正式开源发布GraphRAG。GraphRAG可以提高大型语言模型在私有数据集上的推理能力。 背景痛点&#xff1…

MSVC2017+Qt 打包

在环境变量下配置好 QT 和 MSVC 的路径 相关搜索&#xff1a; 找不到msvcp140.dll 1.搜索 Qt 选择在编译器路径下打开 2. Windeployqt 生成打包&#xff0c;正常情况下生成 VC 相关package&#xff0c; 即 msvcp140.dll 等MSVC 相关 但是lz尝试没有生成 解决办法 先将生成…

数据库作业d8

要求&#xff1a; 一备份 1 mysqldump -u root -p booksDB > booksDB_all_tables.sql 2 mysqldump -u root -p booksDB books > booksDB_books_table.sql 3 mysqldump -u root -p --databases booksDB test > booksDB_and_test_databases.sql 4 mysql -u roo…

MySQL 中的几种锁

MySQL 中的锁 #按锁粒度如何划分? 按锁粒度划分的话&#xff0c;MySQL 的锁有&#xff1a; 表锁&#xff1a;开销小&#xff0c;加锁快&#xff1b;锁定力度大&#xff0c;发生锁冲突概率高&#xff0c;并发度最低;不会出现死锁。行锁&#xff1a;开销大&#xff0c;加锁慢…

电脑压缩软件哪个好?WinRAR、7-Zip、Bandizip 还是360压缩

文件压缩软件已成为我们日常工作中不可或缺的一部分&#xff0c;它不仅能够帮助我们节省存储空间&#xff0c;还能提高文件传输效率。本文简鹿办公小编将对四款主流的电脑压缩软件进行对比&#xff0c;它们分别是 WinRAR、7-Zip、Bandizip 和 360 压缩。 一、WinRAR WinRAR 是…

Qt中文个数奇数时出现问号解决

Qt中文个数奇数时出现问号解决 目录 Qt中文个数奇数时出现问号解决问题背景问题场景解决方案 问题背景 最近在开发一个小工具&#xff0c;涉及到一些中文注释自动打印&#xff0c;于是摸索如何把代码里面的中文输出到csv文件中&#xff0c;出现了乱码&#xff0c;按照网上的攻…

vue2-Django3-iframe解决方案,处理安全策略,事件拦截,处理iframe重载等

目录 简介 实现iframe 后端安全策略 通过Ngnix代理实现SAMEORIGIN iframe的事件拦截&#xff0c;自定义处理 iframe的状态保持&#xff08;解决vue中iframe重载&#xff09; 解决方法 简介 Iframe&#xff08;内联框架&#xff09;是一种HTML元素&#xff0c;用于在网页…

Nginx配置缺少导致CSS不起作用

引言 在Web开发中&#xff0c;确保样式表正确加载是前端显示正常工作的关键。然而&#xff0c;有时候即使CSS文件的路径和代码本身没有问题&#xff0c;CSS样式也可能无法正确应用。本文将分享一个常见的问题——Nginx配置缺少导致的CSS不起作用&#xff0c;以及如何解决这个问…

周鸿祎为什么建议Java、前端、大数据、PHP开发都要学一下大模型?_ai大模型全栈工程师跟java有关吗

ChatGPT的出现在全球掀起了AI大模型的浪潮&#xff0c;2023年可以被称为AI元年&#xff0c;AI大模型以一种野蛮的方式&#xff0c;闯入你我的生活之中。 从问答对话到辅助编程&#xff0c;从图画解析到自主创作&#xff0c;AI所展现出来的能力&#xff0c;超出了多数人的预料&…

智慧公厕系统实现人性化与节能化的完美结合

在当今社会&#xff0c;科技的飞速发展正不断改变着我们的生活方式&#xff0c;公厕也不例外。智慧公厕系统的出现&#xff0c;不仅提升了人们的使用体验&#xff0c;更实现了人性化与节能化的完美结合&#xff0c;为城市公共服务带来了全新的变革。 一、人性化&#xff0c;是智…

echarts 实现水利计算模型-雨量,流量,时间分割线

需求背景解决效果ISQQW代码地址index.vue 需求背景 实现水利计算模型-雨量&#xff0c;流量&#xff0c;时间分割线 解决效果 ISQQW代码地址 链接 index.vue <!--/** * author: liuk * date: 2024/06/13 * describe: 洪水预报结果图表 */--> <template><di…

算法篇 滑动窗口 leetcode 长度最小的子数组

长度最小的子数组 1. 题目描述2. 算法图分析2.1 暴力图解2.2 滑动窗口图解 3. 代码演示 1. 题目描述 2. 算法图分析 2.1 暴力图解 2.2 滑动窗口图解 3. 代码演示

Flask `preprocess_request` 方法教程

Flask preprocess_request 方法教程 在 Flask 应用中&#xff0c;preprocess_request 方法在请求被分派到相应的视图函数之前被调用。它允许您在请求处理的早期阶段执行一些自定义逻辑。本文将详细讲解 preprocess_request 方法的工作原理及其使用方法。 方法概述 preproces…

数据结构进阶——使用数组实现栈和队列详解与示例(C,C#,C++)

文章目录 1、数组实现栈栈的基本操作C语言实现C#语言实现 2、 数组实现队列队列的基本操作C语言实现C# 语言实现C语言实现 总结 在编程世界中&#xff0c;数据结构是构建高效算法的基石。栈和队列作为两种基本的数据结构&#xff0c;它们的应用非常广泛。本文将带领大家使用C&a…

TCP/IP 原理、实现方式与优缺点

TCP/IP&#xff08;传输控制协议/网际协议&#xff09; 是互联网的核心协议套件&#xff0c;主要用于在不同计算机之间进行通信。它包括多个层次的协议&#xff0c;每层协议负责不同的功能。TCP/IP 的四个层次模型如下&#xff1a; 网络接口层&#xff1a;负责在特定的物理网络…