none
CStringのFormatを使用したときの桁数をそろえたい RRS feed

  • 質問

  • CStringで文字列の整形をしようとしているのですが
    2バイト文字と半角文字を区別して(全角は2バイトで、半角は1バイトで)桁揃えをする方法は無いでしょうか

     

    strtmp.Format(_T("%-20s"),strA + _T("abd") + _T("あいう"));
    としたときに、

    “abd”も“あいう”も同様に3文字とカウントされてしまいます。
    Unicodeにしているのがまずいと思うのですが
    全角、半角を文字のサイズに合わせて整形する方法は無いでしょうか?

    2011年8月12日 1:44

回答

  • 外池と申します。

    「半角」と「全角」。これは、文字を表示したり印刷したりするときの、あるひとつの文字の幅のことですよね? 

    一方で、「2バイト文字」と「1バイト文字」、これは、あるひとつの文字を、コンピューターの内部で何バイトで表現するかのことです。

    全然違うことを、同列で議論しようとしているので、みなさん回答しかねていると思います。

    昔のことですが、日本のパソコンで「半角」=「1バイト文字」、「全角」=「2バイト文字」だったこともありますが(このころのことは私は詳しくないので自信ありません)、少なくとも今のWindowsでは、この関係は成り立ちません。「半角」「全角」の概念は、今は無いと思って良いのではないかと。「1バイト文字」「2バイト文字」の概念は文字コードの種類によっては今もあります。

    なので・・・、いちろうさんご自身で、半角とはどういう文字のこと、全角とはどういう文字のこと、これをまず定義して説明して頂く必要があるかと思います。


    (ホームページを再開しました)
    • 回答の候補に設定 山本春海 2011年8月31日 1:23
    • 回答としてマーク 山本春海 2011年9月2日 4:44
    2011年8月21日 14:30
  • 望まれているのが「メモリ上の配置」だとすると、何を持って「あいうえお」が10バイトとなるのでしょうか。JIS コード(メールで使用します)では、この範囲だけに注目すると10バイトですが、文字列として全体を見ると、おそらく12バイトになります(最初に「漢字 IN コード」、最後に「英数 IN コード」が入る)。

    本題から外れますが、メールで使用する ISO-2022-JP のことであれば、(「漢字INコード」という表現も微妙ですが、)バイト数は間違っています。ESC $ B の3バイトです。ASCIIに戻すのも ESC ( B の3バイトです。なのでこの場合は16バイトです。

    元質問でいちろうさんの求めていることも何となくはわかりますが…これについてはたぶんいったんSHIFT_JISに変換して実際のバイト数を数えるほかないように思います。

    Unicodeのまま文字の全角半角を確認するAPIなどあればいいんですが…。

    • 回答としてマーク いちろう 2011年9月10日 10:13
    2011年8月22日 21:04
  • 佐祐理さん、

    > Unicodeのまま文字の全角半角を確認するAPIなどあればいいんですが…。

    もともと、Unicodeに全角半角の概念は無いと思ったですが、、、。

    でも、日本語環境限定と想定すると、

    半角英数:  0x20 - 0x7E(UTF-8), 0x0020 - 0x007E (UTF-16)

    それ以外は、全角扱いでも良いのではないかと。

    実際の幅については、使用するフォントの文字幅を取得するAPIを一文字ずつ

    使うしかないと思います。

    // Arabic, India系で固定ピッチなんて存在するのでしょうか?

     

    • 回答としてマーク いちろう 2011年9月10日 10:13
    2011年8月30日 14:44
  • Unicode Standard Annex #11 EAST ASIAN WIDTHとして、Unicodeにおける全角半角を定めていますよ。ここにWとあるのが全角です。

    そもそも「ア」はU+FF71 HALFWIDTH KATAKANA LETTER A、つまり名前に「半角」と入ってます。

    • 回答としてマーク いちろう 2011年9月10日 10:13
    2011年8月30日 20:35

すべての返信

  • 以下の語句が何を意味しているのかがよくわからないため、質問の意図が理解できません。

    ・整形

    ・桁揃え

    ・文字のサイズ

     

    それぞれUI的なニュアンスを感じるのですが、どういう意味ですか?

    2011年8月12日 1:55
  • 等幅フォントを使ってコンソールなどに表示する際、半角の英数字や記号が、全角の文字の半分のサイズになることを前提としての質問ですか?

    そうでしたら、どのように文字列が"整形"されてほしいのか、具体例を出してもらえますか?


    2011年8月12日 2:12
  • Unicodeにしているのがまずいと思うのですが

     ここに引用されているコードを見る限り、Unicode なのか MBC なのか、わかりません。コンパイル オプションを変えれば、期待通りになるのでしょうか?


    Jitta@わんくま同盟
    2011年8月12日 13:02
  • すいません。


    使っている文字コードはUTF8です
    やりたいことは半角は1バイト、全角文字は2バイトとして長さをそろえたかったのです

    10文字分でそろえたい場合

    「あいうえお」は「あいうえお」(全て2バイト文字として長さを計算)
    「abcde」は「abcde」と「半角スペース5文字」

    としてです。

    こんな説明ででわかるでしょうか

    2011年8月21日 13:46
  • 外池と申します。

    「半角」と「全角」。これは、文字を表示したり印刷したりするときの、あるひとつの文字の幅のことですよね? 

    一方で、「2バイト文字」と「1バイト文字」、これは、あるひとつの文字を、コンピューターの内部で何バイトで表現するかのことです。

    全然違うことを、同列で議論しようとしているので、みなさん回答しかねていると思います。

    昔のことですが、日本のパソコンで「半角」=「1バイト文字」、「全角」=「2バイト文字」だったこともありますが(このころのことは私は詳しくないので自信ありません)、少なくとも今のWindowsでは、この関係は成り立ちません。「半角」「全角」の概念は、今は無いと思って良いのではないかと。「1バイト文字」「2バイト文字」の概念は文字コードの種類によっては今もあります。

    なので・・・、いちろうさんご自身で、半角とはどういう文字のこと、全角とはどういう文字のこと、これをまず定義して説明して頂く必要があるかと思います。


    (ホームページを再開しました)
    • 回答の候補に設定 山本春海 2011年8月31日 1:23
    • 回答としてマーク 山本春海 2011年9月2日 4:44
    2011年8月21日 14:30
  • プロジェクトの設定とは無関係に、該当箇所ではMBCSを使用すれば良いのではないでしょうか。
    CStringA   strtmp; // MBCS
    strtmp.Format( "%-10s", "あいう");
    strtmp.Format( "%-10s", "abc");
    ・・・そういう簡単な問題じゃぁないのかな(vv;)。

    2011年8月22日 6:17
  •  外池さんの通りですが、具体例を示します。段落の上下は、それぞれ「10バイト」のはずですが、表示される長さが異なります。


    あいうえお
    ijklmijklm

    あいうえお
    ijklmijklm

    あいうえお
    あいうえお

    ijklmijklm
    ijklmijklm

    <p style="font-family:'MS Pゴシック'">あいうえお<br>ijklmijklm</p>
    <p style="font-family:'MS ゴシック'">あいうえお<br>ijklmijklm</p>
    <p><span style="font-family:'MS Pゴシック'">あいうえお<br><span style="font-family:'MS ゴシック'">あいうえお</span></p>
    <p><span style="font-family:'MS Pゴシック'">ijklmijklm<br><span style="font-family:'MS ゴシック'">ijklmijklm</span></p>
    

     いちろうさんが望まれているのが「表示」だとすると、2番目のような表示だと思います。これは、「文字のバイト数」の他に、「文字の表示幅」が関係しています。Shift-JIS コードでは「あいうえお」も「ijklmijklm」も10バイトですが、プロポーショナル フォントで表示すると、期待する表示にはなりません。上の例では Web 用の表記をしていますが、Windows Form でも同じです。

     望まれているのが「メモリ上の配置」だとすると、何を持って「あいうえお」が10バイトとなるのでしょうか。JIS コード(メールで使用します)では、この範囲だけに注目すると10バイトですが、文字列として全体を見ると、おそらく12バイトになります(最初に「漢字 IN コード」、最後に「英数 IN コード」が入る)。Shift-JIS コードだと、10バイトです。「abcde」は、UTF-16 では10バイトですが、Unicode の一つである UTF-8 なら5バイトです。つまり、メモリ上の話だとすると、文字を表すコードを明らかにしなければなりません。

     つまり、「どの文字コードで表現する」というのを明らかにして、それに変換してやれば、望みの通りになる、ということです。とはいえ、ここに示したように、「全角半角」という表示上の幅も、文字コードによるバイト数で表した幅も、現在ではごく限られた範囲の話であり、ほとんど無意味です。他のシステムとのやりとりがあって、その I/O で規定されている等の理由以外では、バイト数で何らかの制限をするという仕様は取りやめた方が良いと思います。


    Jitta@わんくま同盟
    2011年8月22日 14:54
  • いちろうさんは、UTF-8 と書かれているので、文字コードは明らかですね。

    GUI画面での表示の問題かと思いますが、違いますか?

     (コンソール画面でプロポーショナルはまだ見た事がありませんので)

    とすると、固定ピッチのフォントを使うか、一文字毎に、固定ピッチで文字を並べるしかないのではないかと思います。

     

    余談ですが、UTF-8 の場合、漢字は2バイトとは限らず、3バイトもあるので注意ですね。

    また、Unicodeの一覧を見ると、全角(と思われる)英数字や、半角(と思われる)カナもあるようですね。

    手元に資料が無いので、コード位置をすぐには示せませんが、、、。

     

    2011年8月22日 16:02
  • 望まれているのが「メモリ上の配置」だとすると、何を持って「あいうえお」が10バイトとなるのでしょうか。JIS コード(メールで使用します)では、この範囲だけに注目すると10バイトですが、文字列として全体を見ると、おそらく12バイトになります(最初に「漢字 IN コード」、最後に「英数 IN コード」が入る)。

    本題から外れますが、メールで使用する ISO-2022-JP のことであれば、(「漢字INコード」という表現も微妙ですが、)バイト数は間違っています。ESC $ B の3バイトです。ASCIIに戻すのも ESC ( B の3バイトです。なのでこの場合は16バイトです。

    元質問でいちろうさんの求めていることも何となくはわかりますが…これについてはたぶんいったんSHIFT_JISに変換して実際のバイト数を数えるほかないように思います。

    Unicodeのまま文字の全角半角を確認するAPIなどあればいいんですが…。

    • 回答としてマーク いちろう 2011年9月10日 10:13
    2011年8月22日 21:04
  • 例で書かれているコードを見る限りでは、UTF-16のような気がするのですが、
    UTF-8で間違いないですか?
    サンプルコードで書いた内容は忘れて欲しいという話なら良いのですが。

    表示上の桁位置を合わせたいという話であれば、文字のバイト数とは直接関係無い話であるのは
    すでに皆さんが書かれている通りです。
    実際に使っている文字コードをきちんと把握されているのであれば、
    既に皆さんが書かれている内容で対応は出来そうな気がします。

     


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2011年8月29日 2:51
  • 佐祐理さん、

    > Unicodeのまま文字の全角半角を確認するAPIなどあればいいんですが…。

    もともと、Unicodeに全角半角の概念は無いと思ったですが、、、。

    でも、日本語環境限定と想定すると、

    半角英数:  0x20 - 0x7E(UTF-8), 0x0020 - 0x007E (UTF-16)

    それ以外は、全角扱いでも良いのではないかと。

    実際の幅については、使用するフォントの文字幅を取得するAPIを一文字ずつ

    使うしかないと思います。

    // Arabic, India系で固定ピッチなんて存在するのでしょうか?

     

    • 回答としてマーク いちろう 2011年9月10日 10:13
    2011年8月30日 14:44
  • Unicode Standard Annex #11 EAST ASIAN WIDTHとして、Unicodeにおける全角半角を定めていますよ。ここにWとあるのが全角です。

    そもそも「ア」はU+FF71 HALFWIDTH KATAKANA LETTER A、つまり名前に「半角」と入ってます。

    • 回答としてマーク いちろう 2011年9月10日 10:13
    2011年8月30日 20:35
  • 皆さん。いろいろありがとうございます。
    UNICODEだと、半角の英数字も「1文字」としてカウントされてしまい、
    ログをはき出したときに、カナ漢字と半角の英数字が混在したときに
    きれいに出力されず難儀していました。

    S-JISに変換して、出力するようにします

    2011年9月10日 10:13