2016-09-18 32 views
2

C++でunicodeについて学んでいますが、正しく動作させるには苦労しています。私は個々の文字をuint64_tとして扱おうとします。私が必要とするのは、文字を印刷するだけであれば機能しますが、問題は大文字に変換する必要があることです。大文字を配列に格納し、小文字の場合と同じインデックスを使用するだけですが、より洗練されたソリューションを探しています。私はこれと似たようなものを見つけましたquestion答えのほとんどはワイド文字を使っていますが、これは私が使うことのできないものです。ここに私がしようとしたものである:C++でunicode文字を大文字に変換する方法

#include <iostream> 
#include <locale> 
#include <string> 
#include <cstdint> 
#include <algorithm> 

// hacky solution to store a multibyte character in a uint64_t 
#define E(c) ((((uint64_t) 0 | (uint32_t) c[0]) << 32) | (uint32_t) c[1]) 

typedef std::string::value_type char_t; 
char_t upcase(char_t ch) { 
    return std::use_facet<std::ctype<char_t>>(std::locale()).toupper(ch); 
} 

std::string toupper(const std::string &src) { 
    std::string result; 
    std::transform(src.begin(), src.end(), std::back_inserter(result), upcase); 
    return result; 
} 

const uint64_t VOWS_EXTRA[] 
{ 
E("å") , E("ä"), E("ö"), E("ij"), E("ø"), E("æ") 
}; 

int main(void) { 
    char name[5]; 
    std::locale::global(std::locale("sv_SE.UTF8")); 
    name[0] = (VOWS_EXTRA[3] >> 32) & ~((uint32_t)0); 
    name[1] = VOWS_EXTRA[3] & ~((uint32_t)0); 
    name[2] = '\0'; 
    std::cout << toupper(name) << std::endl; 
} 

私は、これは文字IJをプリントアウトすることを期待しかし、それは始まり(ij)にあったように、現実には、同じ文字を出力します。


EDIT:OK、私は、標準C++ hereでのUnicodeのサポートについての詳細を読んで、私の最善の策は、このタスクのためにICUやBoost.localeのようなものを使用することであるように思えC++、本質的に扱います。 std :: stringをバイナリデータのBLOBとして扱うので、Unicode文字を大文字にするのは簡単ではないようです。uint64_tを使った私のハックな解決法は、C++標準ライブラリICUを使用して上記の動作を達成する方法の例に感謝します)

+0

Unicodeが固定幅エンコーディングであるとふりをしないでください。 –

+0

@NicolBolas申し訳ありませんが、私はunicodeでとても慣れていません。普通の文字列を使用しようとしましたが、1文字で作業することができませんでした。 – Linus

+0

非常に特殊なコンパイラを使用しない限り、 'std :: locale :: global(std :: locale(" sv_SE.UTF8 "))'はWindowsと互換性がありません。 MicrosoftのランタイムはUTF-8ロケールをサポートしていません。 'setlocale'のドキュメントを参照してください。 –

答えて

2

ICU User Guideをご覧ください。単純(1文字)の大文字小文字のマッピングの場合は、u_toupperを使用できます。フル・ケース・マッピングの場合は、u_strToUpperを使用します。例コード:

#include <unicode/uchar.h> 
#include <unicode/ustdio.h> 
#include <unicode/ustring.h> 

int main() { 
    UChar32 upper = u_toupper(U'ij'); 
    u_printf("%lC\n", upper); 

    UChar src = u'ß'; 
    UChar dest[3]; 
    UErrorCode err = U_ZERO_ERROR; 
    u_strToUpper(dest, 3, &src, 1, NULL, &err); 
    u_printf("%S\n", dest); 

    return 0; 
} 
+0

ありがとう、遅く受け入れられた答えを申し訳ありません。 ICUが働くには数時間かかりました。私は "関数への未定義参照"エラーで多くの問題がありました。 – Linus

関連する問題