8.VC++における文字の取扱について

このページの情報は、私のパソコン利用環境で、少なくとも1度は実行などしたものを記載していますが、

このページの情報を利用して損害などが生じても、私(このWEBページの作成者、programtips)は一切責任は負いません。

またVisualStudio2015のインストールされた64ビット版Windows10パソコンを前提にしています。

 

1.文字コード、あるいは文字セットについて

IMEを作成していて、SKKの辞書を取り込む際に、単なるテキストファイルとしてうまく読み書きできないということがありました。

途中までは、読み書きできているようなのですが、途中からずれが生じることや、

ファイルのパスを指定するのがうまくいかないということなどもありました。

文字コード、あるいは文字セットというのは、

コンピュータの持っている情報であるところの「0と1」の羅列と、

人間の言語の文字をどう対応させるかということであることは、わかりますが、

情報機器ユーザーから見ると、それらの対応付け・変換は自動で行われていて、その詳細まではわかりにくいものと思います。

(以下、不正確かもしれませんがここでは、シフトJISや、EUC、UNICODEなどがさらに具体的な変換方式と結びついたものを文字コードと呼びます。)

ここでも、その詳細までは、追跡しませんが、

文字コードについて見てみると、かなりの種類があり、また、その変換の方式も多種多様なことに驚かされます。

 

かなり前の情報ですが、文字コードに関するページ

http://euc.jp/i18n/charcode.ja.html

 

途中で、文字コードの、対応付けの仕方を変えるものもあるようなので、かなり複雑です。

 

2.VC++2015での文字の取り扱い

では、VC++での文字の取り扱いはどうなっているのかというと、

8ビットのchar型を基本にしたマルチバイト文字データと、

16ビットのwchar_t、WCHARを基本にした、WideChar文字データがあるようです。

https://msdn.microsoft.com/ja-jp/library/6aw8xdf2(v=vs.120).aspx

 

WCHARの場合のリテラルの定義の仕方は、頭にLを付けるなどの違いがあります。

"ABC"//マルチバイト文字データリテラルの例

L"ABC"//WideChar文字データリテラルの例

 

また以下のページによると、char文字列はASCIIであり、wchar_tはUnicode対応であり、wchar_tを使うように勧めています。

https://msdn.microsoft.com/ja-jp/library/windows/desktop/ff381407(v=vs.85).aspx

またこのページにもありますが、1つの関数などについて、

char用のものと、wchar_t用のものが、別々に定義されているものがあります。

 

おおむねAとWが名前の末尾につくものです。

例えばMessageBoxについて、MessageBoxAとMessageBoxWがあります。

 

そしてこれらは、ヘッダファイルの定義で以下のような形で定義されています。

#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE

そのため、単にMessageBoxとした場合、

UNICODEがdefineされているかどうかで、MessageBoxAとMessageBoxWか使い分けられることになります。

リテラルについてもTEXT("x")とすれば、同じように使い分けができるようです。

 

この使い分けは、プロジェクトのプロパティの文字セットで変更するようです。

直接ソースコードの中で、この切り替えの部分が読み込まれる前に、#define UNICODEとしても、変更できるようです。

ただし、参照先ページにあるcharが使われなくなっているなどの話や、

wcharがユニコードでcharがそれ以外というのを、

どういう風に理解すればいいのかは疑問が残ります。

ユニコードにもいろいろ種類はあるわけですし、

これだけではエンコーディングの変換は対応できてないように思われます。

 

 

また、直接の文字入出力だけでなく、

CreateFileなどにも、char用のものと、wchar_t用のものがあるものがあるので、この使い分けも必要があります。

 

3.VC++2015でのマルチバイト文字データとWideChar文字データの変換

変換のためにVC++の関数があります。

https://msdn.microsoft.com/ja-jp/library/cc448053.aspx

https://msdn.microsoft.com/ja-jp/library/cc422021.aspx

ただし、注意書きもありますが、必ずしもうまく変換できてるわけでもないような気がします。

 

4.不明点

文字列の格納のためにCStringクラスがありますが、これにもAとWがあり、途中から文字化けする場合もあるようです。

文字コードについては、まだ不明な点が多いので、Encodingクラスなどまた調査するかもしれないです。

以下実験などしたコード

<pre><code>

#include"Windows.h"
int main()
{
//    MessageBoxW(NULL, "HELLO今日は", "", 0);                    //Unicodeで    エラー、        マルチバイトで    エラー
    MessageBoxW(NULL,
        (LPCWSTR)TEXT("HELLO今日は"), (LPCWSTR)TEXT(""), 0);    //Unicodeで    HELLO今日は、    マルチバイトで    文字化け
    MessageBoxW(NULL,
        (LPCWSTR)"HELLO今日は", (LPCWSTR)"", 0);                //Unicodeで    文字化け、        マルチバイトで    文字化け
    MessageBoxW(NULL,L"HELLO今日は", L"", 0);                    //Unicodeで    HELLO今日は、    マルチバイトで    HELLO今日は
#ifdef UNICODE    
    MessageBox(NULL,
        (LPCWSTR)TEXT("HELLO今日は"), (LPCWSTR)TEXT(""), 0);    //Unicodeで    HELLO今日は、    マルチバイトで    エラー
#else
    MessageBox(NULL, "HELLO今日は", "", 0);                        //Unicodeで    エラー、        マルチバイトで    HELLO今日は
#endif
    MessageBoxA(NULL, "HELLO今日は", "", 0);                    //Unicodeで    HELLO今日は、    マルチバイトで    HELLO今日は
    MessageBoxA(NULL,
            (LPCSTR)L"HELLO今日は", (LPCSTR)L"", 0);            //Unicodeで    H、                マルチバイトで    H
//    MessageBoxA(NULL,
//        (LPCWSTR)L"HELLO今日は", (LPCWSTR)L"", 0);                //Unicodeで    エラー、        マルチバイトで    エラー、
//    MessageBoxA(NULL, L"HELLO今日は", L"", 0);                    //Unicodeで    エラー、        マルチバイトで    エラー
//    MessageBoxA(NULL,
//        (LPCWSTR)TEXT("HELLO今日は"), (LPCWSTR)TEXT(""), 0);    //Unicodeで    エラー、        マルチバイトで    エラー
}

#include"Windows.h"
#include"atlstr.h""
int main()
{
    char stringA[] = "HELLO今日は";

    wchar_t stringW[100];



            int codePages[] = { CP_ACP,CP_MACCP,CP_OEMCP,CP_SYMBOL ,CP_THREAD_ACP ,CP_UTF7 ,CP_UTF8 };
            CStringW codePagesString[] ={ "CP_ACP","CP_MACCP","CP_OEMCP","CP_SYMBOL" ,"CP_THREAD_ACP","CP_UTF7" ,"CP_UTF8" };
            CStringA codePagesStringA[] = { "CP_ACP","CP_MACCP","CP_OEMCP","CP_SYMBOL" ,"CP_THREAD_ACP","CP_UTF7" ,"CP_UTF8" };

            int AtoWFlags[] = { MB_COMPOSITE ,MB_PRECOMPOSED ,0 };
            CStringW AtoWFlagsString[] = { "MB_COMPOSITE" ,"MB_PRECOMPOSED" ,"0" };

            for (int i = 0;i < ARRAYSIZE(codePages);i++)
            {
                for (int j = 0;j < ARRAYSIZE(AtoWFlags);j++)
                {

                    memset(stringW, 0, 100);
                    MultiByteToWideChar(codePages[i], AtoWFlags[j], stringA, sizeof(stringA), stringW, 100);
                    CStringW titleText = "AtoW";
                    titleText = titleText + " : " + codePagesString[i] + " + " + AtoWFlagsString[j];
                    MessageBoxW(0, stringW, titleText, 0);
                }
            }


            wchar_t stringW2[]= L"HELLO今日は";
            char stringA2[100];

            int WtoAFlags[] = { WC_NO_BEST_FIT_CHARS ,WC_COMPOSITECHECK ,0 };
            CStringA WtoAFlagsString[] = { "WC_NO_BEST_FIT_CHARS" ,"WC_COMPOSITECHECK" ,"0" };

            for (int i = 0;i < ARRAYSIZE(codePages);i++)
            {
                for (int j = 0;j < ARRAYSIZE(AtoWFlags);j++)
                {

                    memset(stringA2, 0, 100);
                    WideCharToMultiByte(codePages[i], WtoAFlags[j], stringW2, sizeof(stringA), stringA2, 100,0,0);
                    CStringA titleText = "WtoA";
                    titleText = titleText + " : " + codePagesStringA[i] + " + " + WtoAFlagsString[j];
                    MessageBoxA(0, stringA2, titleText, 0);
                }
            }

            
            memset(stringW, 0, 100);
            MultiByteToWideChar(CP_UTF8, 0, stringA, sizeof(stringA), stringW, 100);
            MessageBoxW(0, stringW, L"AtoW: CP_UTF8 + 0", 0);
            memset(stringA2, 0, 100);
            WideCharToMultiByte(CP_UTF8, 0, stringW, 9, stringA2, 100, 0, 0);
            MessageBoxA(0, stringA2, "WtoA: CP_UTF8 + 0 ", 0);

            memset(stringW, 0, 100);
            MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, stringA, sizeof(stringA), stringW, 100);
            MessageBoxW(0, stringW, L"AtoW: CP_UTF8 + 0", 0);
            memset(stringA2, 0, 100);
            WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK, stringW, 9, stringA2, 100, 0, 0);
            MessageBoxA(0, stringA2, "WtoA: CP_UTF8 + 0 ", 0);

}

 </code></pre>

 

 

トップページに戻る

ご意見、ご質問などは下記掲示板にお願いします。

 掲示板

 

作成2016/08/14

(c)2016  programtips




inserted by FC2 system