2016-04-27 51 views
-1

ISO-8859-5標準是unicode字符集的子集。我想測試在C++的ISO-8859-5的字符子集中是否支持unicode字符。要做到這一點,我想編寫一個函數,如下面的isLegal,以便下面的代碼將過濾出非ISO-8859-5字符。測試Unicode代碼點是否在使用C++的ISO-8859-5集合中

假設wstring來自unicode編碼的字符串。

wstring str = L"AåБ0"; 
vector<char32_t> bytes(str.begin(), str.end()); 
for (vector<char32_t>::const_iterator i = bytes.begin(); i != bytes.end(); ++i){ 
if (isLegal(*i, "ISO-8859-5")) 
{ 
    std::cout << (*i) << ' '; 
} 

}

這樣做的原因是,我想支持的字符限制爲Unicode超的一個子集,使用戶無法提交類似的表情符號的和人物不在字符支持的語言。感謝您的幫助。

有沒有簡單的方法來做到這一點。使用例如編解碼器或類似的東西。舉例來說,我知道Qt的一個函數有什麼可以幫助我嗎?

QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5"); 

或者也許是一個圖書館,會爲我做這個。

注意:爲什麼我使用wstring?我的理解是unicode字符每個字符使用1到4個字節。這是與角色渲染時不同的角色的二進制表示。 std:string支持多字節字符串,但是當您嘗試隔離單個字符時,我不知道字符在哪裏開始以及它在哪裏結束,因爲每個字符中的字節寬度不一致。

因此,我使用了一個編解碼器將多字節字符串解碼到std :: wstring中,該字符串在wchar_t上模板化。 Linux上的wchar_t是4個字節寬,因此每個字符將具有一致的寬度。因此,如果將多字節unicode設置爲wstring,則可以更輕鬆地識別每個字符,因爲每個字符的寬度一致爲4個字節,所有unicode字符都將適合4位寬度,因此wstring可處理任何可能的字符Unicode格式。

+2

我投票結束這個問題作爲題外話,因爲它只是一個「給我的代碼」。 –

+0

好的。顯然我不瞭解這裏的文化。我在棧上搜索了幾天的答案。經過多年的使用網站並在可能的地方回答問題,我從來沒有在這裏問過任何問題。我正在提出一個答案,並在我完成後發佈。請告訴我如何改寫問題。 –

+0

如果你打算自己提供代碼,那麼你應該等到你準備好發佈問題和答案並同時提交它們。我們都以爲你希望我們只爲你做。我投票重新開放;一旦其他幾個人也這樣做了,你就可以發佈你的答案。 –

回答

0

沒有用於字符代碼轉換的標準C++庫。事實上,我不認爲C++實現甚至需要知道多個編碼。所以任何解決方案都需要一個庫,或者手工製作的代碼(例如一個大的switch ......)。

既然你提到的Qt,那麼,你應該能夠使用QTextCodec::canEncode

#include <QDebug> 
#include <QTextCodec> 

#include <string> 

int main() { 
    std::wstring const str = L"AåБ0"; 
    auto const *codec = QTextCodec::codecForName("ISO-8859-5"); 
    if (!codec) { 
     qFatal("Codec not found"); 
    } 

    qDebug() << "Using codec" << qPrintable(codec->name()); 

    for (auto c: str) { 
     if (codec->canEncode(c)) 
      qDebug() << c; 
    } 
} 

但是這給了我

Using codec ISO-8859-5 
65 
229 
1041 
128512 
128580 
128545 
48 

所以這是一個無解。

+1

雖然'canEncode'確實被破壞了,但是您傳遞了大量需要代理對代表的'c'。您需要將它們作爲替代對在'QString'中編碼。您需要使用'QChar'替代邏輯來檢查給定的UCS-4'c'是否可以表示爲單個'QChar'還是代理對,然後從那裏開始。 –

+0

@Kuba - 我沒有發現那些在BMP之外。感謝您的澄清。 –

+0

我不確定的一件事是L「foo」是否希望「foo」是UTF-8或者什麼:(它的實現定義,看起來,每[此答案](http://stackoverflow.com/a/ 25568251/1329652)。 –

0

對於我使用這個自定義解決方案的時刻:

#include <vector> 
#include <string> 
#include <boost/assign/std/vector.hpp> 

using namespace std; 
using namespace boost::assign; 

bool isIntInSet(int val, std::vector<int> set){ 
    if (std::find(set.begin(), set.end(), val) != set.end()) 
    { 
    return true; 
    } 
    return false; 
} 

bool isLegal(int val, string isoNum){ 
    const string ISO8859_5 = "ISO8859-5"; 
    if (ISO8859_5 == isoNum){ 
    vector<int> isoSet5; 
    isoSet5 += 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x00A0,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,0x0409,0x040A,0x040B,0x040C,0x00AD,0x040E,0x040F,0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F,0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,0x043F,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,0x044F,0x2116,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,0x045A,0x045B,0x045C,0x00A7,0x045E,0x045F; 
    if (isIntInSet(val, isoSet5))return true; 
    } 
    return false; 
} 

通過查找可見的字符集列表上http://czyborra.com/charsets/iso8859.html每個字符集不包括控制字符,所以這不是完整的ISO8859- 5個字符列表,但對所有可打印字符來說似乎足夠好了。

+2

由於所有的ISO-8859-1集都是ASCII的擴展(包括控制字符),UTF-8也是如此(因爲當你忽略前導零時,它就是Unicode本身)所以你可能想分割那個測試在兩個,快速檢查「<128」和其餘的查找 – MSalters

+0

好主意,這將使它更有效率。 –

相關問題