• ベストアンサー

ユニコード文字の変換について

文字列が書かれたテキストファイルを読み込み、ユニコード部分だけを変換して画面に表示するプログラムを作りたいと思っています。 つまり、 \u305d\u306eaiueo と書かれたテキストファイルがあれば そのaiueo(←『\u305d』は『そ』、『\u306e』は『の』なので) と表示するプログラムを作りたいのですが、fgetsで読み込みprintfで表示するだけではそのまま「\u305d\u306eaiueo」となってしまい困っています。 \を文字(\\)として読み込んでるからだろうとは思うのですが… また、 char a[]="\u305d\u306eaiueo"; と定義した文字列を printf("%s",a); とすると「そのaiueo」と表示されますが、何故こちらは表示されて、前述の方法では表示されないのかも理解できていません。 どのような考え方、方法であれば解決するのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

>wchar_tやmbstowcs関数を使用して『\u305d』→『そ』が表現できるということなのでしょうか? mbstowcsは使いません。wchar_tは使います。 要するに、『\u305d』を自前で『そ』に変換するんです。 例えば、char *pに\のアドレスが入っているとすると、 if( *p == '\\' && *(p+1) == 'u' ){   p+=2; wchar_t wc=strtoul(p,&p,0); : : } とか、そうやって地味に変換するということです。

popokoku
質問者

お礼

諸事情で返答が遅れてしまいました、申し訳ありません。 strtoul()なんていう変換関数があったんですね、今回初めて知りました。 wchar_t wc=strtoul(p,&p,0); だと、「305d」の「d」が変換不可能な文字とみなされてしまったので、基数の0を16として wchar_t wc=strtoul(p,&p,16); setlocale(LC_ALL, ""); printf("%wc",wc); とした所、ちゃんと「そ」と画面に表示することができました。 お陰様で引っかかっていたものがスッキリしました。ありがとうございます!

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

Visual C++では、国際文字名に相当する部分をいったんwchar_t型に格納してから多バイト文字に変換するのがよいでしょう。その際、ロケールを適切に設定してください。 なお、\u1234の形式であれば簡単ですが、\U00123456の形式の場合には、サロゲートペアに置き換えるなどしなければなりません。

popokoku
質問者

お礼

諸事情で返答が遅れてしまいました、申し訳ありません。 \u305dとは異なる形式もあるんですね。「サロゲートペア??」な状態だったので少し調べてみました。 「文字コードは5文字だけどデータは4バイト」 これにも対応するとなるとまた一手間かかりそうですね… 私はほとんど趣味の領域でプログラムを組んでるので対応しなくても全然問題ないですが、 開発者の方達はこういった環境のことも配慮しなくてはいけないとなると大変ですね。

すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

処理系に依存しない一般的な実現方法は、Unicodeの全ての文字に対応した表を作る方法だけです。 > char a[]="\u305d\u306eaiueo"; は国際文字名ですので、\nや??=などと同じで、コンパイル時に実行文字集合に変換されます。

popokoku
質問者

お礼

回答ありがとうございます。 >処理系に依存しない一般的な実現方法は、Unicodeの全ての文字に対応した表を作る方法だけです 処理系に依存しないことを考えるとなるとそこまでしないといけないとは… 全ての文字の対応表を作るとしたら本筋とは違う部分に力を注ぐことになりそうなので、今回は避けようと思います。

すると、全ての回答が全文表示されます。
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

\の処理はコンパイラがよろしくやってくれる処理です。 コンパイラはソースコードにかかれている文字列については処理してくれますが、さすがにテキストファイルにかかれている文字列の面倒まではみてくれません。 したがって自分のプログラムで処理しなくてはなりません。 一文字ずつ読みながらワイド文字に変換するのが楽だと思います。 あと、処理系が書かれていませんね。 VC++であれはprintfで直接ワイド文字列を出力できますが、他の処理系では一工夫いるかもしれません。

popokoku
質問者

お礼

回答ありがとうございます。 処理系ですが、Visual C++ 2008 Express Editionで処理しています。 「一文字ずつ読みながらワイド文字に変換」という部分をプログラムでどう表現してよいのかが、私の頭では思いつきませんでした。 wchar_tやmbstowcs関数を使用して『\u305d』→『そ』が表現できるということなのでしょうか? (作成してるプログラムの一部でユニコードで書かれたテキストファイルを読む必要が生じたため質問したのですが、改めてプログラム全体を試行錯誤した結果、ユニコードで書かれたテキストファイルの読み込みこむ必要性が無くなりそうです。 とはいえ、この問題を宙ぶらりんにするのも気持ちが悪いので、もしよろしければお教え下さい)

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

前者は想像の通りで, プログラムで a[] = "\\u305d\\306eaiueo"; と書いたのと結果的に同じですからねぇ. 後者はコンパイラがよろしくしています. ということで, 「\u+16進4桁」の部分を実際の値にすればいいんだけど, UTF-8 にしないとダメかなぁ? 後者の方で a[0] の値がわかればなんとかなるかもしれんけど....

popokoku
質問者

お礼

回答ありがとうございます。 コンパイラの関係で出力される表現が違っていたわけですか。 これまでソースとファイルに対する扱いは同じようなものだと勝手に思っていました。

すると、全ての回答が全文表示されます。