通過mismatch或lexicographical比較
實作簡單的忽略大小寫字串比較
一個STL菜鳥最常問的問題是「我怎麼使用STL來進行忽略大小寫
(這個問題一個比較難的版本也能用STL解決。另文說明 )為了讓簡單的問題
但是首先,我們需要一種方法來確定兩個字元除了大小寫之外是否相等
int ciCharCompare(char c1, char c2) // 忽略大小寫比較字符 { // c1和c2,如果c1 < c2返回-1, // 如果c1==c2返回0,如果c1 > c2返回1 int Ic1 = tolower(static_cast(c1)); // 這些語句的解釋 int Ic2 = tolower(static_cast(c2)); // 看下文 if (Ic1 < Ic2) return -1; if (lc1 > Ic2) return 1; return 0; }
這個函數遵循了strcmp,可以返回一個負數、零或正數,依賴於c1和c2之間的關係。與strcmp不同的是,ciCharCompare在進行比較前把兩個參數轉化為小寫。這就產生了忽略大小寫的字元比
正如(也是)裡的很多函數,tolower 的參數和返回值類型是int ,但除非這個 int是EOF,它的值必須能表現為一個unsigned char。在C和C++中,char可能是或可能不是有符號的(依賴於實作),當char有符號(Signed)時,唯一確認它的值可以表現為unsigned char的方式是在呼叫tolower之前轉換一下。這就解釋了上面程式碼中的轉換。(在char已經是無符號(Unsigned)的實現中,這個轉換沒有作用。)這也解釋了保 存tolower返回值的是int而不是char。
給定了ciCharCompare,就很容易寫出我們的第一個忽略大小寫的兩個字串比較函數
在我們可以調用mismatch之前,我們必須先滿足它的前提。特別是,我們必須確定一個字串是
int ciStringCompareImpl(const string& s1, // 實作看下文 const string& s2); int ciStringCompare(const string& s1, const string& s2) { if (s1.size() <= s2.size()) return ciStringCompareImpl(s1, s2); else return -ciStringCompareImpl(s2, s1); }
在ciStringCompareImpl中,大部分工作由mismatch來完成。它返回一對迭代器,表示了區間中第一個對應的字符不相同的
int ciStringCompareImpl(const string& si, const strings s2) { typedef pair // PSCI = 「pair of string::const_iterator> PSCI; // string::const_iterator」 PSCI p = mismatch( // 下文解釋了 s1.begin(), s1.end(), // 為什麼我們需要not2 s2.begin(), not2(ptr_fun(ciCharCompare))); if (p.first== s1.end()) { // 如果為真,s1等於 if (p.second == s2.end()) return 0; // s2或s1比s2短 else return -1; } return ciCharCompare(*p.first, *p.second); // 兩個字串的關係 } // 和不匹配的字元一樣
幸運的是,註釋把所有東西都弄清楚了。基本上,一旦你知道了字串中
mismatch會停止。我們不能為此使用ciCharCompare,因為它返回-1、 1或0,而當字元匹配時它返回0,就像strcmp。如果我們把 ciCharCompare作為判斷式傳給mismatch,C++會 把ciCharCompare的返回類型轉換為bool,而當然bool中零的等價物是false,正好和我們想要的相反!同樣的,當 ciCharCompare返回1或-1,那會被解釋成true,因為,就像C,所有非零整數值都看作 true。這再次和我們想要的相反。要修正這個語義 倒置,我們在ciCharCompare前面放上not2和ptr_fun,而且我們都會一直很快樂地生活。
我們的第二個方法ciStringCompare是產生一個合適的STL判斷式:可以在關聯容器中用作比較函數的函數。這個實現很短也很好
bool ciCharLess(char c1, char c2) // 返回在忽略大小寫 { // 的情況下c1是否在c2前面; tolower(static_cast(c1)) < tolower(static_cast(c2)); } bool ciStringCompare(const string& s1, const string& s2) { return lexicographical_compare( s1.begin(), s1.end(), // 關於這個 s2.begin(), s2.end(), // 算法使用的 ciCharLess); // 討論在下文 }
不,我不會讓你再有懸念了。名字最長的算法是set_symmetric_difference。
如果你熟悉lexicographical_compare的行為,上面的代碼在清楚不過了。如果你不明瞭的話,就可能像隔著一塊混凝土
lexicographical_compare是strcmp的泛型版本。strcmp只對字符數組起作用,但 lexicographical_compare對所有任何類型的值的區間都起作用。同時,strcmp總是比較兩個字元看它們的關係是相等、小於或 大於另一個。lexicographical_compare可以傳入一個決定兩個值是否滿足一個使用者定義標準的二元判斷式。
在上面的調用中,lexicographical_compare用來尋找s1和s2第一個不同的位置,基於呼叫 ciCharLess 的結果。如 果,使用那個位置的字元ciCharLess返回true,lexicographical_compare也是;如果,在第一個字元不同的位置,從第 一個字串來的字元先於對應的來自第二個字串的字元
談了很多關於mismatch和lexicographical_compare。雖然我專注於可移植性,但如果我沒有提到忽略大小寫字串 比較函數作為對標準C函式庫的非標準擴展而廣泛存在
int ciStringCompare(const string& s1, const string& s2) { return stricmp(s1.c_str(), s2.c_str()); // 你的系統上的函數名可能不是stricmp } 有的人可能稱此為技巧(hack),但stricmp/strcmpi被最佳化為只做一件事情,對長字串運行起來一般比通用的 算法mismatch 和lexicographical_compare快得多。如果那對你很重要,你可能不在乎你用非標準C函數完成 標準STL算法。有時候使用STL去認識到其他優越的方法是最為有效的方式。
C++ 編譯器免費下載或試用
GNU C++ http://gcc.gnu.org/
cygwin (GNU + cygnus + Windows) http://cygwin.com/,一個成功將Unix開發環境移植至Win32平台的環境,很多有名的遊戲,像Doom即是使用此環境開發而成。
Borland C++ 5.5 http://www.borland.com/bcppbuilder/freecompiler/cppc55steps.html
KAI C++ http://www.kai.com/
C++ 相關資源
C++ Boost http://www.boost.org/
Code Project http://www.codeproject.com
Code Guru http://codeguru.earthweb.com
G++ FAQ http://www.faqs.org/faqs/g++-FAQ/
ISO IEC JTC1/SC22/WG21 - C++ http://anubis.dkuug.dk/jtc1/sc22/wg21/
ACCU (Association of C & C++ Users) http://www.accu.org/index.htm
SourceForge http://sourceforge.net
Sage++ http://www.extreme.indiana.edu/sage/
GP / STL
Dinkum C++ Library http://www.dinkumware.com/
STLport http://www.stlport.org/
SGI STL http://www.sgi.com/tech/stl/
RougeWave Standard C++ Library http://www.ccd.bnl.gov/bcf/cluster/pgi/pgC++_lib/stdlib.htm
STDCXX - Apache C++ Standard Library
http://incubator.apache.org/stdcxx/index.html
macstl http://www.pixelglow.com/macstl/
Safe STL http://www.horstmann.com/safestl.html
Tiny Template Library (TTL) http://tinytl.sourceforge.net/ STLSoft http://synesis.com.au/software/stlsoft/
http://www.melikyan.com/ptypes/
collection of STL documentation http://www.ge.infn.it/geant4/training/stl.html
Qt
TrollTech http://www.trolltech.com
Patterns
Pattern Depot http://www.patterndepot.com
Huston Design Patterns http://rampages.onramp.net/~huston/dp/patterns.html
UML
UML Resource Page http://www.omg.org/technology/uml/
TOOLs
PERL http://www.perl.com/
TCL http://tcl.activestate.com/
RCS http://www.gnu.org/software/rcs/rcs.html
其他技術連結
MSDN http://msdn.microsoft.com
AT&T Labs Research - Software Tools http://www.research.att.com/sw/tools/
點空間 http://www.dotspace.idv.tw
大陸技術網站
中國軟件 CSDN http://www.csdn.net
(user/coder/programmer/engineer/developer 大型入口網站)
UML 播種機 http://www.umlchina.com
STL 中文站 http://www.stlchina.org/
個人首頁
Bjarne Stroustrup http://www.research.att.com/~bs/
Stanley B. Lippman http://people.we.mediaone.net/stanlipp/index.html
David Musser http://www.cs.rpi.edu/~musser/
Scott Meyers http://www.aristeia.com/
Nicolai M. Josuttis http://www.josuttis.com/
Bruce Eckel http://www.bruceeckel.comHerb Sutter http://www.gotw.ca/
Andrei Alexandrescu http://www.moderncppdesign.com
Sleepless in Java http://www.oreilly.com.tw/sleepless/index.htm
Royal http://www.royaloo.com
期刊
Dr. Dobb's Journal http://www.ddj.com/
C/C++ Users Journal http://www.cuj.com/
MSDN Online http://msdn.microsoft.com/msdnmag/
Windows Developers Journal http://www.wdj.com
留言列表