2015-10-05 69 views
0

這個問題以前已經問過,但它的解決方案依賴於我不想依賴的Microsoft基礎類。基本上我想做的是將一個Unicode字符轉換爲它的等價碼。來自Unicode字符的Codepoint?

以下是使用MFC的解決方案。有沒有辦法做到這一點,而不使用afxwin.h?

#include <afxwin.h> 

#include <iostream> 

int main() { 
    using namespace std; 

    TCHAR myString[50] = _T("عربى"); 
    int stringLength = _tcslen(myString); // <----- edit here 

    for(int i=0;i<stringLength;i++) 
    { 
     unsigned int number =myString[i]; 
     cout<<number<<endl; 
    } 
} 
Output: 

1593 
1585 
1576 
1609 
+0

如果你真的想徹底,你需要代理對支持。 –

+0

您是否將您的項目編譯爲UNICODE或ANSI? – roeland

+0

'TCHAR'和'_tcslen()'不是MFC的一部分。它們是C運行時庫的一部分。它們在'tchar.h'中聲明。但是這段代碼並沒有給你正確的代碼點,因爲它沒有考慮UTF-16替代品(假設'UNICODE'被定義爲'TCHAR'映射到'wchar_t')。 –

回答

2

更新

如果你的編譯器支持它,要做到這一點最簡單的方法可能是寫你的常量字符串作爲U"عربى"。這將爲您提供一組char32_t字符,其代碼點只是其值static_cast<uint32_t>()轉換後的值。要以標準格式打印它們,只需加上U+並打印十六進制值。

在C++ 14編譯器上試試這個(我建議將源文件保存爲utf-8)。

#include <cstdlib> 
#include <iomanip> 
#include <iostream> 

using std::cout; 

int main() 
{ 
    constexpr char32_t codepoints[] = U"عربى"; 
    constexpr size_t n = sizeof(codepoints)/sizeof(char32_t); 

    cout.setf(cout.hex, cout.basefield);  // Output in hex 
    cout.setf(cout.right, cout.adjustfield); // Prepending 
    cout.fill('0');       // leading zeroes 
    // Fixed: Don’t print the terminating U'\0'. 
    for (size_t i = 0; i < n && codepoints[i]; ++i) 
    cout << "U+" << std::setw(4) << (unsigned long)codepoints[i] << std::endl; 

    return EXIT_SUCCESS; 
} 

換算

的C++ STL具有<codecvt>現在,可以從UTF-8或UTF-16轉換爲UCS-32。示例代碼(來自http://en.cppreference.com/w/cpp/locale/codecvt_utf16):

#include <fstream> 
#include <iostream> 
#include <string> 
#include <locale> 
#include <codecvt> 

void prepare_file() 
{ 
    // UTF-16le data (if host system is little-endian) 
    char16_t utf16le[4] ={0x007a, // latin small letter 'z' U+007a 
         0x6c34, // CJK ideograph "water" U+6c34 
         0xd834, 0xdd0b}; // musical sign segno U+1d10b 
    // store in a file 
    std::ofstream fout("text.txt"); 
    fout.write(reinterpret_cast<char*>(utf16le), sizeof utf16le); 
} 

int main() 
{ 
    prepare_file(); // open as a byte stream 
    std::wifstream fin("text.txt", std::ios::binary); 
    // apply facet 
    fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>)); 

    for (wchar_t c; fin.get(c);) 
    std::cout << std::showbase << std::hex << c << '\n'; 
} 

C11和C++ 11還具有的功能爲多字節UTF-8和UTF-16和寬字符串之間轉換(從這裏:http://en.cppreference.com/w/c/string/multibyte/mbrtoc32)。 mbstowcs()函數也可能是相關的。

#include <stdio.h> 
#include <locale.h> 
#include <string.h> 
#include <uchar.h> 
#include <assert.h> 

mbstate_t state; 

int main(void) 
{ 
    setlocale(LC_ALL, "en_US.utf8"); 
    char *str = u8"z\u00df\u6c34\U0001F34C"; // or u8"zß水" 
    printf("Processing %zu bytes: [ ", strlen(str)); 
    for(char* p = str; *p; ++p) 
    printf("%#x ", (unsigned char)*p); puts("]"); 

    char32_t c32; 
    char *ptr = str, *end = str + strlen(str); 
    int rc; 

    while(rc = mbrtoc32(&c32, ptr, end - ptr, &state)) { 
    printf("Next UTF-32 char: %#x obtained from ", c32); 
    assert(rc != -3); // no surrogate pairs in UTF-32 
    if(rc > 0) { 
     printf("%d bytes [ ", rc); 
     for(int n = 0; n < rc; ++n) 
     printf("%#x ", (unsigned char)ptr[n]); puts("]"); 
     ptr += rc; 
    } 
    } 
} 

儘管這些實施例使用十六進制代碼,C11和C++ 11個支持Unicode字符串(http://en.cppreference.com/w/cpp/language/string_literal)。由於上面示例中的Unicode是utf-16le,因此將其寫爲常量的標準方式是u"عربى"。您也可以將其編碼爲帶有U"عربى"的ucs-32,而不必執行任何代理對轉換。

+0

謝謝,但我的下一個問題是我可以插入我從字符串中提取的字符來代替您在上面輸入的十六進制代碼。我想直接將字符轉換爲unicode碼點。 – Svetsi

+0

已更新,並附有說明。這使得這更簡單。 – Davislor

+0

感謝您的努力Lorehead。不要誤解我的意思,但我只需要說一件事。我不是世界上最先進的程序員,看上面的語法看起來非常複雜。在使用之前我必須先了解它。我認爲只有練習才能讓我完成這個任務。你使用的語法非常先進嗎?我會認爲這是。我只是讓你知道我不是軟件工程師,所以這將是一個理解你的答覆的努力。 – Svetsi

0

簡單,閱讀unicode規範,並注意unicode標量,代理和補充字符,擴展字形集羣在你自己的。

或者您可以使用當今大多數操作系統所包含的IBM ICU庫。

如果問題只是MFC頭文件,你可以定義UNICODE,_UNICODE和include tchar.h。