C 日本語文字列のソースを表示
新しいページはコチラ
移動:
案内
,
検索
※このページではC言語にも存在していたという意味で記事タイトルがC 日本語文字列になっていますが、<br /> [[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br /> <br /> == '''日本語文字列''' == char型の配列で1byte、1文字を表現できるascii文字コードというものを使っていましたが、<br /> 問題点はいくつかありますが、そのままでも日本語全角文字は表現できます。日本語文字コードは2Byteで表現されます。<br /> 全角のアルファベットからカタカナ、ひらがな、漢字、記号、あまり使わない漢字を含めて65536種類を00 00からFF FFまで<br /> で表現しています。最初の1byteが0x80~0x9F、0xE0~0xFCならばasciiコードでは定義していないため、その後ろの1byteも読み込んで1文字だと処理してくれます。<br /> マルチバイト文字と呼んでいます。asciiコードですでに使われている部分は使えないとしても、日本語文字コードは15616種類を使えます。これでも十分です。<br /> <br /> 問題点1は文字数と配列の大きさが一致しないことです。<br /> 加えて、0x80 0x5cのように2byte文字コードの中に0x5cが登場すると、0x5c='\'ですので、次の文字はエスケープシーケンスだとみなされ<br /> 2byteずつ出力してくれる手順より優先して、その次にくる文字の1byteの処理をしようとします。この結果文字化けが発生します。2byte文字の下位byteに0x5cが<br /> 登場するのは、以下のような文字です。<span style="color:red">但し、現在のVisualStudioC++2012では、内部的に解決するので、この問題は発生しません。とは言え、文字列検索\の検索とかで支障があるやもしれません。</span> <br /> ―,ソ,Ы,Ⅸ,噂,浬,欺,圭,構,蚕,十,申,曾,箪,貼,能,表,暴,予,禄,兔,喀,媾,彌,拿,杤,歃,濬,畚,秉,綵,臀,藹,觸,軆,鐔,饅,鷭,偆,砡,纊,犾<br /> 普段使わない文字が多いですが、使いそうなのは―,ソ,Ⅸ,噂,欺,圭,構,蚕,十,申,曾,貼,能,表,暴,予,といったあたりでしょうか。使う使わないは、それぞれの立場で異なるので、<br /> そういった分類は意味を成しませんが、ともかくこれらの文字が出てきたらエスケープシーケンスを打ち切るために'\\'という形にすればよく、<br /> 十\個,表\示,能\力とかにする手法があります。出力に限ればそれで済むことですが、検索処理でこれにはまると、面倒過ぎる。<br /> ※勘違いしてはいけないことですが、printf文で出力するときに必要となる手法としてです。<br /> テキスト文書が能\力といった形で保存しておくということを言っているのではないです。プログラム側だけで対処すべきことです。<br /> それはメモ帳のようなテキストエディタで「表示」と記述してANSI(実際はShift_JISでCP932)形式で保存しても、バイナリエディタで開いたら95 5C 8E A6と保存されることでも<br /> 理解できると思います。95 5C 5C 8E A6と保存していたら、あるテキストエディタ「表\示」とそのまま画面に出力され、適当なプログラムの方では「表示」とされることになります。<br /> <br /> このような問題から、日本語をそのままchar型でマルチバイト文字列として扱うのはよろしくないということがわかります。<br /> ※0x5cをみつけたら、もう一個\を加える処理とか、マルチバイトの先頭にくる文字コードが来たら2byteで1文字とか計算したりして、昔はPerlとかでCGI組むときでは、このままつかってたこともありました。(汗<br /> 今はいろいろ便利な関数が用意されているので、そういったことは自分で対処しなくてよくなりましたね。<br /> <br /> それで、解決策は?<br /> <br /> 実はいくつかありまして…。どれがいいとか悪いとかは、それぞれなんですけど…あの~その~面倒ですが、そのいくつかを紹介しようかと思います。<br /> 「おいおい…一つにしてよ。どうすればいいかわからんやん。」という声が聞こえてきますが、全くその通りなんですけど、いまだに宙に浮いている問題でして、<br /> 統一まではできないかと思います。<br /> でも一番いいのはこれってのはあります。でも、それはそれで、「そんなことせなあかんの?話が違う、帰るわ!」って思われるかもしれません。<br /> <br /> == '''マルチバイト文字列、ワイド文字列''' == *マルチバイト文字列<br /> マルチバイト文字列はchar型でやってきたこと。<br /> *ワイド文字列<br /> 固定の2byte以上のメモリ空間に英数字ascii範囲とか関係なくすべて同じ固定の領域に格納する方法。デメリットとしては、文字列でメモリ空間をかなり無駄にしてしまうということ。<br /> あえて英数字のみ対応のアプリを作るのは、このデメリットと引き換えにして、メモリの節約をしていることになります。それか面倒だから、asciiコードのみ対応にしたとか…。<br /> でも、言いにくいことなんですけど…、いろんな方式をいろんな人が使っている昨今でして、全体的に網羅しておかないと変換とかしないとダメなので、覚えることが多いのも事実です。<br /> Unicodeって言う方式もこれです。<br /> VisualSutdioのプロジェクトの設定でもUnicode文字列とマルチバイト文字列、どっちも使わないってのが設定できます。<br /> VisualStudioをアクティブにしている状態で[Alt]+[F7]でプロジェクトのプロパティが表示されるダイアログが表示されます。<br /> 左側のツリー構造から構成プロパティの中の全般を選択すると右側のビュー表示されるリストに文字セットというのがあります。<br /> リストには「Unicode文字セットを使用する/マルチバイト文字セットを使用する/設定なし」の3つがあり、ここで選択した設定にしたがって<br /> TCHAR型という文字列変数を定義することで、設定にしたがって、マルチバイトおよびUnicodeを判別してコンパイルしてくれます。<br /> 因みにワイド文字列型では、wchar_t型というのを使うのですが、TCHAR型は、Unicode設定だとwchar_tに置き換わることになります。<br /> <br /> ワイド文字列では、文字列リテラルへは L("yonewiki") としなければならないし、<br /> 例えば文字列を引数にする関数もwprintf(L("cStr=%s"),cStr );とかに多数の書き換えが必要になります。<br /> そして、ワイド文字がどこの国の言葉を扱うのかを定義するには、<br /> setlocale関数で設定が必要で、<br /> setlocale( LC_ALL, "Japanese" );<br /> <br /> ※ちなみに関数のリファレンスはmsdnが最強だと思うわけでして、<br /> *C++Runtimeリファレンス<br /> http://msdn.microsoft.com/ja-jp/library/634ca0c2(v=vs.90).aspx<br /> *setlocale<br /> http://msdn.microsoft.com/ja-jp/library/x99tb11d(v=vs.90).aspx<br /> <br /> のようにsetlocale関数の記述が必要になります。setlocale関数を使うには#include<locale.h>が必要です。<br /> setlocale関数でも引数に文字列リテラルを与えるので、そこでワイド文字列を使うために_wsetlocale関数もあります。<br /> _wsetlocale( LC_ALL, L("Japanese") );<br /> とします。こちらはwchar.hをインクルードするだけで使えるとのこと。<br /> wcslenは文字列の文字数をカウントする関数です。マルチバイト文字列版はstrlen関数になります。<br /> <br /> <br /> さらにwcher_t型を使うには、プリプロセッサでwchar.hを読み込まなくてはならず、<br /> <nowiki>#include<wchar.h></nowiki>と記述しないといけないです。<br /> 従って、ワイド文字列版のプログラムは以下のようになります。 <syntaxhighlight lang="cpp" line start="1"> #include <iostream> //#include<locale.h> wchar.hがインクルードされていれば、いらない。 #include<wchar.h> int main() { _wsetlocale( LC_ALL, L("Japanese")); wchar_t cStr[]=L("よねウィキyonewiki"); wprintf(L("cStr0=%s sizeof=%d StrCount=%d"), cStr0,sizeof(cStr0),wcslen(cStr0)); } </syntaxhighlight> <br /> TCHAR型も同じようなものですが、プロジェクトの設定次第で置き換わるということが特徴です。<br /> これでプロジェクトの設定をUnicodeの文字セットにしていれば、wchar_t型になり、<br /> さらにTCHAR型を使うには、プリプロセッサでtchar.hを読み込まなくてはならず、<br /> <nowiki>#include<tchar.h></nowiki>と記述しないといけないです。<br /> setlocale関数も_tsetlocale関数として置き換えておくことができます。<br /> Unicodeセットのプロジェクト設定なら結局_wsetlocaleに置き換わるだけです。<br /> 文字列リテラルは_T(" ")といった形式で記述しておきます。<br /> _tcslen関数はwcslen関数と同じです。<br /> このようにマルチバイト文字列版、ワイド文字列版、プロジェクト設定に従うTCHAR版の3つの関数があります。<br /> cout関数にはTCHAR版が無いようなので、最初からstd::wcoutと記述するか、<br /> wcout関数と_tcout関数が同じになるように定義する必要があります。実用的にはあまり使わない関数なので、あってもなくても困りません。<br /> 従って、TCHAR版のプログラムは以下のようになります。 <syntaxhighlight lang="cpp" line start="1"> #include <iostream> //#include<locale.h> tchar.hがインクルードされていれば、いらない。 #include<tchar.h> int main() { _tsetlocale( LC_ALL, _T("Japanese")); TCHAR cStr0[]=_T("表示:よねウィキの機能<yonewiki>"); _tprintf(_T("cStr0=%s sizeof=%d StrCount=%d"), cStr0,sizeof(cStr0),_tcslen(cStr0)); } </syntaxhighlight> 出力結果は <syntaxhighlight lang="cpp" line start="1"> cStr0=表示:よねウィキの機能<yonewiki> sizeof=44 StrCount=21 </syntaxhighlight> となります。 TCHAR型のユニコード(UTF-16)設定にした場合、wchar_t型のcStr0は配列番号0~21の22の大きさを持つ配列になります。<br /> Unicode文字セットですのでShft_JISとは異なる数値が使われますが、0番から順に<br /> 0x8868(表),0x793A(示),0xFF1A(:),0x3088(よ),0x306D(ね),0x30A6(ウ),0x30A3(ィ),0x30AD(キ),0x306E(の),0x6A5F(機),0x80FD(能)<br /> 0x003C(<nowiki><</nowiki>),0x0079(y),0x006F(o),0x006E(n),0x0065(e),0x0077(w),0x0069(i),0x006B(k),0x0069(i),0x003E(<nowiki>></nowiki>),0x0000(\0)<br /> のように格納されています。 あんまり変わり映えしませんが、プロジェクトの設定に従うという意味ではTCHAR型を使うのが少しお勧めです。<br /> 気を付けなければならないのは、Shift_JIS(CP932)コード文字セットで格納された配列をユニコード文字セットのプロジェクトで受け取ったり、<br /> その逆のことが起こったりする場合には変換が必要になったりと、いいことばかりではありません。<br /> この他、文字コードにはShift_JIS(CP932)ではないShift_JISやEUCやMac日本語といった文字コードもあり、可能性だけで考えると<br /> Unicode:UTF-8/UTF-16/UTF-32<br /> Shift_JIS:CP932/shift_jis/shift_jis2000/shift_jis2004<br /> Mac:x-mac-japanese<br /> EUC:CP51932/CP20932/euc-jp2000/euc-jp2004/eucJP-ms<br /> JIS:CP50220/ISO-2022-JP/ISO-2022-JP-1/ISO-2022-JP-2004/ISO-2022-JP-3<br /> JIS 1Byte:ISO-2022-JP/CP50221<br /> といった文字コードが存在し、外国語文字コードセットも含めるとかなりの数の文字コードが世界に広がっています。<br /> Unicodeも扱いがいくつかあるため、実はもう少し勉強しないといけないです。 VisualStudioでUnicodeと選択した場合は、UTF-16で扱われているということになります。<br /> UTF-8では英数字が1Byte、日本語は3Byteを使います。<br /> テキストエディタは、このあたりの解釈が厳密で、ファイルを保存するときにも文字コードセットと符号化方式を遵守していますし、<br /> 互換性を高めているものが、多いです。<br /> <br /> <br /> <br /> WindowsのVisualStudioなどでWin32 APIを使える環境であれば、以下のような型もあります。<br /> LPCSTR =const CHAR * <br /> LPCWSTR=const WCHAR *<br /> LPCTSTR=const TCHAR * <br /> LPSTR =CHAR *<br /> LPWSTR =WCHAR * <br /> LPTSTR =TCHAR *<br /> それぞれの正式な名称は <br /> Long Pointer to Constant null-terminated STRing<br /> Long Pointer to Constant null-terminated Wide STRing<br /> Long Pointer to Constant null-terminated Template STRing<br /> Long Pointer to null-terminated STRing<br /> Long Pointer to null-terminated Wide STRing<br /> Long Pointer to null-terminated Template STRing<br /> であり、その略の型名が対応しているとのこと。<br /> PCSTR/PCWSTR/PCTSTR/PSTR/PWSTR/PTSTRと先頭にLが着かないものはWin16時代に使われたものですが、今では差がありません。<br /> <br /> MFC(MicrosoftFaundationClass)というMicrosoftが提供しているクラスの文字列型には<br /> 文字列の操作を強化したCStringもあります。有名なので手ごわいですが、これはMFCです。<br /> MFCは無料では配られていないクラスライブラリでして、Microsoftが定義した型ってのはすごく一般的にも使われるくらい流行します。<br /> ということで、使うべき型は、WIN32 APIでもLPCTSTR/PCTSTRあるいはLPTSTR/PTSTRということになりましょうか。<br /> とはいっても、世界中にはいろんな型の文字列で操作されますので、いろいろな変換が必要になります。<br /> <br /> == '''マルチバイト文字列、ワイド文字列の相互変換''' ==
C 日本語文字列
に戻る。
個人用ツール
18.117.75.226
このIPアドレスのトーク
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ