忍者ブログ

マインのブログ

マインが何かを気まぐれに書く日記です。

[PR]

カテゴリー:

2024/04/27(Sat)10:44

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

No.|CommentTrackback

ワイド文字とかめんどい

カテゴリー:プログラムとか

2007/04/18(Wed)23:07

えー、今日はデータベースの授業でした。
が、何でしょうね、あのハンドアウト。
スライドの順番がおかしい。
ちょっと早めに学校に着いたのでそれをがんばってやろうと思ってましたが、無理でした。
もうちょっと調べないとなー。
てか、元のデータをくれ。
そしたら俺がやってやるよ!
それにあれ分かりにくいしなー。
明日は演習だが、大丈夫だろうか??

と、授業の愚痴はこの辺にして昨日言ってたワイド文字を使ったプログラムに関して。
まあ、ここに書いてあるとおりにしても動かないなんてことはよくあることなので、それは気にしない方向で。
ちなみにVC6.0かVC2005のコンソールです。

まず、ワイド文字の型ですが、wchar_tというのを使います。
stdio.hに入ってるはずですが、もしあれならwchar.hをインクルードしちゃってください。
あとはcharと同じように使えます。
つまりワイド文字列なら
wchar_t *wstr;
みたいになるわけです。
しかし、これを実際に使うとなるとマルチバイト文字列で使ったようにstrlenとかstrcmpとかが使えません。
よく使う物の対応を書いておきます。
strlen -> wcslen
strcmp -> wcscmp
strcpy -> wcscpy
atoi -> _wtoi
まあ、見て分かるとおり、strが付くものはstrをwcsにすれば大丈夫です。
もちろん、マルチバイト文字列と同じでstring.hをインクルードしないとダメですけどね。
atoiだけが違いますね。
見難いとは思いますが、(アンダーバー)wtoiです。

では、ちょっとしたサンプルを。

-----ここからソース-------
#include <stdio.h>
#include <string.h>

int main()
{
      wchar_t  *wstr = L"テスト";
      wchar_t  wstr2[20];
      wchar_t  *wstr3 = L"test";

      wcscpy(wstr2, wstr);
      // VC2005を使いwarningを消したければ
      // wcscpy_s(wstr2, 20, wstr);

      wprintf(L"%s\n", wstr);
      wprintf(L"%s\n", wstr2);
      wprintf(L"%s\n", wstr3);

      return 0;
}
------ソースここまで----------
""で囲った文字列をワイド文字列として扱う場合はL""とします。
小数を明示的にfloatであるとするときの1.0fと似たようなものと覚えてもらえればいいかと。
ワイド文字列を出力するときはwprintf(const wchar_t *Format, ...)を使います。
これも引数がwchar_t*なので
wprintf(L"...", ...);
というようにします。
さて、結果は
-----output-----
テスト
テスト
test
-----to here----
となればいいのですが、実際は
-----output-----
???
???
test
-----to here----
となってしまいます。
これはワイド文字の日本語が日本語として認識されてないことが原因らしいです。

これを解決するためにはlocale.hをインクルードし、main()の最初に
setlocale(LC_ALL, "");
を入れるとちゃんと日本語が表示されるようになります。
この命令の意味ですが、
「これ以降に出てくる関数で扱う言語をPC環境の標準言語(日本語)にする」
というような意味だったかと。
よく覚えてません。
まあ、この辺は調べればすぐ出てくるかと。

さて、ゲームを作る上でワイド文字を使うときは外部から読み込むことのほうが多いと思います。
マルチバイト文字であればgetcやscanf(あまり使わないかな?)を使うと思います。
これらもワイド文字用の関数があります。
getc -> getwc
scanf -> wscanf
sprintf -> swprintf
wscanfやswprintfはwprintfのように引数としてwchar_t*を使うのでLを忘れないようにしましょう。

では、またサンプルを。
読み込みに使う外部データは
-------- test.txt ------
テスト
てすと
test
--------to here------
とします。
これを1文字ずつ読み込んでそれを出力するというプログラムを作ります。
まあ、これを見てる人の大半はwhileを使ってEOFまでループさせて
getwcで読み込んだ文字をwprintfで出力すればいいとすぐに分かると思いますが、
それだけではうまくいきません。
それはなぜか?
実際に自分でプログラムを組んでみてから下のサンプルを見てください。
違いがすぐに分かると思います。
-----------ここからソース----------
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main()
{
      setlocale(LC_ALL, "");

      FILE *file;
      file = _wfopen(L"test.txt", L"r");
      // VC2005を使っていてwarningを出したくなければ
      // _wfopen_s(&file, L"test.txt", L"r");

      // ファイルオープンに失敗
      if (file == NULL) exit(10);

      wchar_t ch;
      while ( (ch = getwc(file)) != WEOF) wprintf(L"%c", ch);

      fclose(file);

      return 0;
}
---------ソースここまで--------------
この出力は
-----output-------
テスト
てすと
test
-----to here-------
となります。
ちょっと説明するとテキストをワイド文字として読み取る場合には_wfopenを使い、
これから読み上げる文字はワイド文字であるということを明確にする必要があります。
またワイド文字のEOFはWEOFです。
間違えると無限ループになったりとひどいことになると思います。

さてさて、大分長くなってきましたが、もう1ステップ行ってみますか。
今度はSTLのstringです。
これはマルチバイト文字列ですが、ワイド文字のストリングはどうすればいいのか?
自分で作ってください、なんてことはひどいことはさすがに言われません。
ちゃんとwstringというワイド文字列型が用意されています。
これはSTLのstringと同様に
#include <string>

using namespace std;
を適所に入れれば使えます。
あとはlength()やc_str()などstringと同じように使えます。
もちろん出力にはwprintfや文字加算はwchar_tを使いますが。

まあ、こういうわけで、ワイド文字を扱うのはかなり大変です。
ああ、なんか間違えがあっても気にしないでくださいね。
プログラムをやってる人なら自分で直せるはずです。
勝手に直すなり俺に文句を言うなりしてください。
てか、なげーな、この記事。
ここまで読んだ方、本当にお疲れ様でした。
ちなみにここに書いたことは少し調べればゴロゴロ出てきます。
そっちのほうが詳しくていいかも。
さて、今日の終わりにバグが出てしまったからちょっとやるかな。
明日が1限だから夜更かしできないのがイヤだな。

拍手[0回]

PR

No.930|Comment(0)Trackback()

Comment

Comment Write
Name
Title
Mail
URL

Pass Vodafone絵文字 i-mode絵文字 Ezweb絵文字 

Trackback

URL :