今天,我要和妳談談C++中的頭文件。在我寫算法展示源代碼的時候,很多朋友給我留言說被我頭文件裏的內容震驚了。其實我的頭文件之所以這麽復雜,完全是因為我從大學acm競賽開始就壹直在用。對於acm比賽的選手來說,這樣的頭文件其實是小兒科。
今天,我們來看看acmer頭文件中隱藏的秘密。
首先,讓我們看看我完整的頭文件代碼。
# include & ltiostream & gt
# include & ltcstdio & gt
# include & ltcstring & gt
# include & lt字符串& gt
# include & ltcstdlib & gt
# include & ltcmath & gt
# include & lt隊列& gt
# include & ltvector & gt
# include & lt地圖& gt
# include & ltset & gt
# include & lt算法& gt
# include & lt功能性& gt
#定義rep(i,a,b)for(int I = a;我& ltb;i++)
#定義Rep(i,a,b)for(int I = a;我& gtb;我-)
#define foreach(e,x)for(_ _ type of(x . begin())e = x . begin();e!= x . end();e++)
#定義mid((l+r)>;& gt1)
#定義埃爾松(k & lt& lt1)
#定義rson(k & lt;& lt1|1)
#定義MEM(a,x)記憶集(a,x,sizeof a)
#定義pii對& ltint,int & gt
#定義LL long long
usingnamespacestd
constint N = 500005
constlonglong Mod = 99997867
請點擊輸入圖片說明。
包括零件
首先,我們來看包含部分。我們壹個壹個來看iostream。不用說,C++標準輸入輸出頭文件包含了C++ iostream函數,這是經典的cin和cout。說到cin和cout,C語言中cin和cout的開銷比scanf和printf慢很多,容易影響程序的性能。所以對acmer來說,scanf和printf能做到的,cin和cout永遠做不到。當然scanf和printf不是最快的,還有更快的getchar和putchar,所以有些玩家會手動讀取char,把它變成int或者float函數,當然這在大多數情況下是沒有必要的。
Cstdio的功能和iostream壹樣,不過是C語言中的輸入輸出函數,不多說了。
Cstring也屬於C語言,是C語言中的字符串庫,有很多字符串相關的函數。同樣,出於性能考慮,如果在C語言中可以使用char[]就不需要使用C++ string。下壹個字符串庫就不用說了,就是C++的字符串處理庫。
cstdlib的庫函數相當於C語言中的stdlib.h,封裝了壹些常用的庫函數,如rand、s rand、free、malloc等。
Cmath庫相當於C語言中的math.h,封裝了壹些數學運算相關的庫函數,比如pow、sqrt等。
下面的隊列,矢量,貼圖,集合都是STL庫,裏面包含了壹些有用的數據結構。例如,queue封裝了queue和dequeue,以及priority_queue,即queue、dequee和priority queue。向量、映射和集合分別是線性表、映射表和集合。熟練使用它們可以大大降低編碼的復雜性。
算法庫翻譯成算法庫,自然封裝了很多算法。比如sort排序,reverse flip,next _ permission下的next全排列,lower_bound,upper_bound函數等。
最後壹個用的不多的函數庫,顧名思義封裝了函數對象上的壹些操作。比如bind,reference_wrapper等等。
事實上,有壹種巧妙的方法可以同時包含所有的頭文件:
# include & ltbits/stdc++。h & gt
不過這種方式有個小問題,並不是所有環境都支持,尤其是官方比賽。所以壹般來說,大家都會在壹些網絡比賽中使用。我個人懶得區分環境,所以習慣壹個壹個包含。
請點擊輸入圖片說明。
定義零件
Define是C++中壹個非常強大的函數,可以定義規則來代替代碼。熟練使用define還可以大大簡化編碼。但需要註意的是,凡事不可過猶不及。定義用多了,會影響程序的可讀性,還可能影響別人的編碼。因此,許多大公司禁止使用define。個人覺得沒那麽嚴重。define可以用,按照規範正確使用即可。
第壹行是這兩行,它們是for循環的定義。
#定義rep(i,a,b)for(int I = a;我& ltb;i++)
#定義Rep(i,a,b)for(int I = a;我& gtb;我-)
#define foreach(e,x)for(_ _ type of(x . begin())e = x . begin();e!= x . end();e++)
Rep是repeat的縮寫。使用時只需要rep(i,A,B)來代替冗長的for循環的寫法,其中I是循環變量,A和B分別是循環的上下界,註意區間左閉右開。
Rep也是同樣的邏輯,只是反循環而已。
Foreach使用了C++11的新特性,可以實現自動叠代,在某些場景下非常方便。
#定義mid((l+r)>;& gt1)
這壹行用在二分搜索法,左邊界是L,右邊界是R,所以它們的中點是(l+r)/2,用位運算表示:(L+R)> & gt;1。示例:
# define之前
while(l+1 & lt;r) {
int m = (l + r)>& gt1;
if(a[m]& lt;= v) {
l = m;
}否則{
r = m;
}
}
在# define之後
while(l+1 & lt;r) {
if(a[mid]& lt;= v) {
l = mid
}否則{
r = mid
}
}
#定義埃爾松(k & lt& lt1)
#定義rson(k & lt;& lt1|1)
這兩條線主要用於線段樹,因為C++往往不用類來實現線段樹,而是通過數組來模擬。在段樹中,如果壹個節點的id是U,那麽它的左子是2 x u,它的右子的id是2 x u+1,用位操作表示為U
#定義MEM(a,x)記憶集(a,x,sizeof a)
#定義pii對& ltint,int & gt
#定義LL long long
最後三行放在壹起,第壹行是memset的縮寫,可以用來初始化數組。Pii縮寫為pair
關於類型的重定義,這裏用define不太好。更好的方法是使用typedef。例如,上面的對和long long可以寫成:
typedef對& ltint,int & gtpii
typedeflonglong LL
這比定義更標準化,因為定義是生硬的字符串替換,而typedef是類型別名,編譯器可以檢查,所以可以使用typedef或typedef。
請點擊輸入圖片說明。
樂章結尾部
除了上面提到的頭文件,還有壹些更高端的用法,比如壹些模板類,壹些常用的算法,比如gcd等等。但我個人認為意義不是很大。面試和筆試的代碼環節,以上頭文件就夠了。
蘋果iCloud數據中心投入運營;網易公布不當言論HR處理結果:開除;OceanBase數據庫將開源|極客頭條
程序員應該在35歲退休嗎?
從“不作惡”到“門在那邊”,Google AI的倫理史