C 日本語文字列 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(マルチバイト文字列、ワイド文字列の相互変換)
 
1行: 1行:
 +
[[C PlusPlus#Cにもあった技術|C++]]へ戻る
 +
 +
 
※このページではC言語にも存在していたという意味で記事タイトルがC 日本語文字列になっていますが、<br />
 
※このページではC言語にも存在していたという意味で記事タイトルがC 日本語文字列になっていますが、<br />
 
[[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br />
 
[[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br />
 
<br />
 
<br />
 
== '''日本語文字列''' ==
 
== '''日本語文字列''' ==
char型の配列で1byte、1文字を表現できるascii文字コードというものを使っていましたが、<br />
+
 
問題点はいくつかありますが、そのままでも日本語全角文字は表現できます。日本語文字コードは2Byteで表現されます。<br />
+
char型の配列で1byte、1文字を表現できるascii文字コードというものを使っていましたが、問題点はいくつかありますが、そのままでも日本語全角文字は表現できます。日本語文字コードは2Byteで表現されます。
全角のアルファベットからカタカナ、ひらがな、漢字、記号、あまり使わない漢字を含めて65536種類を00 00からFF FFまで<br />
+
全角のアルファベットからカタカナ、ひらがな、漢字、記号、あまり使わない漢字を含めて65536種類を00 00からFF FFまでで、表現しています。最初の1byteが0x80~0x9F、0xE0~0xFCならばasciiコードでは定義していないため、その後ろの1byteも読み込んで1文字だと処理してくれます。マルチバイト文字と呼んでいます。asciiコードですでに使われている部分は使えないとしても、日本語文字コードは15616種類を使えます。これでも十分です。<br />
で表現しています。最初の1byteが0x80~0x9F、0xE0~0xFCならばasciiコードでは定義していないため、その後ろの1byteも読み込んで1文字だと処理してくれます。<br />
+
 
マルチバイト文字と呼んでいます。asciiコードですでに使われている部分は使えないとしても、日本語文字コードは15616種類を使えます。これでも十分です。<br />
+
 
<br />
+
 
問題点1は文字数と配列の大きさが一致しないことです。<br />
+
問題点1は文字数と配列の大きさが一致しないことです。加えて、0x80 0x5cのように2byte文字コードの中に0x5cが登場すると、0x5c='\'ですので、次の文字はエスケープシーケンスだとみなされ2byteずつ出力してくれる手順より優先して、その次にくる文字の1byteの処理をしようとします。この結果文字化けが発生します。2byte文字の下位byteに0x5cが登場するのは、以下のような文字です。<span style="color:red">但し、現在のVisualStudioC++2012では、内部的に解決するので、この問題は発生しません。とは言え、文字列検索\の検索とかで支障があるやもしれません。</span>  
加えて、0x80 0x5cのように2byte文字コードの中に0x5cが登場すると、0x5c='\'ですので、次の文字はエスケープシーケンスだとみなされ<br />
+
 
2byteずつ出力してくれる手順より優先して、その次にくる文字の1byteの処理をしようとします。この結果文字化けが発生します。2byte文字の下位byteに0x5cが<br />
+
 
登場するのは、以下のような文字です。<span style="color:red">但し、現在のVisualStudioC++2012では、内部的に解決するので、この問題は発生しません。とは言え、文字列検索\の検索とかで支障があるやもしれません。</span> <br />
+
 
―,ソ,Ы,Ⅸ,噂,浬,欺,圭,構,蚕,十,申,曾,箪,貼,能,表,暴,予,禄,兔,喀,媾,彌,拿,杤,歃,濬,畚,秉,綵,臀,藹,觸,軆,鐔,饅,鷭,偆,砡,纊,犾<br />
 
―,ソ,Ы,Ⅸ,噂,浬,欺,圭,構,蚕,十,申,曾,箪,貼,能,表,暴,予,禄,兔,喀,媾,彌,拿,杤,歃,濬,畚,秉,綵,臀,藹,觸,軆,鐔,饅,鷭,偆,砡,纊,犾<br />
普段使わない文字が多いですが、使いそうなのは―,ソ,Ⅸ,噂,欺,圭,構,蚕,十,申,曾,貼,能,表,暴,予,といったあたりでしょうか。使う使わないは、それぞれの立場で異なるので、<br />
+
 
そういった分類は意味を成しませんが、ともかくこれらの文字が出てきたらエスケープシーケンスを打ち切るために'\\'という形にすればよく、<br />
+
 
\個,表\示,能\力とかにする手法があります。出力に限ればそれで済むことですが、検索処理でこれにはまると、面倒過ぎる。<br />
+
普段使わない文字が多いですが、使いそうなのは―,ソ,Ⅸ,噂,欺,圭,構,蚕,十,申,曾,貼,能,表,暴,予,といったあたりでしょうか。使う使わないは、それぞれの立場で異なるので、そういった分類は意味を成しませんが、ともかくこれらの文字が出てきたらエスケープシーケンスを打ち切るために'\\'という形にすればよく、十\個,表\示,能\力とかにする手法があります。出力に限ればそれで済むことですが、検索処理でこれにはまると、面倒過ぎる。<br />
※勘違いしてはいけないことですが、printf文で出力するときに必要となる手法としてです。<br />
+
 
テキスト文書が能\力といった形で保存しておくということを言っているのではないです。プログラム側だけで対処すべきことです。<br />
+
 
それはメモ帳のようなテキストエディタで「表示」と記述してANSI(実際はShift_JISでCP932)形式で保存しても、バイナリエディタで開いたら95 5C 8E A6と保存されることでも<br />
+
※勘違いしてはいけないことですが、printf文で出力するときに必要となる手法としてです。テキスト文書が能\力といった形で保存しておくということを言っているのではないです。プログラム側だけで対処すべきことです。それはメモ帳のようなテキストエディタで「表示」と記述してANSI(実際はShift_JISでCP932)形式で保存しても、バイナリエディタで開いたら95 5C 8E A6と保存されることでも理解できると思います。95 5C 5C 8E A6と保存していたら、あるテキストエディタ「表\示」とそのまま画面に出力され、適当なプログラムの方では「表示」とされることになります。このような問題から、日本語をそのままchar型でマルチバイト文字列として扱うのはよろしくないということがわかります。※0x5cをみつけたら、もう一個\を加える処理とか、マルチバイトの先頭にくる文字コードが来たら2byteで1文字とか計算したりして、昔はPerlとかでCGI組むときでは、このままつかってたこともありました。(汗<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 />
でも一番いいのはこれってのはあります。でも、それはそれで、「そんなことせなあかんの?話が違う、帰るわ!」って思われるかもしれません。<br />
+
 
<br />
+
  
 
== '''マルチバイト文字列、ワイド文字列''' ==
 
== '''マルチバイト文字列、ワイド文字列''' ==
39行: 40行:
  
 
*ワイド文字列<br />
 
*ワイド文字列<br />
固定の2byte以上のメモリ空間に英数字ascii範囲とか関係なくすべて同じ固定の領域に格納する方法。デメリットとしては、文字列でメモリ空間をかなり無駄にしてしまうということ。<br />
+
固定の2byte以上のメモリ空間に英数字ascii範囲とか関係なくすべて同じ固定の領域に格納する方法。デメリットとしては、文字列でメモリ空間をかなり無駄にしてしまうということ。あえて英数字のみ対応のアプリを作るのは、このデメリットと引き換えにして、メモリの節約をしていることになります。それか面倒だから、asciiコードのみ対応にしたとか…。でも、言いにくいことなんですけど…、いろんな方式をいろんな人が使っている昨今でして、全体的に網羅しておかないと変換とかしないとダメなので、覚えることが多いのも事実です。Unicodeって言う方式もこれです。Unicodeの符号化方式のUTF-16は、基本的には半角の英数字も含めて、2byteで1文字を表すためメモリは無駄にしますが、変換効率が高いために実行速度が速くなるというメリットがあります。実行速度の速さにあやかれるほどのプログラムを作るかどうかは未知数です。<br />
あえて英数字のみ対応のアプリを作るのは、このデメリットと引き換えにして、メモリの節約をしていることになります。それか面倒だから、asciiコードのみ対応にしたとか…。<br />
+
 
でも、言いにくいことなんですけど…、いろんな方式をいろんな人が使っている昨今でして、全体的に網羅しておかないと変換とかしないとダメなので、覚えることが多いのも事実です。<br />
+
 
Unicodeって言う方式もこれです。<br />
+
VisualSutdioのプロジェクトの設定でもUnicode文字列とマルチバイト文字列、どっちも使わないってのが設定できます。VisualStudioをアクティブにしている状態で[Alt]+[F7]でプロジェクトのプロパティが表示されるダイアログが表示されます。左側のツリー構造から構成プロパティの中の全般を選択すると右側のビュー表示されるリストに文字セットというのがあります。リストには「Unicode文字セットを使用する/マルチバイト文字セットを使用する/設定なし」の3つがあり、ここで選択した設定にしたがって、Visual C++だけの機能になりますが、TCHAR型という文字列変数を定義することで、設定にしたがって、マルチバイトおよびUnicodeを判別してコンパイルしてくれます。因みにワイド文字列型では、wchar_t型というのを使うのですが、TCHAR型は、Unicode設定だとwchar_tに置き換わることになります。
Unicodeの符号化方式のUTF-16は、基本的には半角の英数字も含めて、2byteで1文字を表すためメモリは無駄にしますが、変換効率が高いために実行速度が速くなるというメリットがあります。<br />
+
 
実行速度の速さにあやかれるほどのプログラムを作るかどうかは未知数です。<br />
+
 
 +
どっちも使わない、設定なしを選択した方がよい場合もあります。それはワイド文字、Unicodeとか、マルチバイト文字を使わないアプリ構成にしたい場合です。Windows.hで提供されるようなAPIでさえも文字列を引数にとることはありますが、この引数の受け取り方が設定なしの場合、なにかとchar型のままでいいよ。という具合になります。そうするとwchar型とかtchar型を使わなくてもよいので、ひたすら文字列はchar型のみを扱えばよいことになります。最初のうちは英語のみ対応のアプリにして練習するのもありかなと思いますので、設定なしという道もあっていいかと思います。むしろ学術的なことに専念するアプリやそういった専門書なんかでは、設定なしを使って説明されるパターンがあります。これは文字列うんぬんを語ると限られたページの中で専門的なことが説明できなくなるからだと思います。ここで書いたことを知っていればあとで、ワイド文字対応に応用することなんかは簡単なことですから、別の専門的なことを勉強するにあたっては、設定なしを選択して、英語版アプリ(1バイト文字、ASCIIコード範囲)を作る覚悟で取り組むということもあっていいかと思います。      
 +
 
 +
 
 +
ワイド文字列では、文字列リテラルへは L"yonewiki" としなければならないし、例えば文字列を引数にする関数もwprintf(L"cStr=%s",cStr );とかに多数の書き換えが必要になります。そして、ワイド文字がどこの国の言葉を扱うのかを定義するには、setlocale関数で設定が必要で、setlocale( LC_ALL, "Japanese" );※リテラルの設定では省略されていますが、setlocale( LC_ALL, "Japanese_Japan.932" ); />
 +
と設定していることになります。出力するときには日本語のShift_JISにしてねということです。今はWindowsPCのコマンドプロンプトで動作を確認しているからです。<br />
 +
 
  
VisualSutdioのプロジェクトの設定でもUnicode文字列とマルチバイト文字列、どっちも使わないってのが設定できます。<br />
 
VisualStudioをアクティブにしている状態で[Alt]+[F7]でプロジェクトのプロパティが表示されるダイアログが表示されます。<br />
 
左側のツリー構造から構成プロパティの中の全般を選択すると右側のビュー表示されるリストに文字セットというのがあります。<br />
 
リストには「Unicode文字セットを使用する/マルチバイト文字セットを使用する/設定なし」の3つがあり、ここで選択した設定にしたがって<br />
 
Visual C++だけの機能になりますが、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 />
 
※リテラルの設定では省略されていますが、setlocale( LC_ALL, "Japanese_Japan.932" );<br />
 
と設定していることになります。出力するときには日本語のShift_JISにしてねということです。<br />
 
今はWindowsPCのコマンドプロンプトで動作を確認しているからです。
 
<br />
 
 
※ちなみに関数のリファレンスはmsdnが最強だと思うわけでして、<br />
 
※ちなみに関数のリファレンスはmsdnが最強だと思うわけでして、<br />
*C++Runtimeリファレンス<br />
+
*C++Runtimeリファレンス(※実行時に動的に呼び出せるという意味でRuntimeとついています。通常はRuntimeライブラリはWindowsのバージョンによって異なるライブラリが入っていますが、Versionが上がっても基本的には、同じようなものだと考えて差し支えないです。静的にもコンパイルできますので、Windows系 Visual C++で使えるC++リファレンスと思ってよいかと。でもいろんなバージョンがあるからこそ、MSVCRTxx.dllが無いのでエラーってなったりする不具合もネット界隈を賑わしています。全部、最初から配ればいいのにMicrosoft…何やってんだ…素人には手ごわいエラーだけに印象悪いっしょ。ちょっと調べることができたら解決できるんですけどね。まぁなんのこっちゃわからん人には難しいわな。)<br />
 
http://msdn.microsoft.com/ja-jp/library/634ca0c2(v=vs.90).aspx<br />
 
http://msdn.microsoft.com/ja-jp/library/634ca0c2(v=vs.90).aspx<br />
 
*setlocale<br />
 
*setlocale<br />
 
http://msdn.microsoft.com/ja-jp/library/x99tb11d(v=vs.90).aspx<br />
 
http://msdn.microsoft.com/ja-jp/library/x99tb11d(v=vs.90).aspx<br />
 
<br />
 
<br />
のようにsetlocale関数の記述が必要になります。setlocale関数を使うには#include<locale.h>が必要です。<br />
+
のようにsetlocale関数の記述が必要になります。setlocale関数を使うには#include<locale.h>が必要です。setlocale関数でも引数に文字列リテラルを与えるので、そこでワイド文字列を使うために_wsetlocale関数もあります。<br />
setlocale関数でも引数に文字列リテラルを与えるので、そこでワイド文字列を使うために_wsetlocale関数もあります。<br />
+
 
_wsetlocale( LC_ALL, L("Japanese") );<br />
+
 
とします。こちらはwchar.hをインクルードするだけで使えるとのこと。<br />
+
_wsetlocale( LC_ALL, L"Japanese" );<br />
 +
 
 +
 
 +
とします。こちらはwchar.hをインクルードするだけで使えるとのこと。
 
wcslenは文字列の文字数をカウントする関数です。通常のマルチバイト文字でもワイド文字でもない、何もしない関数はstrlen関数になります。<br />
 
wcslenは文字列の文字数をカウントする関数です。通常のマルチバイト文字でもワイド文字でもない、何もしない関数はstrlen関数になります。<br />
<br />
+
 
<br />
+
 
さらにwcher_t型を使うには、プリプロセッサでwchar.hを読み込まなくてはならず、<br />
+
 
 +
さらにwcher_t型を使うには、プリプロセッサでwchar.hを読み込まなくてはならず、
 +
 
 +
 
 
<nowiki>#include<wchar.h></nowiki>と記述しないといけないです。<br />
 
<nowiki>#include<wchar.h></nowiki>と記述しないといけないです。<br />
 
従って、ワイド文字列版のプログラムは以下のようになります。
 
従って、ワイド文字列版のプログラムは以下のようになります。
<syntaxhighlight lang="cpp" line start="1">
+
 
 +
 
 +
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> wchar.hがインクルードされていれば、いらない。
 
//#include<locale.h> wchar.hがインクルードされていれば、いらない。
 
#include<wchar.h>
 
#include<wchar.h>
 
int main() {
 
int main() {
     _wsetlocale( LC_ALL, L("Japanese"));
+
     _wsetlocale( LC_ALL, L"Japanese");
     wchar_t cStr[]=L("よねウィキyonewiki");
+
     wchar_t cStr[]=L"よねウィキyonewiki";
     wprintf(L("cStr0=%s sizeof=%d StrCount=%d"), cStr0,sizeof(cStr0),wcslen(cStr0));
+
     wprintf(L"cStr0=%s sizeof=%d StrCount=%d", cStr0,sizeof(cStr0),wcslen(cStr0));
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
<br />
 
<br />
TCHAR型も同じようなものですが、プロジェクトの設定次第で置き換わるということが特徴です。<br />
+
TCHAR型も同じようなものですが、プロジェクトの設定次第で置き換わるということが特徴です。これでプロジェクトの設定をUnicodeの文字セットにしていれば、wchar_t型になり、さらにTCHAR型を使うには、プリプロセッサでtchar.hを読み込まなくてはならず、<br />
これでプロジェクトの設定をUnicodeの文字セットにしていれば、wchar_t型になり、<br />
+
 
さらにTCHAR型を使うには、プリプロセッサでtchar.hを読み込まなくてはならず、<br />
+
<nowiki>#include<tchar.h></nowiki>
<nowiki>#include<tchar.h></nowiki>と記述しないといけないです。<br />
+
 
setlocale関数も_tsetlocale関数として置き換えておくことができます。<br />
+
と記述しないといけないです。setlocale関数も_tsetlocale関数として置き換えておくことができます。Unicodeセットのプロジェクト設定なら結局_wsetlocaleに置き換わるだけです。文字列リテラルは_T("  ")といった形式で記述しておきます。_tcslen関数はwcslen関数と同じです。このようにマルチバイト文字列版、ワイド文字列版、プロジェクト設定に従うTCHAR版の3つの関数があります。cout関数にはTCHAR版が無いようなので、最初からstd::wcoutと記述するか、wcout関数と_tcout関数が同じになるように定義する必要があります。実用的にはあまり使わない関数なので、あってもなくても困りません。<br />
Unicodeセットのプロジェクト設定なら結局_wsetlocaleに置き換わるだけです。<br />
+
 
文字列リテラルは_T("  ")といった形式で記述しておきます。<br />
+
 
_tcslen関数はwcslen関数と同じです。<br />
+
C++標準関数の文字列操作系の関数を使わないようにするのが、自分は良いと思います。自分のパソコンの環境だけで、ちょっとしたことのために、マクロ定義するような手法は嫌いです。何をやってるのかが分からなくなっていきやすいような気がします。長い置き換えが必要な部分だけをプログラムにするようにしています。<br />
このようにマルチバイト文字列版、ワイド文字列版、プロジェクト設定に従うTCHAR版の3つの関数があります。<br />
+
cout関数にはTCHAR版が無いようなので、最初からstd::wcoutと記述するか、<br />
+
wcout関数と_tcout関数が同じになるように定義する必要があります。実用的にはあまり使わない関数なので、あってもなくても困りません。<br />
+
C++標準関数の文字列操作系の関数を使わないようにするのが、自分は良いと思います。<br />
+
自分のパソコンの環境だけで、ちょっとしたことのために、マクロ定義するような手法は嫌いです。何をやってるのかが分からなくなっていきやすいような気がします。<br />
+
長い置き換えが必要な部分だけをプログラムにするようにしています。<br />
+
 
<br />
 
<br />
 
従って、TCHAR版のプログラムは以下のようになります。<br />
 
従って、TCHAR版のプログラムは以下のようになります。<br />
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
114行: 107行:
 
     _tprintf(_T("cStr0=%s sizeof=%d StrCount=%d"), cStr0,sizeof(cStr0),_tcslen(cStr0));
 
     _tprintf(_T("cStr0=%s sizeof=%d StrCount=%d"), cStr0,sizeof(cStr0),_tcslen(cStr0));
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
出力結果は
 
出力結果は
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
cStr0=表示:よねウィキの機能<yonewiki> sizeof=44 StrCount=21
 
cStr0=表示:よねウィキの機能<yonewiki> sizeof=44 StrCount=21
</syntaxhighlight>
+
</syntaxhighlight2>
 
となります。
 
となります。
TCHAR型のユニコード(UTF-16)設定にした場合、wchar_t型のcStr0は配列番号0~21の22の大きさを持つ配列になります。<br />
+
TCHAR型のユニコード(UTF-16)設定にした場合、wchar_t型のcStr0は配列番号0~21の22の大きさを持つ配列になります。Unicode文字セットですのでShft_JISとは異なる数値が使われますが、0番から順に<br />
Unicode文字セットですのでShft_JISとは異なる数値が使われますが、0番から順に<br />
+
 
 
0x8868(表),0x793A(示),0xFF1A(:),0x3088(よ),0x306D(ね),0x30A6(ウ),0x30A3(ィ),0x30AD(キ),0x306E(の),0x6A5F(機),0x80FD(能)<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 />
 
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 />
+
のように格納されています。あんまり変わり映えしませんが、プロジェクトの設定に従うという意味ではTCHAR型を使うのが少しお勧めです。気を付けなければならないのは、Shift_JIS(CP932)コード文字セットで格納された配列をユニコード文字セットのプロジェクトで受け取ったり、その逆のことが起こったりする場合には変換が必要になったりと、いいことばかりではありません。この他、文字コードにはShift_JIS(CP932)ではないShift_JISやEUCやMac日本語といった文字コードもあり、可能性だけで考えると
気を付けなければならないのは、Shift_JIS(CP932)コード文字セットで格納された配列をユニコード文字セットのプロジェクトで受け取ったり、<br />
+
 
その逆のことが起こったりする場合には変換が必要になったりと、いいことばかりではありません。<br />
+
 
この他、文字コードにはShift_JIS(CP932)ではないShift_JISやEUCやMac日本語といった文字コードもあり、可能性だけで考えると<br />
+
 
Unicode:UTF-8/UTF-16/UTF-32<br />
 
Unicode:UTF-8/UTF-16/UTF-32<br />
 
Shift_JIS:CP932/shift_jis/shift_jis2000/shift_jis2004<br />
 
Shift_JIS:CP932/shift_jis/shift_jis2000/shift_jis2004<br />
135行: 127行:
 
JIS:CP50220/ISO-2022-JP/ISO-2022-JP-1/ISO-2022-JP-2004/ISO-2022-JP-3<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 />
 
JIS 1Byte:ISO-2022-JP/CP50221<br />
といった文字コードが存在し、外国語文字コードセットも含めるとかなりの数の文字コードが世界に広がっています。<br />
+
 
Unicodeも扱いがいくつかあるため、実はもう少し勉強しないといけないです。
+
 
VisualStudioでUnicodeと選択した場合は、UTF-16で扱われているということになります。<br />
+
といった文字コードが存在し、外国語文字コードセットも含めるとかなりの数の文字コードが世界に広がっています。Unicodeも扱いがいくつかあるため、実はもう少し勉強しないといけないです。VisualStudioでUnicodeと選択した場合は、UTF-16で扱われているということになります。UTF-8では英数字が1Byte、日本語は3Byteを使います。テキストエディタは、このあたりの解釈が厳密で、ファイルを保存するときにも文字コードセットと符号化方式を遵守していますし、互換性を高めているものが、多いです。複雑過ぎて、自分には作れそうもないですね。<br />
UTF-8では英数字が1Byte、日本語は3Byteを使います。<br />
+
 
テキストエディタは、このあたりの解釈が厳密で、ファイルを保存するときにも文字コードセットと符号化方式を遵守していますし、<br />
+
 
互換性を高めているものが、多いです。複雑過ぎて、自分には作れそうもないですね。<br />
+
 
<br />
+
 
WindowsのVisualStudioなどでWin32 APIを使える環境であれば、以下のような型もあります。<br />
 
WindowsのVisualStudioなどでWin32 APIを使える環境であれば、以下のような型もあります。<br />
 
LPCSTR =const CHAR * <br />  
 
LPCSTR =const CHAR * <br />  
158行: 149行:
 
であり、その略の型名が対応しているとのこと。<br />
 
であり、その略の型名が対応しているとのこと。<br />
 
PCSTR/PCWSTR/PCTSTR/PSTR/PWSTR/PTSTRと先頭にLが着かないものはWin16時代に使われたものですが、今では差がありません。<br />
 
PCSTR/PCWSTR/PCTSTR/PSTR/PWSTR/PTSTRと先頭にLが着かないものはWin16時代に使われたものですが、今では差がありません。<br />
<br />
+
 
MFC(MicrosoftFaundationClass)というMicrosoftが提供しているクラスの文字列型には<br />
+
 
文字列の操作を強化したCStringもあります。有名なので手ごわいですが、これはMFCです。<br />
+
MFC(MicrosoftFaundationClass)というMicrosoftが提供しているクラスの文字列型には文字列の操作を強化したCStringもあります。有名なので手ごわいですが、これはMFCです。MFCは無料では配られていないクラスライブラリでして、Microsoftが定義した型ってのはすごく一般的にも使われるくらい流行します。ということで、使うべき型は、WIN32 APIでもLPCTSTR/PCTSTRあるいはLPTSTR/PTSTRということになりましょうか。とはいっても、世界中にはいろんな型の文字列で操作されますので、いろいろな変換が必要になります。<br />
MFCは無料では配られていないクラスライブラリでして、Microsoftが定義した型ってのはすごく一般的にも使われるくらい流行します。<br />
+
 
ということで、使うべき型は、WIN32 APIでもLPCTSTR/PCTSTRあるいはLPTSTR/PTSTRということになりましょうか。<br />
+
 
とはいっても、世界中にはいろんな型の文字列で操作されますので、いろいろな変換が必要になります。<br />
+
ここではwchar_t型で文字列を使うために、TCHAR型を使い、ワイド文字列用の各関数wcsで始まるような関数を使います。マルチバイト文字列とした場合はchar型でマルチバイト文字列用の各関数_wbやwbで始まるような関数に置き換えられることを意味します。ってことはstrcpyという文字列コピー関数や、strcat(文字列連結)、strlen(文字列カウント)のようなstrで始まるようなC標準ライブラリ関数は使われないことになります
<br />
+
 
ここではwchar_t型で文字列を使うために、TCHAR型を使い、ワイド文字列用の各関数wcsで始まるような関数を使います。<br />
+
 
マルチバイト文字列とした場合はchar型でマルチバイト文字列用の各関数_wbやwbで始まるような関数に置き換えられることを意味します。<br />
+
最近は文字列操作関数にxxx_sやxxx_lのようなセキュア思想(本当に安全なのかどうかは不明?使い方よっては間違いだらけのプログラムになる可能性もある)の文字列操作関数がありまして、大雑把に分類すると文字列操作の関数は上記のようなことから、以下のような文字列操作関数に分類できます。<br />
ってことはstrcpyという文字列コピー関数や、strcat(文字列連結)、strlen(文字列カウント)のようなstrで始まるような<br />
+
C標準ライブラリ関数は使われないことになります。<br />
+
<br />
+
最近は文字列操作関数にxxx_sやxxx_lのようなセキュア思想(本当に安全なのかどうかは不明?使い方よっては間違いだらけのプログラムになる可能性もある)の文字列操作関数がありまして、<br />
+
大雑把に分類すると文字列操作の関数は上記のようなことから、以下のような文字列操作関数に分類できます。<br />
+
 
*strxxx系関数<br />
 
*strxxx系関数<br />
 
*マルチバイト文字_mbxxxx関数/mbxxxx関数<br />
 
*マルチバイト文字_mbxxxx関数/mbxxxx関数<br />
189行: 175行:
 
LPCSTR/LPCWSTR/LPCTSTR/LPSTR/LPWSTR/LPTSTR/PCSTR/PCWSTR/PCTSTR/PSTR/PWSTR/PTSTR/<br />
 
LPCSTR/LPCWSTR/LPCTSTR/LPSTR/LPWSTR/LPTSTR/PCSTR/PCWSTR/PCTSTR/PSTR/PWSTR/PTSTR/<br />
 
という型…<br />
 
という型…<br />
どれか一つに決めて使うのは自分次第ですが、世界中のプログラマがどれを使うかは、わかりません。<br />
+
 
しかもどの関数も微妙に動作が違ったりするので、完全な理解をしようとすると、途方に暮れそうになります。<br />
+
 
でも、まぁそれだけの種類があるんだなぁとわかってさえいれば、その都度、変換方法を調べるということができるので、それでいいのかなぁと思ったりもします。<br />
+
どれか一つに決めて使うのは自分次第ですが、世界中のプログラマがどれを使うかは、わかりません。しかもどの関数も微妙に動作が違ったりするので、完全な理解をしようとすると、途方に暮れそうになります。でも、まぁそれだけの種類があるんだなぁとわかってさえいれば、その都度、変換方法を調べるということができるので、それでいいのかなぁと思ったりもします。で、文字コードセット変換…リトルエンディアン…ビッグエンディアン…文字コードセットの符号化方式UTF-8/UTF-16/UTF-32その他…もうね。なんか崩壊してるような気もするけど、やるしかないわなorz<br />
で、文字コードセット変換…リトルエンディアン…ビッグエンディアン…文字コードセットの符号化方式UTF-8/UTF-16/UTF-32その他…<br />
+
 
もうね。なんか崩壊してるような気もするけど、やるしかないわなorz<br />
+
 
学校で教えてくれるプログラミングがいかにその一部分だけを勉強していたのかを思い知らされる現実。<br />
+
学校で教えてくれるプログラミングがいかにその一部分だけを勉強していたのかを思い知らされる現実。そして、これを覚えたところでWindowsプログラミングができるわけでもないという、目指すべき頂上の遠さ。全部を理解しようなんて思わないことですね。必要最低限の装備でどこまで登れるか?登山はあんまりやったことがないのでアレなんすけど<br />
そして、これを覚えたところでWindowsプログラミングができるわけでもないという、目指すべき頂上の遠さ。<br />
+
 
全部を理解しようなんて思わないことですね。必要最低限の装備でどこまで登れるか?登山はあんまりやったことがないのでアレなんすけど<br />
+
 
<br />
+
そんな軽装備で山登りなんて始めたら、間違いなく死ににいくようなもんです。それでも目指すべきところがあるのならば、頑張るしかないっすね。自分自身はMFCを使ったアプリも複雑過ぎて理解しきれなかったし、ある程度は理解しようとしたんですけど…。C++を理解して、MFCのちょいかじり、さらにその先にあるC++/CLI、DirectShowを使ってみたりもしましたが、いやはや。どこまで理解できたのやら(汗。Win32APIだけでUSBラジオを操作したり、音を出力する質素なアプリとか、そういうのを作るのが精一杯でしたね。あと面白いのはSteinBerg社の提供しているVSTiスケルトンから音楽やMIDI処理系のDLL開発をするのも楽しかったような。
そんな軽装備で山登りなんて始めたら、<br />
+
間違いなく死ににいくようなもんです。それでも目指すべきところがあるのならば、頑張るしかないっすね。<br />
+
自分自身はMFCを使ったアプリも複雑過ぎて理解しきれなかったし、ある程度は理解しようとしたんですけど…。<br />
+
C++を理解して、MFCのちょいかじり、さらにその先にあるC++/CLI、DirectShowを使ってみたりもしましたが、いやはや。<br />
+
どこまで理解できたのやら(汗。Win32APIだけでUSBラジオを操作したり、音を出力する質素なアプリとか、そういうのを作るのが精一杯でしたね。<br />
+
あと面白いのはSterinBerg社の提供しているVSTiスケルトンから音楽やMIDI処理系のDLL開発をするのも楽しかったような。<br />
+
 
自分もわからなかったことを、もう一度、理解してみようと思います。<br />
 
自分もわからなかったことを、もう一度、理解してみようと思います。<br />
  
 
== '''マルチバイト文字列、ワイド文字列の相互変換''' ==
 
== '''マルチバイト文字列、ワイド文字列の相互変換''' ==
 
まずは、文字列の配列で以下のように格納されているものがあって、<br />
 
まずは、文字列の配列で以下のように格納されているものがあって、<br />
 +
 
TCHAR *cStr0[]={_T("表示:よねウィキの機能<yonewiki>"),_T("表示:よねウィキの機能1<yonewiki>"),_T("表示:よねウィキの機能2<yonewiki>")};<br />
 
TCHAR *cStr0[]={_T("表示:よねウィキの機能<yonewiki>"),_T("表示:よねウィキの機能1<yonewiki>"),_T("表示:よねウィキの機能2<yonewiki>")};<br />
を単純にpcStr0というポインタ変数を使って、まるまるコピーする場合はこんな風に自分ならやります。<br />
+
 
動的メモリを確保してもらいますが、それで効率が本当にいいのか悪いのかは知りません。なんとなくやりきった感じだけはします。<br />
+
 
<syntaxhighlight lang="cpp" line start="1">
+
を単純にpcStr0というポインタ変数を使って、まるまるコピーする場合はこんな風に自分ならやります。動的にメモリを確保してもらいますが、それで効率が本当にいいのか悪いのかは知りません。なんとなくやりきった感じだけはします。<br />
 +
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
235行: 217行:
 
return 0;
 
return 0;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
本当は12行目のコピーをする関数である_tcscpy_s関数は語尾の_sの無い関数を使いたいところですが、warningが表示されるので、あえて使いこなします。<br />
+
本当は12行目のコピーをする関数である_tcscpy_s関数は語尾の_sの無い関数を使いたいところですが、warningが表示されるので、あえて使いこなします。_tcscpy_sの第一引数はコピー先のTCHAR型先頭アドレスでコピーするのに必要な配列の大きさを持っていれば良いです。第二引数では、コピー先の配列の大きさを指定しています。第三引数はコピー元のTCHAR型の先頭アドレスです。<br />
_tcscpy_sの第一引数はコピー先のTCHAR型先頭アドレスでコピーするのに必要な配列の大きさを持っていれば良いです。第二引数では、コピー先の配列の大きさを指定しています。<br />
+
 
第三引数はコピー元のTCHAR型の先頭アドレスです。<br />
+
 
<br />
+
 
7行目のNew演算子では、TCHAR型のポインタのポインタ型の配列大きさを3を確保して、実体化しています。<br />
+
7行目のNew演算子では、TCHAR型のポインタのポインタ型の配列大きさを3を確保して、実体化しています。アドレスを保持できる4Byteの大きさの領域が配列番号0~3まで作られたことになります。10行目のNew演算子では、cStr[0]~[2]の文字列の文字数+1の大きさの配列をTCHAR型で確保します。ワイド文字列のwchar_t型でも21文字+1、22文字+1、22文字+1と順番に確保しますし、マルチバイト文字ならchar型ですので、すべて全角文字に対しては2byte、2文字分の領域が必要だと計算し、32文字+1、33文字+1、33文字+1を確保します。何故+1文字分を確保するかと言えば、文字列の最後には\0を格納してくれるので、その分をあけておかなければなりません。<br />
アドレスを保持できる4Byteの大きさの領域が配列番号0~3まで作られたことになります。<br />
+
 
10行目のNew演算子では、cStr[0]~[2]の文字列の文字数+1の大きさの配列をTCHAR型で確保します。<br />
+
 
ワイド文字列のwchar_t型でも21文字+1、22文字+1、22文字+1と順番に確保しますし、<br />
+
18行目、20行目では、delete演算子で動的生成した領域の放棄を宣言して、リソースを返却します。使い終わったら速やかに、返す。<br />
マルチバイト文字ならchar型ですので、すべて全角文字に対しては2byte、2文字分の領域が必要だと計算し、<br />
+
32文字+1、33文字+1、33文字+1を確保します。何故+1文字分を確保するかと言えば、文字列の最後には\0を格納してくれるので、<br />
+
その分をあけておかなければなりません。<br />
+
18行目、20行目では、delete演算子で動的生成した領域の放棄を宣言して、リソースを返却します。<br />
+
使い終わったら速やかに、返す。<br />
+
 
出力結果はマルチバイト文字設定だと<br />
 
出力結果はマルチバイト文字設定だと<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
cStr0=表示:よねウィキの機能<yonewiki> sizeof=3 StrCount=32
 
cStr0=表示:よねウィキの機能<yonewiki> sizeof=3 StrCount=32
 
cStr0=表示:よねウィキの機能<yonewiki>
 
cStr0=表示:よねウィキの機能<yonewiki>
271行: 248行:
 
pcStr0=表示:よねウィキの機能2<yonewiki>
 
pcStr0=表示:よねウィキの機能2<yonewiki>
 
  cStr0=表示:よねウィキの機能2<yonewiki>
 
  cStr0=表示:よねウィキの機能2<yonewiki>
</syntaxhighlight>
+
</syntaxhighlight2>
 
となります。<br />
 
となります。<br />
 
ワイド文字列設定なら<br />
 
ワイド文字列設定なら<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
cStr0=表示:よねウィキの機能<yonewiki> sizeof=3 StrCount=21
 
cStr0=表示:よねウィキの機能<yonewiki> sizeof=3 StrCount=21
 
sizecStr0=0,cStr0=表示:よねウィキの機能<yonewiki>
 
sizecStr0=0,cStr0=表示:よねウィキの機能<yonewiki>
295行: 272行:
 
pcStr0=表示:よねウィキの機能2<yonewiki>
 
pcStr0=表示:よねウィキの機能2<yonewiki>
 
  cStr0=表示:よねウィキの機能2<yonewiki>
 
  cStr0=表示:よねウィキの機能2<yonewiki>
</syntaxhighlight>
+
</syntaxhighlight2>
となります。Visual C++をつかわれているのであれば、プロジェクトの設定をマルチバイトにしたり、Unicodeにしてみたりして下さい。<br />
+
となります。Visual C++をつかわれているのであれば、プロジェクトの設定をマルチバイトにしたり、Unicodeにしてみたりして下さい。TCHAR型で記述しているので、どちらでも動作すると思います。<br />
TCHAR型で記述しているので、どちらでも動作すると思います。<br />
+
 
<br />
+
 
それで、なんでしたっけ、ワイド文字列とマルチバイト文字列の相互互換なんですけど、<br />
+
それで、なんでしたっけ、ワイド文字列とマルチバイト文字列の相互互換なんですけど、ようするにこのコピーをするときにワイド文字列とマルチバイトが混じっているケースで考えて、どのように対処すればいいのかで、
ようするにこのコピーをするときにワイド文字列とマルチバイトが混じっているケースで考えて、どのように対処すればいいのかで、<br />
+
説明ができると思ったのでした。mbstowcs関数とwcstombs関数でやりとりが出来るようになっています。実際、こんなケースがあるのかは知りませんが、こんな関数があるってことは、テキストをどこからか読み込んだ場合とか、そういったプログラムから引数として受け取るとか、そういったケースもあるのでしょう。関数の引数はそれぞれ異なるので、気を付けなければなりません。<br />
説明ができると思ったのでした。<br />
+
 
mbstowcs関数とwcstombs関数でやりとりが出来るようになっています。<br />
+
 
実際、こんなケースがあるのかは知りませんが、こんな関数があるってことは、テキストをどこからか読み込んだ場合とか、<br />
+
で、無理矢理にそういったサンプルのプログラムを作るのは意外と面倒でして、サンプルは鋭意執筆中ということにしておきたいと思います。ぉぃ。っていうか、MSDNライブラリが落っこちてるみたいで、厳密な解釈を調べながら書くことができない。mbstowcs関数にも_tbstowcsとかmbstowcs_sとかmbstowcs_s_lとかあると思うんですけど、その辺りを知ることが出来ない。その逆もしかり。<br />
そういったプログラムから引数として受け取るとか、そういったケースもあるのでしょう。<br />
+
 
関数の引数はそれぞれ異なるので、気を付けなければなりません。<br />
+
 
<br />
+
ようはchar型に収められた文字列をwchar_t型に変換したり、wchar_t型で収められた文字列をchar型に変換したりするってことなんですけど。UnicodeとShift_JISの変換もここで知っておくべきか…。つうか、この記事、長すぎっ。誰も理解できないんじゃね?って思う今日この頃。<br />
で、無理矢理にそういったサンプルのプログラムを作るのは意外と面倒でして、サンプルは鋭意執筆中ということにしておきたいと思います。ぉぃ。<br />
+
 
っていうか、MSDNライブラリが落っこちてるみたいで、厳密な解釈を調べながら書くことができない。<br />
+
 
mbstowcs関数にも_tbstowcsとかmbstowcs_sとかmbstowcs_s_lとかあると思うんですけど、その辺りを知ることが出来ない。その逆もしかり。<br />
+
<br />
+
ようはchar型に収められた文字列をwchar_t型に変換したり、wchar_t型で収められた文字列をchar型に変換したりするってことなんですけど。<br />
+
UnicodeとShift_JISの変換もここで知っておくべきか…。<br />
+
つうか、この記事、長すぎっ。誰も理解できないんじゃね?って思う今日この頃。<br />
+
<br />
+
 
とかいいつつ、サンプルプログラムを作りました。<br />
 
とかいいつつ、サンプルプログラムを作りました。<br />
 
mbstowcs関数とwcstombs関数はやはり、mbstowcs_s関数とwcstombs_s関数があって更には、<br />
 
mbstowcs関数とwcstombs関数はやはり、mbstowcs_s関数とwcstombs_s関数があって更には、<br />
323行: 294行:
 
http://msdn.microsoft.com/ja-jp/library/vstudio/s7wzt4be(v=vs.110).aspx<br />
 
http://msdn.microsoft.com/ja-jp/library/vstudio/s7wzt4be(v=vs.110).aspx<br />
 
サンプルプログラムは以下のとおりです。<br />
 
サンプルプログラムは以下のとおりです。<br />
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
397行: 368行:
 
return 0;
 
return 0;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
前半部分にマルチバイト文字→ワイド文字変換<br />
 
前半部分にマルチバイト文字→ワイド文字変換<br />
 
後半部分にワイド文字→マルチバイト文字変換<br />
 
後半部分にワイド文字→マルチバイト文字変換<br />
 
の処理を記述しました。<br />
 
の処理を記述しました。<br />
 
mbstowcs_s(sizeReturnValue, NULL, 0,cStr1[i], 0);<br />
 
mbstowcs_s(sizeReturnValue, NULL, 0,cStr1[i], 0);<br />
のように第二引数には本来、変換後の文字列の先頭アドレスを記述しますが、NULLと指定して、<br />
+
のように第二引数には本来、変換後の文字列の先頭アドレスを記述しますが、NULLと指定して、第三引数の変換後の配列要素数も0にして、第四引数に変換元の文字列の先頭アドレスを記述し、変換する要素数も0を指定するとsize_t型のポインタ変数sizeReturnValueに変換に必要な配列サイズが返ってきます。その返却された値を
第三引数の変換後の配列要素数も0にして、第四引数に変換元の文字列の先頭アドレスを記述し、変換する要素数も0を指定すると<br />
+
 
size_t型のポインタ変数sizeReturnValueに変換に必要な配列サイズが返ってきます。<br />
+
 
その返却された値を<br />
+
requiredSize = *sizeReturnValue;のようにしてコピーしておいて、
requiredSize = *sizeReturnValue;のようにしてコピーしておいて、<br />
+
 
 +
 
 
mbstowcs_s(sizeReturnValue, pcStr2[i], requiredSize, cStr1[i], requiredSize);<br />
 
mbstowcs_s(sizeReturnValue, pcStr2[i], requiredSize, cStr1[i], requiredSize);<br />
 +
 +
 
とすることで変換がされます。<br />
 
とすることで変換がされます。<br />
 
逆のwcstombs_sも同様です。やったことないようなプログラムでしたので、たまには、こうして確かめてみるのも良いですね。<br />
 
逆のwcstombs_sも同様です。やったことないようなプログラムでしたので、たまには、こうして確かめてみるのも良いですね。<br />
 
<br />
 
<br />
ちょっと出力結果に冗長さを設定したサンプルプログラムなので、<br />
+
ちょっと出力結果に冗長さを設定したサンプルプログラムなので、以下のように出力が長くなりましたが、全部貼っておきます。<br />
以下のように出力が長くなりましたが、全部貼っておきます。<br />
+
<syntaxhighlight2 lang="cpp">
<syntaxhighlight lang="cpp">
+
 
マルチバイト文字→ワイド文字変換
 
マルチバイト文字→ワイド文字変換
  
636行: 609行:
 
pcStr0=表示:よねウィキの機能2<yonewiki>
 
pcStr0=表示:よねウィキの機能2<yonewiki>
 
  cStr1=表示:よねウィキの機能2<yonewiki>
 
  cStr1=表示:よねウィキの機能2<yonewiki>
</syntaxhighlight>
+
</syntaxhighlight2>
 
ってな感じになります。マルチバイト文字に変換することでShift_JIS cp932になっていることもわかったかと思います。<br />
 
ってな感じになります。マルチバイト文字に変換することでShift_JIS cp932になっていることもわかったかと思います。<br />
 
人に見せるのに、出力部分の適当さ加減はすごいね。でも、これって内部的な努力は凄いけど、外部から見れば何も変化を感じないので、<br />
 
人に見せるのに、出力部分の適当さ加減はすごいね。でも、これって内部的な努力は凄いけど、外部から見れば何も変化を感じないので、<br />
 
さみしいね。次は文字列の操作の記事でも書きます。<br />
 
さみしいね。次は文字列の操作の記事でも書きます。<br />
 
<br />
 
<br />
[[C PlusPlus|C++]]へ戻る
+
 
 +
 
 +
[[C PlusPlus#Cにもあった技術|C++]]へ戻る

2020年9月11日 (金) 00:00時点における最新版



個人用ツール
名前空間

変種
操作
案内
ツールボックス