快讀快寫 模板


  1. #include<cstdio>        
  2. #include<iostream>        
  3. #include<cctype>        
  4. using namespace std;        
  5. int read()        
  6. {        
  7.     int s = 0, f = 1;        
  8.     char ch = getchar();        
  9.     while(!isdigit(ch)) {        
  10.         if(ch == '-') f = -1;        
  11.         ch = getchar();        
  12.     }        
  13.     while(isdigit(ch)) {        
  14.         s = s * 10 + ch - '0';        
  15.         ch = getchar();        
  16.     }        
  17.     return s * f;        
  18. }        
  19. void write(int x)        
  20. {        
  21.     if(x < 0) {        
  22.         putchar('-');        
  23.         x = -x;        
  24.     }        
  25.     if(x > 9)        
  26.         write(x/10);        
  27.     putchar(x % 10 + '0');        
  28.     return;        
  29. }        
  30. int main()        
  31. {        
  32.     int a;        
  33.     a = read();        
  34.     write(a);        
  35.     return 0;        
  36. }      

一些問題:

1. 快讀快寫比標准輸入輸出流以及C的格式化輸入輸出要快,主要是由於直接利用了單個字符操作,並且適用范圍僅限所定義的返回類型與輸出類型,犧牲了標准輸入輸出的普適性而換取了效率,在算法競賽中具有廣泛的應用空間。

2. 快讀、快寫函數的實現分別用到了循環和遞歸,從理論上講無法完成內聯,inline建議不會被編譯器采納;通過在vijos上對某一需要大量輸入的題目使用快讀進行測試,可以發現read()前加入或不加入inline的效率幾乎相同。由此可以判斷inline大概率被忽略,或是函數調用和返回的時間微不足道,個人認為inline沒有必要。(不理解的同學可從資料和各大博客了解內聯函數的相關知識)

3. 該方法利用了cctype庫中的字符判斷函數isdigit(),其效率與手寫ASCII碼判斷幾乎不相上下,甚至更快,可以說同時實現了簡潔與快捷,建議使用。

4. 理論上效率較高的寫法是將read中所定義的變量加入寄存器建議,但是實測的效率相差並不大。依然有指令被編譯器忽略的可能性,因此加不加入就看自己的想法了。

5. int read(void)函數也可以寫成void read(&int)的形式(對地址進行直接賦值操作),效率方面沒有太大差別,可以按照個人愛好采用不同風格。

6. 一種使用fread()函數可以進一步顯著提升讀入效率,但寫法較為復雜,且需要額外開辟內存,出錯率高,在OI中用途有限,有興趣的同學可以自行學習了解。

 

太原五中

袁盛琪

2019年3月26日

 

----------------------------------------------

2019.7.7 做一個補充

  1. template <typename T>    
  2. void read(T &x) {    
  3.     x = 0;    
  4.     int f = 1;    
  5.     char ch = getchar();    
  6.     while (!isdigit(ch)) {    
  7.         if (ch == '-') f = -1;    
  8.         ch = getchar();    
  9.     }    
  10.     while (isdigit(ch)) {    
  11.         x = x * 10 + (ch ^ 48);    
  12.         ch = getchar();    
  13.     }    
  14.     x *= f;    
  15.     return;    
  16. }   

以上是使用模板template的快速讀入。它可以讀取任何格式的整型數據。

再說明一個以前留下的小問題:register編譯建議是在每個函數進程中重新定義的,即便是讀入int64范圍的數據,函數變量也最多會迭代20次左右,每次把它定義在寄存器里其實有些雞肋。

----------------------------------------------

附上使用模板的快寫。

 
  1. template <typename T>  
  2. void write(T x)    
  3. {    
  4.     if(x < 0) {    
  5.         putchar('-');    
  6.         x = -x;    
  7.     }    
  8.     if(x > 9)    
  9.         write(x/10);    
  10.     putchar(x % 10 + '0');    
  11.     return;    
  12. }    


免責聲明!

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



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