快读

1、为什么要有快读

好吧,有些题目看上去十分简单,例如https://www.luogu.com.cn/problem/P4305这道题,实际上数据量巨多,光是一个测试点就可能有几个MB,在这种情况下,就连scanf和printf函数都会超时Σ( ° △ °|||)︴我当初用scanf写时TLE了3个点。我才不会告诉你我是用unordered_map水过去的

所以我们需要找到另外的读入数据的方式。这时就要用到我们平时忽视的一个函数了——getchar()。你肯定会感到惊讶,但是我可以毫不犹豫地告诉你,这玩意确实比上述两个读入方式快许多。我们先一个萝卜一个坑,从读入int型开始慢慢做。

前面主要讲运行原理,如果是需要直接拿代码的,可以调到最后面去查看

2、输入int

有时输入并不会像你想的那么简单,常常会出现一些空格或回车。如果从当前字符直接开始读的话,就会多读入一些空格或者回车,导致数据出错。所以我们需要一个循环先过滤掉前面一些不需要的字符

char ch = ' ';//初始化超重要的
while(ch < '' || ch > '')
{
ch = getchar();//此处用ch来充当变量
}

我们似乎要考虑一个情况,如果出现负数,会怎么样?没关系,在这个循环里加入一个判断,来确定是正数还是负数:

char ch = ' ';//初始化超重要的
int w = ;//是1就是正数
while(ch < '' || ch > '')
{
if(ch == '-') w = -;//是-1就是负数
ch = getchar();//此处用ch来充当变量
}

我这段代码有一个隐藏BUG。先让读者观摩几分钟,然后查一查BUG。

BUG就是:如果输入数据时" -  9",它也会判断为负数!不过没关系,很多题目的输入数据已经保证不会出现这种情况。如果还不放心,可以自己改一改(其实是我懒了

目前已经将前面多余的字符过滤掉了,现在要处理的是后面数字部分。此时我们要引用一个新的变量s来存储所输入的数字。处理输入也很简单,不断输入直到不再是1~9之间的数:

while(ch >= '' && ch <= '')
{
s = s * + ch - '',//读入的数据是字符,需要减去一个ASCLL码
ch = getchar();
}

如此,我们最后返回数据就可以了。全代码:

inline int IntRead()//内联函数稍微快一点点
{
char ch = getchar();
int s = , w = ;
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
s = s * + ch - '',
ch = getchar();
}
return s * w;
}
int main()
{
int a;
a = IntRead();
cout << a;
}

(等会,我好像忘记打include了)

3、输入string字符串

处理完int输入,字符串输入相对来说简单多了。首先先处理完前面多余的回车与空格,然后再不断读入直到读到回车或空格。这里不再赘述直接上代码:

inline string StringRead()
{
string str;
char s = getchar();
//处理多余回车或空格
while (s == ' ' || s == '\n' || s == '\r')
{
s = getchar();
}
//不断读入直到遇到回车或空格
while (s != ' ' && s != '\n' && s != '\r')
{
str += s;
s = getchar();
}
return str;
}

4、读入浮点数

终于到一个稍微复杂一点的地方了,读入浮点数。读入浮点数有两个策略,1是先读入字符串然后再进行处理,2是读入的过程中,先读整数部分,然后再读小数部分。这里我选择第二种。

前面处理多余字符和判断负数的方式与int相同,只是后面读入数字过程中要改变一下。我们引入两个变量n、k和m,n存储当前是读整数部分还是小数部分,k表示小数部分的值,m表示小数部分的长度(可省略,但为了方便阅读)。(这样写或许过于复杂?)如果读到小数点,便修改n的值,否则就看n的值来读入整数或小数。

最后返回答案时,直接将k转换为小数,然后加上整数部分,然后再决定是返回负数还是正数。

代码:

inline double DoubleRead()
{
//double的值可能很大,所以开long long
long long s = , w = , k = , n = , m = ;
char ch = getchar();
//和int一毛一样有木有
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while((ch >= '' && ch <= '') || ch == '.')
{
//n = 0代表读入整数,= 1代表读入小数
if (ch == '.')
n = ;
else if (n == )
s = s * + ch - '';
else k = k * + ch - '', m++;
ch = getchar();
}
return (pow(0.1, m) * k + s) * w;
}

大致的读入方法就OK了,但是实际上我并没有对代码做优化。快速读出的代码略有麻烦,或许我以后会再写一个随笔来讲一下。用了一个下午的时间,你真的以为我只做了这些?(笑)闲得无聊的我还写了两个类来施行快速读入或读出,下面放代码:

所有代码

//FastIntput.h
#include <cstdio>
#include <string>
#include <cmath>
class FastInput
{
private:
public:
inline friend FastInput& operator >> (FastInput& in, int& a)
{
int s = , w = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
s = s * + ch - '', ch = getchar();
}
a = s * w;
return in;
}
inline friend FastInput& operator >> (FastInput& in, long long& a)
{
long int s = , w = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
s = s * + ch - '', ch = getchar();
}
a = s * w;
return in;
}
inline friend FastInput& operator >> (FastInput& in, float& a)
{
long long s = , w = , k = , now = , mi = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while((ch >= '' && ch <= '') || ch == '.')
{
if (ch == '.')
now = ;
else if (now == )
s = s * + ch - '';
else k = k * + ch - '', mi++;
ch = getchar();
}
a = (pow(0.1, mi) * k + s) * w;
return in;
}
inline friend FastInput& operator >> (FastInput& in, double& a)
{
long long int s = , w = , k = , now = , mi = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while((ch >= '' && ch <= '') || ch == '.')
{
if (ch == '.')
now = ;
else if (now == )
s = s * + ch - '';
else k = k * + ch - '', mi++;
ch = getchar();
}
a = (pow(0.1, mi) * k + s) * w;
return in;
}
inline friend FastInput& operator >> (FastInput& in, char& ch)
{
ch = getchar();
return in;
}
inline friend FastInput& operator >> (FastInput& in, std::string& st)
{
std::string str;
char s = getchar();
while (s == ' ' || s == '\n' || s == '\r')
{
s = getchar();
}
while (s != ' ' && s != '\n' && s != '\r')
{
str += s;
s = getchar();
}
st = str;
return in;
}
};
FastInput FI;

快速读入

//FastOutPut.h
#include <cstdio>
#include <string>
class FastOutput
{
private:
public:
inline friend FastOutput& operator << (FastOutput& out, int s)
{
int k = ;
if (s == )
putchar('');
while (s)
{
k = k * + s % ;
s /= ;
}
while (k)
{
putchar(k % + '');
k /= ;
}
return out;
}
inline friend FastOutput& operator << (FastOutput& out, long long s)
{
long long k = ;
if (s == )
putchar('');
while (s)
{
k = k * + s % ;
s /= ;
}
while (k)
{
putchar(k % + '');
k /= ;
}
return out;
}
inline friend FastOutput& operator << (FastOutput& out, float a)
{
int mi = , s[];
if (a == )
putchar('');
while (a != (long long)a)
{
a *= , mi++;
}
long long k = a, i = ;
while (k != )
{
s[i] = k % , i++, k /= ;
}
for (i -= ;i >= ;i--)
{
if (i == mi - )
putchar('.');
putchar(s[i] + '');
}
return out;
}
inline friend FastOutput& operator << (FastOutput& out, double a)
{
int mi = , s[];
if (a == )
putchar('');
while (a != (long long int)a)
{
a *= , mi++;
}
long long int k = a, i = ;
while (k != )
{
s[i] = k % , i++, k /= ;
}
for (i -= ;i >= ;i--)
{
if (i == mi - )
putchar('.');
putchar(s[i] + '');
}
return out;
}
inline friend FastOutput& operator << (FastOutput& out, char& ch)
{
putchar(ch);
return out;
}
inline friend FastOutput& operator << (FastOutput& out, std::string str)
{
int i = ;
while (str[i] != '\0')
{
putchar(str[i]), i++;
}
return out;
}
};
FastOutput FO;

快速读出

inline int IntRead()
{
char ch = getchar();
int s = , w = ;
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
s = s * + ch - '',
ch = getchar();
}
return s * w;
}

快速读入int

inline string StringRead()
{
string str;
char s = getchar();
while (s == ' ' || s == '\n' || s == '\r')
{
s = getchar();
}
while (s != ' ' && s != '\n' && s != '\r')
{
str += s;
s = getchar();
}
return str;
}

快速读入string

inline double DoubleRead()
{
long long s = , w = , k = , n = , m = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') w = -;
ch = getchar();
}
while((ch >= '' && ch <= '') || ch == '.')
{
if (ch == '.')
n = ;
else if (n == )
s = s * + ch - '';
else k = k * + ch - '', m++;
ch = getchar();
}
return (pow(0.1, m) * k + s) * w;
}

快速读入double

...
//把那两个类复制或用include调用
int main()
{
int a;
long long b;
long long int c;
float d;
double e;
std::string f;
FI >> a;
FO << a << "\n";
FI >> b;
FO << b << "\n";
FI >> c;
FO << c << "\n";
FI >> d;
FO << d << "\n";
FI >> e;
FO << e << "\n";
FI >> f;
FO << f << "\n";
}

最上面俩代码用法

关于前面两个类,你没必要选择复制粘贴,而是可以用调用库的方式来调用它们。例如:

#include "FastInput.h"

最后

这一篇随笔算是比较短的,但是我还是花了一个下午的时间去码代码,但可能依旧有一些小错误。一些代码复制上来的时候我并没有仔细去检查,如果你发现了错误,欢迎在评论区里留言。

[C/C++]快速读入代码(快读)的更多相关文章

  1. C/C++快读(快速读入)有多——安全AC

    在一些算法题目中中,有的程序会被卡常(数),就是说,程序虽然渐进复杂度,(通俗来讲:算法的时间复杂度)可以接受,但因为算法本身的时间常数过大,导致程序在一些算法竞赛中超时.这是,快读就显得尤为重要了. ...

  2. C++手写快读详解(快速读入数字)

    众所周知,C++里是自带读入的(这不废话吗) 例如: int a; cin>>a; 这样的读入理解简单,适合初学者,但是非常慢. 再例如: int a; scanf("%d&qu ...

  3. C++读入神器——文操快读(oj也可以用)

    当某天,本蒟蒻沉迷于卡常的时候: 我-- 突然,YYKdalao说:用文操快读啊! 然后 喔-目瞪口呆 不多说,上源码: 本来用的读入方式: inline void Read( int &x ...

  4. 快读&快写模板【附O2优化】

    快读&快写模板 快读快写,顾名思义,就是提升输入和输出的速度.在这里简单介绍一下几种输入输出的优劣. C++ cin/cout 输入输出:优点是读入的时候不用管数据类型,也就是说不用背scan ...

  5. int快读

    昨天偶然间看到CJ_tony的快读,所以便决定学习一下. 这个快读的原理就是:读入单个字符要比读入读入数字快,先读入字符,然后再转化成数字.(原理的话大学再研究) 代码: #include<io ...

  6. C++快读模板

    C++的快速读入模板 inline int read() { ; char ch = getchar(); ') { if (ch == '-') flag = true; ch = getchar( ...

  7. C++中的快读和快写

    快读原理 单个字符的读入速度要比读入数字快,因此我们以字符的形式先读入,然后处理计算转为数字. 代码 inline int read(){ register int x = 0, t = 1; reg ...

  8. 利用sublime的snippet功能快速创建代码段

    在前端开发中我们经常会输入相同的一些基本代码,例如常用的jquery引用,bootstrap框架,cssreset等等,如果每次使用时在复制粘贴感觉很麻烦,这里介绍一种更为简洁的方法 利用sublim ...

  9. 网站快速收录/站点快速收录/seo快排技术/seo快速排名/泛域名快速收录/泛目录快速收录

    泛目录技术是目前最快速最有效的办法,增加站点的收录方面,这里推荐莲花泛目录 莲花泛目录,完善的技术支持,代码亲自编写,独立研发.业界领先. (这个是seo关键词,请无视,直接看下面的泛目程序介绍)网站 ...

随机推荐

  1. 评测Loki日志工具

    评测Loki日志工具 目录 评测Loki日志工具 部署Loki 配置grafana 总结: 优势: 劣势: 本文仅对Loki进行简单评测,不涉及原理和细节. 部署Loki Loki是grafana团队 ...

  2. faker生成器生成虚拟数据的Python模块

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:行哥 今天给大家介绍一个Faker模块,一款基于Python的测试数 ...

  3. 附002.Nginx全系列大总结

    Nginx全系列总结如下,后期不定期更新. 欢迎基于学习.交流目的的转载和分享,禁止任何商业盗用,同时希望能带上原文出处,尊重ITer的成果,也是尊重知识. 若发现任何错误或纰漏,留言反馈或右侧添加本 ...

  4. Python源码剖析|百度网盘免费下载|Python新手入门|Python新手学习资料

    百度网盘免费下载:Python源码剖析|新手免费领取下载 提取码:g78z 目录  · · · · · · 第0章 Python源码剖析——编译Python0.1 Python总体架构0.2 Pyth ...

  5. ~~并发编程(十四):Queue~~

    进击のpython ***** 并发编程--Queue 进程其实就提过这个Queue的问题,我们为什么在进程使用Queue? 是因为当时我们想要对共享数据进行修改,同时也希望它能够自动的给我加个锁 基 ...

  6. MySQL组复制MGR(四)-- 单主模式与多主模式

    (一)概述 组复制可以运行在单主模式下,也可以运行在多主模式下,默认为单主模式.组的不同成员不能部署在不同模式下,要切换模式,需要使用不同配置重新启动组而不是单个server. 相关参数如下: # 该 ...

  7. python unicode和string byte

    python unicode 和string那 开发过程中总是会碰到string, unicode, ASCII, 中文字符等编码的问题, 每次碰到都要现搜, 很是浪费时间, 于是这次狠下心, 一定要 ...

  8. jmeter控制器入门笔记一

    @@@@@@@@@@@@@@@ 千里之行 今天记录一下个人才使用控制器时的一些心得.逻辑控制器在jmeter中有很多种,个人根据官方解释理解的作用就是:通过控制器可以更好地控制请求的执行顺序.jmet ...

  9. Python os.isatty() 方法

    概述 os.isatty() 方法用于判断如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False.高佣联盟 www.cgewang.com 语法 isatty ...

  10. Python time ctime()方法

    描述 Python time ctime() 函数把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式.高佣联盟 www.cgewang.com 如果参数未给或者为None的时候, ...