• 丢人笔记:黑科技——使用streambuf加速读入输出


    UPD20191125:我发现我又丢人了,sgetc只会读取缓冲区当前字符而不会前移读取位置,想要读取并前移读取位置应该用sbumpc。。。

      一般情况下,在C++中,iostream内的cin和cout是比scanf和printf慢的,这主要是为了同时兼容iostream和stdio,iostream与stdio的缓冲区被绑到了一起,以及cin和cout的stream是绑定在一起的,这使得cin和cout有额外的开销

      为了提高cin和cout的效率,我们可以取消iostream与stdio的同步,以及cin和cout的stream的绑定:

    1 std::ios::sync_with_stdio(false);
    2 cin.tie(NULL);
    3 cout.tie(NULL);

      这样cin与cout就比scanf和printf快了。在本机测试上,iostream甚至比stdio快了6倍左右。然而这样做之后,就不可以将iostream与stdio混用了,然而输入量较大的时候,这种方法仍然无能为力

      在stdin中,我们有getchar,想要追求更快的速度,我们有fread

      在iostream中我们同样可以达到同样的效率,甚至更快:

      首先要获取cin的streambuf:

    std::streambuf *fb = cin.rdbuf();

      然后我们就可以进行类似stdio中的操作:

      对于getchar,我们有sbumpc,它的用法等同于getchar,速度略快于getchar:

    char ch = fb -> sbumpc();

      对于fread,我们有sgetn,它的用法与fread类似,速度略快于fread:

    #define MAX_INPUT 1000000
    char buf[MAX_INPUT]
    int main() {
        fb -> sgetn(buf, MAX_INPUT);
        return 0;
    }

      输入问题就解决了。还有输出问题:

      (不知道为什么,网上的输出代码在我这边不会进行输出,然而我这边手写的输出比fwrite慢了好多。。。。)

      对于putchar,我们有sputc,它的用法等同于putchar,速度略快于putchar:

    char ch = '
    ';
    fb -> sputc(ch);

      对于fwrite,我们有sputn,它的用法与fwrite类似,速度略快于fwrite?

    #define MAX_OUTPUT 1000000
    char buf[MAX_OUTPUT];
    int main() {
        fb -> sputn(buf, MAX_OUTPUT);
        return 0;
    }

      这样我们就有了一份完整的快速输入输出 丢人 代码(因为sputn的那份比sputc还慢,所以这里就用了sputc的代码):

    #include<iostream>
    #include<cctype>
    using std::cin;
    using std::cout;
    using std::endl;
    namespace IN {
        #define MAX_INPUT 1000000
        #define cinchar() ((fs == ft && (ft = (fs = buf) + fb -> sgetn(buf, MAX_INPUT))) ? 0 : *fs++)
        char buf[MAX_INPUT], *fs, *ft;
        inline int read() {
            static std::streambuf *fb = cin.rdbuf();
            register int x = 0;
            register bool f = false;
            register char ch = cinchar();
            while (!isdigit(ch)) {
                if (ch == '-') f = true;
            ch = cinchar();
            }
            while (isdigit(ch)) {
                x = (x << 1) + (x << 3) + ch - '0';
                ch = cinchar();
            }
            return f ? -x : x ;
        }
        #undef MAX_INPUT
        #undef cinchar
    }
    
    namespace OUT {
        inline void put(int x) {
            static std::streambuf *fb = cout.rdbuf();
            static char stack[11];
            static int top = 0;
            if (!x) {
                fb -> sputc('0');
                fb -> sputc('
    ');
                return;
            }
            while (x) {
                stack[++top] = x % 10 + '0';
                x /= 10;
            }
            while (top) {
                fb -> sputc(stack[top]);
                --top;
            }
            fb -> sputc('
    ');
        }
    }
    
    int main() {
        freopen("add.in", "r", stdin);
        std::ios::sync_with_stdio(false);
        cin.tie(NULL);
        cout.tie(NULL);
        int a = IN::read(), b = IN::read();
        OUT::put(a + b);
        return 0;
    }

     为了丢人,在这里贴上sputn的代码

     1 namespace OUT {
     2     #define MAX_OUTPUT 1000000
     3     char buf[MAX_OUTPUT], *fs = buf, *ft = buf + MAX_OUTPUT;
     4     #define coutchar(ch) *fs++ = ch
     5     inline void put(int x) {
     6         static std::streambuf *fb = cout.rdbuf();
     7         static char stack[11];
     8         static int top = 0;
     9         if (!x) {
    10             coutchar('0'); coutchar('
    ');
    11             return;
    12         }
    13         while (x) {
    14             stack[++top] = x % 10 + '0';
    15             x /= 10;
    16         }
    17         while (top) {
    18             *fs++ = stack[top];
    19             --top;
    20         }
    21         coutchar('
    ');
    22         fb -> sputn(buf, fs - buf);
    23         fs = buf;
    24     }
    25     #undef coutchar
    26     #undef MAX_OUTPUT
    27 }
    sputn

    代码部分参考自:https://blog.csdn.net/simpsonk/article/details/78457842

  • 相关阅读:
    multimap-begin
    multimap-constructors
    multimap-constructors
    map-rend
    map-rend
    map-rbegin
    map-rbegin
    lower_bound
    纪念邓小平同志诞辰110周年,2014年出品的48集电视剧《历史转折中的邓小平》
    二叉查找树(二叉排序树)的详细实现,以及随机平衡二叉查找树Treap的分析与应用
  • 原文地址:https://www.cnblogs.com/hinanawitenshi/p/8830097.html
Copyright © 2020-2023  润新知