2016-03-24 50 views
2

我正在開發一個項目,其中區分大小寫的操作需要替換爲不區分大小寫的操作。在此做一些閱讀後,要考慮數據的類型有:不區分大小寫的操作

  1. Ascii字符
  2. 非ASCII字符
  3. Unicode字符

請讓我知道,如果我錯過了列表中的任何內容。

以上需要單獨處理還是有C++庫可以處理它們而不涉及數據類型?

具體做法是:

  1. 是否Boost庫爲此提供支持?如果是這樣,是否有示例或關於如何使用API​​的文檔?

  2. 我瞭解了IBM的Unicode國際組件(ICU)。這是一個爲不區分大小寫的操作提供支持的庫嗎?如果是這樣,是否有示例或關於如何使用API​​的文檔?

最後,上述(和其他)方法中的哪一種更好,爲什麼?

謝謝!

基礎上的意見和答案,我寫了一個示例程序,爲了更好地理解:

#include <iostream>  // std::cout 
#include <string>   // std::string 
#include <locale>   // std::locale, std::tolower 

using namespace std; 

void ascii_to_lower(string& str) 
{ 
    std::locale loc; 
    std::cout << "Ascii string: " << str; 
    std::cout << "Lower case: "; 

    for (std::string::size_type i=0; i<str.length(); ++i) 
     std::cout << std::tolower(str[i],loc); 
    return; 
} 

void non_ascii_to_lower(void) 
{ 
    std::locale::global(std::locale("en_US.UTF-8")); 
    std::wcout.imbue(std::locale()); 
    const std::ctype<wchar_t>& f = std::use_facet<std::ctype<wchar_t> >(std::local 
    std::wstring str = L"Zoë Saldaña played in La maldición del padre Cardona."; 

    std::wcout << endl << "Non-Ascii string: " << str << endl; 

    f.tolower(&str[0], &str[0] + str.size()); 

    std::wcout << "Lower case: " << str << endl; 

    return; 
} 

void non_ascii_to_upper(void) 
{ 
    std::locale::global(std::locale("en_US.UTF-8")); 
    std::wcout.imbue(std::locale()); 
    const std::ctype<wchar_t>& f = std::use_facet<std::ctype<wchar_t> >(std::local 
    std::wstring str = L"¥£ªÄë"; 

    std::wcout << endl << "Non-Ascii string: " << str << endl; 

    f.toupper(&str[0], &str[0] + str.size()); 

    std::wcout << "Upper case: " << str << endl; 

    return; 
} 

int main() 
{ 
    string str="Test String.\n"; 

    ascii_to_lower(str); 
    non_ascii_to_upper(); 
    non_ascii_to_lower(); 

    return 0; 
} 

輸出是:

ASCII字符串:測試字符串。 小寫字母:測試字符串。

非ASCII字符串:▒▒▒▒▒ 大寫:▒▒▒▒▒

非ASCII字符串:Zo▒Salda▒a在Lamaldici▒n德爾帕德里卡多納播放。 小寫字母:zoalsalda▒a在la maldici?n del padre cardona中演奏。

雖然非ascii字符串似乎轉換爲大寫和小寫,但某些文本在輸出中不可見。爲什麼是這樣?

總的來說,示例代碼看起來好嗎?

+4

您可以將ASCII和非ASCII轉換爲utf-32,並將它們與unicode字符串本身作爲std :: wstring對待。你可以使用std :: to_lower去除大小寫因子。 – LibertyPaul

+1

@LibertyPaul你的意思是'std :: u32string'? – Simple

+0

@Simple wstring是basic_string 這是32位,但是,是的,u32string是一個很好的建議。 – LibertyPaul

回答

2

我對這個問題有點驚訝。一個簡單的搜索boost case conversion提出了第一個條目:Usage - 1.41.0 - Boost它有一個大小寫轉換的條目。

搜索stl case conversion有一個條目tolower - C++ Reference - Cplusplus.com它也顯示瞭如何使用STL進行轉換。

要進行不區分大小寫的搜索,請將它們都轉換爲小寫或大寫並進行比較。

來自boost的代碼示例。組織:從Cplusplus.com

string str1("HeLlO WoRld!"); 
to_upper(str1); // str1=="HELLO WORLD!" 

實施例:

// tolower example (C++) 
#include <iostream>  // std::cout 
#include <string>   // std::string 
#include <locale>   // std::locale, std::tolower 

int main() 
{ 
    std::locale loc; 
    std::string str="Test String.\n"; 
    for (std::string::size_type i=0; i<str.length(); ++i) 
    std::cout << std::tolower(str[i],loc); 
    return 0; 
} 

對於ASCII字符(字符的ASCII值< 128),應該沒有問題。如果您正在使用MCBS,則可能需要使用本地代碼頁。 Unicode應該沒有問題AFAIK。

至於馬特喬丹的評論:

這個請求真正的問題是,許多語言都有大小寫轉換的背景條件 - 例如希臘語中的大寫sigma 0x3A3應該變爲0x03C3或0x03C2,具體取決於它是否在單詞的末尾。

如果boost庫支持這個,我會很驚喜。如果他們不這樣做,你將不得不測試它並報告錯誤。他們的頁面上沒有提及他們是否執行任何上下文案例轉換。解決辦法可能是測試轉換爲小寫和比較,並轉換爲大寫和比較。如果兩者都是真的,那麼就有一場比賽,這應該對99.99%的情況起作用。

Bjarne Stroustrup發現一篇有趣的文章here,這是一篇關於Locales的好書。

+0

謝謝!我已經添加了一個示例代碼來更好地理解這一點。 – Maddy

1

你已經有一個關於提升的非常好的答案。此處一些補充說明:

字符編碼

ASCII字符上7位編碼。 ISO 8859-1windows-1252通過利用第8位來擴展具有有限國際字符集的ASCII。

Unicode標準更進一步擴展ASCII,並在32位上定義。有幾種編碼可用:32位上的UTF32是最簡單的(1個Unicode字符= 1個字符),但UTF16UTF8編碼允許使用較小的字符存儲具有可變大小編碼的Unicode文本。

爲了使它更加困難,不同的操作系統使用不同的約定。在linux上,wchart_t通常是用於unicode的32位寬字符,而wstring是基於wchar_t的字符串,而char使用UTF8編碼。在窗口wchar_t被定義爲16位,因爲窗口的本地編碼是UCS-2(unicode的子集),並且char通常被理解爲win1252。

與字符大小和編碼

所以回來在你處理問題,有兩個方面需要考慮:

  • 存儲 - 如果要一刀切一切,你可以使用char32_t,它可以保存任何unicode字符的ASCII碼。對於字符串使用basic_string<char32_t>u32string,這些字符串支持您用於處理普通字符串的所有功能。或者你可以使用普通字符串並堅持UTF 8 everywhere

  • 編碼 - 您的應用程序如何解釋char中包含的值,並執行轉換爲小寫或大寫等操作。這在適用的locale中定義。

幸運的是,C++標準庫可與所有這些方面應對:

  • 現場幫助管理uppercase &小寫轉換,可以使用相應的編碼測試(例如isupper()isalpha(),...)
  • codecvt允許各種encondings之間進行轉換

其他庫

ICU庫似乎不提供大小寫不敏感的比較。它爲文本處理提供支持,例如,遍歷文本元素,使用排序規則排序等等。

由於這些享受的廣泛支持,我建議繼續使用標準庫或提升。

+0

謝謝!我已經添加了一個示例代碼來更好地理解這一點。 – Maddy

+1

@Maddy您的語言環境的第一部分對應於en =英語和美國=美國等國家/地區設置,如貨幣。英語只知道a-z,沒有特殊的字符用於上轉換。將西班牙語設置爲語言以獲得Zoë的propper轉換。 – Christophe

+0

並找到您的Linux系統上支持的語言環境:http://www.cyberciti.biz/faq/how-to-set-locales-i18n-on-a-linux-unix/ – Christophe