解決済み

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

  • 暇なときにでも
  • 質問No.4196857
  • 閲覧数808
  • ありがとう数103
  • 気になる数0
  • 回答数5
  • コメント数0

お礼率 100% (14/14)

文字列が書かれたテキストファイルを読み込み、ユニコード部分だけを変換して画面に表示するプログラムを作りたいと思っています。
つまり、
\u305d\u306eaiueo
と書かれたテキストファイルがあれば
そのaiueo(←『\u305d』は『そ』、『\u306e』は『の』なので)
と表示するプログラムを作りたいのですが、fgetsで読み込みprintfで表示するだけではそのまま「\u305d\u306eaiueo」となってしまい困っています。
\を文字(\\)として読み込んでるからだろうとは思うのですが…

また、
char a[]="\u305d\u306eaiueo";
と定義した文字列を
printf("%s",a);
とすると「そのaiueo」と表示されますが、何故こちらは表示されて、前述の方法では表示されないのかも理解できていません。

どのような考え方、方法であれば解決するのでしょうか?

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

  • 回答No.5

ベストアンサー率 19% (338/1717)

>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

お礼率 100% (14/14)

諸事情で返答が遅れてしまいました、申し訳ありません。

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);
とした所、ちゃんと「そ」と画面に表示することができました。
お陰様で引っかかっていたものがスッキリしました。ありがとうございます!
投稿日時 - 2008-08-07 13:22:37

その他の回答 (全4件)

  • 回答No.4

ベストアンサー率 26% (845/3158)

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

お礼率 100% (14/14)

諸事情で返答が遅れてしまいました、申し訳ありません。

\u305dとは異なる形式もあるんですね。「サロゲートペア??」な状態だったので少し調べてみました。
「文字コードは5文字だけどデータは4バイト」
これにも対応するとなるとまた一手間かかりそうですね…
私はほとんど趣味の領域でプログラムを組んでるので対応しなくても全然問題ないですが、
開発者の方達はこういった環境のことも配慮しなくてはいけないとなると大変ですね。
投稿日時 - 2008-08-07 13:21:43
  • 回答No.3

ベストアンサー率 26% (845/3158)

処理系に依存しない一般的な実現方法は、Unicodeの全ての文字に対応した表を作る方法だけです。

> char a[]="\u305d\u306eaiueo";

は国際文字名ですので、\nや??=などと同じで、コンパイル時に実行文字集合に変換されます。
お礼コメント
popokoku

お礼率 100% (14/14)

回答ありがとうございます。

>処理系に依存しない一般的な実現方法は、Unicodeの全ての文字に対応した表を作る方法だけです
処理系に依存しないことを考えるとなるとそこまでしないといけないとは…
全ての文字の対応表を作るとしたら本筋とは違う部分に力を注ぐことになりそうなので、今回は避けようと思います。
投稿日時 - 2008-07-25 00:22:52
  • 回答No.2

ベストアンサー率 19% (338/1717)

\の処理はコンパイラがよろしくやってくれる処理です。
コンパイラはソースコードにかかれている文字列については処理してくれますが、さすがにテキストファイルにかかれている文字列の面倒まではみてくれません。

したがって自分のプログラムで処理しなくてはなりません。
一文字ずつ読みながらワイド文字に変換するのが楽だと思います。

あと、処理系が書かれていませんね。
VC++であれはprintfで直接ワイド文字列を出力できますが、他の処理系では一工夫いるかもしれません。
お礼コメント
popokoku

お礼率 100% (14/14)

回答ありがとうございます。

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

ベストアンサー率 23% (3656/15482)

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

お礼率 100% (14/14)

回答ありがとうございます。
コンパイラの関係で出力される表現が違っていたわけですか。
これまでソースとファイルに対する扱いは同じようなものだと勝手に思っていました。
投稿日時 - 2008-07-25 00:20:45
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

特集

ピックアップ

ページ先頭へ