• ベストアンサー

3バイト文字(UTF-8)をprintfで等幅表示をするには?

64BIT環境のLINUX、gcc で開発をしております。 表題の件ですが、UTF-8 は3バイト文字が多いため、strlenの戻り値と、printf で表示したときの画面上の桁数が一致しません。 そのため、下記のようなプログラムを実行すると >> int main() { char* s = "あいうえお"; printf("%20s\n", s); return 0; } ... あいうえお << と、画面上で15桁で表示されます。 つまり、文字列中のUTF-8の文字数分、表示幅がフィールド幅より短くなるわけです。 現状、文字列中の UTF-8文字の数を数える関数を作成し、以下のように対処しております。 >> int strUTF8Count(const char* s) { int notAsciiCount = 0; while(*s++) { if (!isascii(*s)) ++notAsciiCount; } return notAsciiCount / 3; } int main() { char* s = "あいうえお"; printf("%*s\n", 20 + strUTF8Count(s), s); return 0; } << これで、現状動いておりますが、strUTF8Count関数の作りが雑で、ascii でなければ UTF-8 と仮定しているし、UTF-8 であれば、3バイト文字と仮定してしまっています。 printf もかなりみづらいですし、何かもっとスマートな方法はないものでしょうか? UTF-8 の扱いとしては一般的なものと思われますが、ネット上を検索しても有効な対処が見つかりませんでした。 どなたかよい知恵をお持ちの方がいらっしゃいましたら、知恵を分けてくれるようお願いします。

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

UTF8 での, 各文字のバイト数の数え方: 0xxx xxxx の 8ビットなら 1バイト (ASCII と同じ値) 110x xxxx というバイトなら, 次は 10yy yyyy というバイトがあるはずで, この文字は 2バイト. UCS-4 としての値は xxxxx yyyyyy の 11ビット. 1110 xxxx というバイトならそのあとに 10yy yyyy 10zz zzzz というバイトがあって, 全体で 3バイト. UCS-4 としての値は xxxx yyyyyy zzzzzz の 20ビット. Unicode としてはここまで. このようにして, 各文字のバイト数を調べながらポインタを進めれば何文字かがわかりますが, 表示する桁数としては実はわからなかったりします. surrogated pair とか combination mark とかがあると, 「表示する桁数」は表示するデバイスに依存しそう.

DOSKOI-PANDA
質問者

お礼

ありがとうございます。 等幅表示するには wprintfを使うしかなさそうですねぇ。(しかし何故か表示されない……)

その他の回答 (3)

回答No.4

もしや wprintf() で wchat_t * を引数にしても何も出ないということで悩んでます? もしそうならフォーマットを %s じゃなくて %ls でやってみましょう。(printf() でも同じことですが)

回答No.3

固定サイズフォントでの表示カラム数を調べたいなら wcswidth() を使えばいいのでは?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ロケールが適切に設定されてれば mbtowc と wprintf. そうでなければ UTF8 の「文字数」を数える. 最初のバイトを見れば, 「その文字が何バイトか」はわかる... んだけど, surrogated pair はどうします?

DOSKOI-PANDA
質問者

補足

>> setlocale(LC_CTYPE, ""); printf("CODESET is UTF-8? = %d\n", strcmp(nl_langinfo(CODESET), "UTF-8") == 0); char* s = "あいうえお"; wchar_t wcs[BUFSIZ]; mbtowcs(wcs, s, BUFSIZ); wprintf(L"%s\n", wcs); << でやってみましたが、表示されませんでした。 「文字数」の数え方ですが、UTF-8とASCIIが混ざって入っている文字列中から、UTF-8文字の最初のバイトのバイトはどのように探したらよいかわかりません。 また http://ash.jp/code/unitbl21.htm とかを見ても、1バイト目の値は文字により様々で、どのような値が文字数になるのか、法則はあるのでしょうか? ここで言う「文字数」とは、そのUTF-8がデータ上何バイト使用しているかという意味ですか? それとも、画面に出力したときの桁数でしょうか?