输入输出大全(普通输入输出和快读快写)C/C++

简介: 输入输出大全(普通输入输出和快读快写)C/C++

前言

我最早接触的刷题平台是力扣,这导致我第一次在PTA平台上写题的时候在数据的输入和输出上感到非常折磨。这篇文章是我对各种输入输出的总结,准备开始刷题的同学看这篇文章能帮你节约不少的时间。


缓存区 : 书上的定义是,缓冲区是一块物理内存中的存储区,当数据进行转移时用来临时存放数据。在这里的作用我就把他理解成,在输入和输出时数据时,这些数据都要在缓存区走一遍再去完成他们的功能

一、普通读写操作

在不考虑读写运行速度的情况下,基本的读入函数就能完成我们所有的读入功能。下面主要介绍不同的读入函数,

1、cin

作为操作起来最方便的读入函数,cin不需要记住任何的多余符号,新手只要知道他在空格和换行符会自动停止读入就行,且不会清空缓存区,对刚刚刷题的小白非常的友好。但我个人是非常不建议用的,速度慢是其次,主要是他在读入一些比较特殊的词时会有些不方便(这个题目写多了肯定会遇到的),最基础的操作相比来说的话我更推荐scanf

2、scanf

我是非常建议把scanf当成不需要考虑读入效率时的默认输入方式的。一般的scanf使用方法我就不多说了,这里介绍几种在刷题时曾经困扰过我的几种输入。

题目要求读入n个整形(n不确定),存放在arr数组里,输入时每个整形之间会以空格分开,具体样子如下。

当时我不了解scanf遇到空格会结束的特性,这个输入没有完成,其实这种类型的输入通过一句话就可以解决

while(~scanf("%d",&arr[i++]));//i就是个从零开始的变量

这里用到了scanf的返回值特性,scanf其实是有返回值的(可能就我不知道吧),一次scanf读入几个字符他就会返回几,碰到空格或者TAB等会返回0,而碰到输入结束标志会返回EOF(即-1),所以这里用的是~符号,让-1的时候得到0退出while循环,就是要让他在检测接收到数据和空格时都继续接收下一个,而接收到输入结束标志时退出while即不继续输入

大部分不确定输入个数的输入通过这个都能解决,但有一个例子不可以:要求将n(n不确定)个字符串放到二维数组arr里,具体如下。

我们先直接看解决代码

while(~scanf("%d",&arr[i++]) && getchar() == ' ');//i就是个从零开始的变量

这里我先解释上面的那一串字符为什么不能用之前的方法解决,在最开始我也不明白为什么这样的字符串输入进来会有问题,后面我看了录进去的值之后我发现其实不管是让我输入字符串还是让我输入整形,我的输入都是有问题的,只不过在字符串输入的时候更容易发现错误。对于第一个输入整形的题目我们写一下就会发现当我们运行完时,如果我们输入3个数,n的值会变成4而不是3,这是因为scanf在读入的时候在把空格,换行等读入到缓存区的时候会结束此次读入,但是这时候缓存区里的空格,换行等不会消失,这就导致我读完最后一个数时其实缓存区里还有\n而不是结束标志,这时候如果下一位是文章结束标志scanf会将\n转换成空格存到我的数组里,当然这时候n++于是导致n比我们想要的值还多一。那为什么加了getchar就好了呢,这我们就要知道getchar的处理字符方式,当缓存区有字符时,getchar会从缓存区读取并清空一个字符,而这里就是用到了getchar的这个特性,不仅可以清空scanf之后缓存区残留的符号还能,让循环在正确的时候退出。

3、gets/getline

这两个分别是c/c++的输入函数,这里要注意的是gets在c++里是不能用的,在这里讲一下这两个函数和scanf有什么区别,前面我们已经说过了scanf遇到空格和回车会停止,但是这里的gets只有遇到回车才会停止,并且会自动把\n转化成\0(gets只会能把数据读到char*里)。还有一点与scanf不同的是scanf会把空格换行等留在缓存区里,只能通过getchar来清除,但gets不会在缓存区里留东西getline就是c++版的gets。那什么时候会用到这个呢?当我想输入一段字符串但字符串里面包含空格时,我就只能用gets去实现这个功能

4、printf

所有的输出我都是建议printf的,虽然cout非常的方便,但是学会printf可以满足所有不需要效率时的输出操作。下面主要讲两个我之前不知道的操作。

固定小数位数的输出,这里举个例子1:比如我要输出一个小数后两位的浮点数

1. double a =2.127;
2. printf("%.2lf\n",a);//控制double类型到两位小数

这里有一点要注意,最后一位显示出来的小数是会自动四舍五入的

例子2:在整形前面自动补0直到达到指定位数,多用于有补0格式要求的整形输出

1. int i=2;
2. printf("%02d",i);//不够两位在左边补零,补空格也行

二、快读快写

在有些题目里读写要求的数据量特别大时甚至会要求我们不能使用语言本身提供的函数,而是要求我们对一些不方便但是效率高的函数操作来达到输入输出的功能,这就是快读快写。

快读快写的本质就是用更快的读入函数去实现读写操作,读入操作时间 cin > scanf > getchar > fread.这就衍生出了以下两种快读(getchar版本和fread版本)。以下按照整型的输入来解释。

1. inline int read1()//这里加inline是为了解决一些频繁调用的函数大量消耗栈空间(栈内存)的问题
2. {
3. int x = 0, f = 1;
4. char ch = getchar();
5. while (ch < '0' || ch >'9')
6.     {
7. if (ch == '-') f = -1;
8.         ch = getchar();
9.     }
10. while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
11. return x * f;
12. }

上面根据getchar读入字符的功能去实现读入一个整形,但是这样的函数没法像scanf一样放在while里读入,这就导致如果不告诉你数据个数你就没法很好的读入,于是改进后函数为下面这样,输入检测到\n会让while退出。

1. inline int read2(int* a,int i)//这里加inline是为了解决一些频繁调用的函数大量消耗栈空间(栈内存)的问题
2. {
3. int x = 0, f = 1;
4. char ch = getchar();
5. while (ch < '0' || ch > '9')
6.     {
7. if (ch == '-') f = -1;
8.         ch = getchar();
9.     }
10. while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
11.     a[i] = x * f;
12. if (ch == '\n') return 0;
13. return 1;
14. }

从之前所说的我们知道还有一个比getchar更快的函数,接下来我们再用fread去实现getchar,实现一个更快的快读。

1. char buf[100000], * p1 = buf, * p2 = buf;
2. 
3. inline char nc() {
4. if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, 1, stdin);
5. return *p1++;
6. }
7. 
8. inline int read3(int* a, int i) {
9. int x = 0, f = 1;
10. char ch = nc();
11. while (ch < '0' || ch > '9')
12.     {
13. if (ch == '-') f = -1;
14.         ch = nc();
15.     }
16. while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = nc();
17.     a[i] = x * f;
18. if (ch == '\n') return 0;
19. return 1;
20. }

fwrite(buffer,size,count,fp)   buf表示存放读入一个数据的地址指针;size表示读出的字节数;count表示读出数据项的个数;fp表示文件型指针。

同样的我们这时候看快写运行时间 cout > printf > putchar ,下面就是用putchar来实现printf

1. void write(int x)
2. {
3. if (x < 0) putchar('-'), x = -x;
4. if (x > 9) write(x / 10);
5. putchar(x % 10 + '0');
6. return;
7. }

1、整形快读快写

1. char buf[100000], * p1 = buf, * p2 = buf;
2. 
3. inline char nc() {
4. if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, 1, stdin);
5. return *p1++;
6. }
7. 
8. inline int read3(int* a, int i) {
9. int x = 0, f = 1;
10. char ch = nc();
11. while (ch < '0' || ch > '9')
12.     {
13. if (ch == '-') f = -1;
14.         ch = nc();
15.     }
16. while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = nc();
17.     a[i] = x * f;
18. if (ch == '\n') return 0;
19. return 1;
20. }
21. 
22. void write(int x)
23. {
24. if (x < 0)
25. putchar('-'), x = -x;
26. if (x > 9)
27. write(x / 10);
28. putchar(x % 10 + '0');
29. return;
30. }

2、浮点型的快读快写

这方面用到的雀食没见过,而且如果把浮点型写成快读快写也需要很多的函数,效果没那么明显,这里就不写了。

3、字符串快读快写

这里其实也起不到多大的优化效果,看个人意愿是否使用,这里就不用fread了。

1. inline string readstr() {
2.  string s = "";
3.  char ch;
4.  while ((ch = getchar()) != '\n') s += ch;
5.  return s;
6. }
7. 
8. inline void writestr(string s) {
9.  for (int i = 0; i < s.size(); i++) putchar(s[i]);
10. }

三、O2优化

读入数据量大的时候O2优化能减少很多运行时间,具体原理不需要了解,这里就直接放O2开关。

把下面这句话写到程序前面就好啦。

#pragma GCC optimize(2)

总结

很多的题目都是可以不要快读快写的,很多时候怎么方便怎么来,但是这不意味这就不重要,快读快写在关键时刻说不定真的能救你一命呢。

相关文章
|
3月前
|
人工智能 自然语言处理 搜索推荐
Spark-TTS: AI语音合成的"变声大师"
Spark-TTS 是一款革命性的语音合成模型,被誉为“变声大师”。它通过创新的 BiCodec 技术将语音分解为语义和全局两种 Token,实现对音色、性别、语速等属性的精细控制。结合统一的 LLM 架构,Spark-TTS 简化了传统 TTS 的复杂流程,同时提供了前所未有的灵活性。此外,团队还发布了 VoxBox 开源数据集,为行业提供标准评估基准。尽管在零样本场景下仍存改进空间,但 Spark-TTS 已经开启了语音合成新时代,让个性化、可控的 AI 语音成为可能。
|
3月前
|
安全 Ubuntu Linux
硬盘格式化用什么工具好?这6个工具值得了解一下
本文介绍了硬盘格式化的重要性及注意事项,并推荐了几款主流平台下的实用格式化工具,包括Windows磁盘管理器、文件资源管理器、DiskGenius、Diskpart命令行、Mac Disk Utility以及Linux的GParted,帮助用户安全高效地完成格式化操作。
|
9月前
|
机器学习/深度学习 数据采集 人工智能
AI在用户行为分析中的应用:实现精准洞察与决策优化
AI在用户行为分析中的应用:实现精准洞察与决策优化
1229 15
|
JavaScript Java 测试技术
大学生体质测试|基于Springboot+vue的大学生体质测试管理系统设计与实现(源码+数据库+文档)
大学生体质测试|基于Springboot+vue的大学生体质测试管理系统设计与实现(源码+数据库+文档)
282 0
2022最新最详细必成功的在Vscode中设置背景图、同时解决不受支持的问题
这篇文章提供了在VScode中设置背景图的详细步骤,包括下载background插件、编辑setting.json文件、配置背景样式,并解决了设置后出现的不支持提示的问题。
2022最新最详细必成功的在Vscode中设置背景图、同时解决不受支持的问题
|
分布式计算 资源调度 Hadoop
在YARN集群上运行部署MapReduce分布式计算框架
主要介绍了如何在YARN集群上配置和运行MapReduce分布式计算框架,包括准备数据、运行MapReduce任务、查看任务日志,并启动HistoryServer服务以便于日志查看。
184 0
|
11月前
|
人工智能 算法 C语言
详解树状数组(C/C++)
详解树状数组(C/C++)
|
存储 算法 C++
【C++ 包装器类 map】C++ 标准库(std)中的map结构 哈希表(unordered_map)和黑红树(map)教程
【C++ 包装器类 map】C++ 标准库(std)中的map结构 哈希表(unordered_map)和黑红树(map)教程
1099 1
|
自然语言处理 搜索推荐
通义大模型使用指南之通义万相
该文介绍了如何在阿里云的通义大模型平台注册账号,并详细展示了通义万相功能的使用,包括文本生成图像、相似图像生成、图像风格迁移和应用广场(虚拟模特)四个部分。用户可以通过输入文字或选择图片,生成不同风格的创意作品,并能进行点赞、不满意、生成相似图、下载原图和收藏等操作。在应用广场中,用户可以上传图片并替换模特及背景,创建个性化商品展示图。
4868 0
|
C语言 C++
关于DEV中collect2.exe [Error] ld returned 1 exit status的问题解决!!!
关于DEV中collect2.exe [Error] ld returned 1 exit status的问题解决!!!