丟人筆記:黑科技——使用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 = '\n';
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('\n');
            return;
        }
        while (x) {
            stack[++top] = x % 10 + '0';
            x /= 10;
        }
        while (top) {
            fb -> sputc(stack[top]);
            --top;
        }
        fb -> sputc('\n');
    }
}

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('\n');
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('\n');
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM