• 締切済み

マルチバイト混在の文字列整形

OS: Linux Ubuntu 言語: C++ 引数でchar*型の文字列配列(マルチバイト含む)を受け取り 指定した幅で枠つきで文字列を出力したいのですがうまくいきません。 作りたい出力 ━━━━━━━ ┃1: あいうえお┃ ┃2: かきく   ┃ ┃3: abc    ┃ ━━━━━━━ - str[] = {"あいうえお", "かきく", "abc"} - あいうえおの後ろは空白なし - 他は空白と文字列を合計してあいうえおと同じ長さに合うように 私の環境では日本語は3byteと認識され  strlen("あいうえお") = 15 となります。 イメージでは for (i = 0; i < strlen(str[])の最大値; i++) { cout << "┃" << i << ":" << setw(15) << left << str[i] << "┃" } のようなコードになると思うのですが 日本語一文字が出力上は2byte分の幅に見えるのに 認識としては3byteになってしまうので空白が1byte多くなり ━━━━━━━ ┃1: あいうえお┃ ┃2: かきく    ┃ ┃3: abc       ┃ ━━━━━━━ のようにずれてしまいます。 (表記上、最初の枠もずれていますが  現状は足りない分を埋めるsetfillが余計に働いてしまうということです。) 何か対策はありますでしょうか?

  • oxfax
  • お礼率27% (57/209)

みんなの回答

回答No.6

> Unicodeで作成していました。 > Shift-JISだと確かに2byteで問題なくできました。 ならばUTF-8だったのでしょう。 UTF-16なら全角/半角によらず2byteですし、strlenは誤動作しますから。 > ただ、フォントに依存しないような結果画面にしたいのですが > 端末の文字コードをプログラム実行に強制変更などということはできますか? フォントと文字コードは別物です。 Shift-JISに変換したのち長さを返す関数をひとつ用意すればいいかと。

  • wormhole
  • ベストアンサー率28% (1619/5654)
回答No.5

>意図としては結果画面が環境依存したくないということです。 環境依存にしたくないということであれば「等幅フォント」前提というのは環境依存ではないでしょうか。 >端末の文字コードをプログラム実行に強制変更などということはできますか? できません。

回答No.3

文字コードがEUC-JPかなにかかしら。 Shift-JISに変換すれば半角1byte/全角2byteになりますぜ。

oxfax
質問者

補足

Unicodeで作成していました。 Shift-JISだと確かに2byteで問題なくできました。 ただ、フォントに依存しないような結果画面にしたいのですが 端末の文字コードをプログラム実行に強制変更などということはできますか?

  • wormhole
  • ベストアンサー率28% (1619/5654)
回答No.2

文字のバイト数と表示幅を関連づけて考えるのがそもそもの間違いです。 まともにするなら文字に対応するフォントの情報から表示幅を取得することになります。 フォントから情報を取得するような事はしたくない、ということであれば文字を引数に表示幅を返すサブルーチンを作成するのがよいかと思います。

oxfax
質問者

補足

サブルーチンで日本語が3byteの場合は対応できました。 表示幅というのは表現が変かもしれませんが 意図としては結果画面が環境依存したくないということです。

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.1

1バイト文字は1と数え、3バイト文字は2と数えると言うことであれば、自分でサブルーチンを作るしかないと思います。

oxfax
質問者

お礼

サブルーチンでやる方法はできました。ありがとうございます。

関連するQ&A

  • phpでマルチバイトを含む文字列のバイト数を求めることは可能でしょうか?

    例として次のような文字列のバイト数を求めたいです。 あaいbc54うえ strlenは正確にバイト数が返ってきませんでした。 mb_strlenでは文字数が返ってきてしまうため、使えません(あくまでもバイト数です。) 結果個人的にmb_strwidthを使うことに行き着いたのですが、mb_strwidthは文字幅を評価する関数と表記されていました。 何パターンか実際にテストしてみた結果mb_strwidthでも動作に支障はなかったのですが、mb_strwidthを使うという方法で 正しいのでしょうか? もし、バイト数を数えるよい方法がございましたら教えていただきたいです!よろしくお願いします。

    • 締切済み
    • PHP
  • Cでは文字列をどのように認識するのでしょうか?

    C言語には文字列型というものは存在しないと教わりました。 文字列の終わりはヌル文字で認識できますが、 文字列型というものが存在しないのに何故次のバイトを読もうとするのですか? たとえばchar str[] = "abc";、あるいはchar *p = "abc";とあったとして printf(str);あるいはprintf(p); でなぜabcが出力されるのでしょうか?なぜaの次にbがbの次にcがあるとわかるのでしょうか? char型で先頭アドレスが渡された場合、ヌル文字を見つけるまでアドレスをインクリメントし続けるという決まりでもあるのでしょうか? それに文字列型というものが存在しないなら''と""を分ける意味もないのでは??

  • 文字列の整形

    文字列"abc"を"abc___"(_は半角空白の代わり)のように必要な桁数だけ 空白で埋めるにはどうすればよいでしょうか? 自分はAPIの中から適当なものを見つけられなかったため ループで必要な桁数になるまで空白をappendする といった方法をとってしまったのですが、 もしかして適当なAPIがあるのかと思いまして 質問いたしました。 またこういう処理は端的にいうと何々処理というのでしょうか?

    • ベストアンサー
    • Java
  • C言語の文字列の取り扱いが分かりません

    こんにちは。 C言語で分からないことがあり、質問させていただきました。 学校で、文字列の取り扱いを習いました。 そこで質問なんですが、以下のソースコードをstrcpy , strcat , strcmp , strlen を使わずに書くことってできないですか? 先生に質問したところ、ポインタとかいうのを使うのだそうですが、それを使わずに書くことってできるんですか?もしよろしければお願いします。 以下のプログラムですが、ユーザーから2つの文字列を受けて、そこから4つの文字列関数を使ってみましょう、というやつです。実行結果も貼っておきますね。 #include <string.h> #include <stdio.h> int main(void) { char str1[80], str2[80]; int i; printf("INPUT 1st word-line. : "); gets(str1); printf("INPUT 2nd word-line. : "); gets(str2); /*文字列(word-line)の長さを確認します。*/ printf("%s is %d moji long.\n", str1, strlen(str1)); printf("%s is %d moji long.\n", str2, strlen(str2)); /*文字列を比較します。*/ i = strcmp(str1, str2); if (!i) printf("two word-lines are same length.\n"); else if (i < 0) printf("%s is smaller than %s.\n", str1, str2); else printf("%s is bigger than %s.\n", str1, str2); /*十分なスペースがあるのなら、str2をstr1の最後に結合させます。*/ if((strlen(str1) + strlen(str2)) < 80 ){ strcat(str1, str2); printf("%s\n", str1); } /*str2をstr1にコピーする*/ strcpy(str1, str2); printf("%s %s\n", str1, str2);

  • 全角文字と半角文字を判別して文字列を追加

    全角文字と半角文字が混合している文字列に文字を追加するプログラムを考えています。 仕様としては全角から半角に変わる際には全角文字の後ろに1234を、 半角から全角に変わるときは半角文字の後ろに4321をつけるというものです。 例1 文字列が「あxxxお」ならば出力結果は「あ1234xxx4321お」 そこで質問なのですが 文字列から全角文字と半角文字をプログラム上で判別して 上記のように出力するにはどうしたらいいんでしょうか? ヒント等ございましたらどうぞお願いします。 とりあえず作ってみた例1の結果を無理やり出力するプログラムのコードを載せておきます。 こちらをうまく改変してくださっても結構ですのでよろしくお願いいたします。 #include <stdio.h> #include <string.h> int main(void){ unsigned char str0[256] = "あxxxお", str1[256] = "1234",str2[256]= "4321"; unsigned int zh,hz, len0 = strlen(str0),len1=strlen(str1),len2=strlen(str2); printf("挿入前:%s\n",&str0); zh=2; //全角から半角に変わる位置 hz=5; //半角から全角に変わる位置 //1234を挿入/// memmove(&str0[zh+len1], &str0[zh], len0 - zh+1); memcpy(&str0[zh], str1, len1); //4321を挿入/// memmove(&str0[hz+len1+len2], &str0[hz+len1], len0); memcpy(&str0[hz+len1], str2, len2); printf("挿入後:%s\n",&str0); return 0; }

  • OpenGLを用いた文字列の表示

    OpenGLを用いた文字列の表示に関して質問です。 現在,VisualC++6.0でDLLを作成し,VBA上でモデリングを行うツールの作成をしています。 http://www.natural-science.or.jp/article/20091123143714.php 上記サイトを参考にして文字列の出力はできたのですが, 文字列に色の指定ができなくなってしまいました。 (ツール作成当初はできていました) 文字列を描画している部分のソースは以下のようにしています。 glColor3fv( color ); glRasterPos3fv( pos ); for(int i=0;i<strlen(str);i++){  glutBitmapCharacter( GLUT_BITMAP_9_BY_15 , str[i] ); } もしかしたら,他のところに原因はあるのかもしれませんが, ご存知の方がいらっしゃいましたら, ご教授いただけませんでしょうか。 以上,よろしくお願いいたします。

  • 文字列の扱い方

    初歩的な質問ですみません… str文字列からcという文字を見つけたら添字を返すという関数を作ったのですが、 iにこの関数を代入して、if文の制御式にiを使って比較するまでは正常なのですが、 真文にiを使うと何故か偽文(という言い方でいいのでしょうか…この場合("そんな値はありません。"というところです)が実行されてしまいます。 よろしければご教授お願い致します。 #include <stdio.h> int str_char(const char str[],int c) { int len = strlen(str); int i; for (i = 0;i < len;i++) { if (str[i] == c) return i; } return -1; } int main() { char str[64] = "Fucking Brutal Death Metal"; int ch,i; printf("どの文字を調べますか?"); scanf("%c",&ch); i = str_char(str,ch); if (i >= 0) printf("その文字は%d番目にあります。",str_char(str,ch) + 1); //何故かiだと動かない else printf("そんな値はありません。"); return 0; }

  • 文字列から空白を取り除きたいのですが

    C言語を勉強しはじめて間もない者です。 文字列から空白を取り除く(空白は左に詰めることで埋める)処理をしたいのですが、下記のようなやり方でうまくできなくて困っています。 ↓を実行すると" 1234"なら"12344"になるはずだったのですが、うまくいきません。何がおかしいのでしょうか?? よろしければご教授願います。 ※文字列は半角のみ想定しています。 int i = 0; char str[] = " 1 23 4 5"; char *p; p = str;   while( *p != '\0' ){     if ( isspace(*p) != 0 ){       while( *(p + i + 1) != '\0' ){         *(p + i) = *(p + i + 1);         i++;       }     }     p++;   }  

  • 入力した文字列から母音だけを出力するプログラム

    文字列を入力し母音だけを出力するプログラムを作りました。 以下だと小文字の母音しか出力できないので大文字にも対応させたいのですが、switch文のcaseを増やすと冗長になってしまう気がします。 switch文以外の方法でもっと簡潔に書く方法はありますか?ご教授お願い致します。 /* 入力した文字列のうち、母音「a,i,u,e,o」だけ出力する */ #include <stdio.h> #include <string.h> #define MAXSTR 256 int main(void) { char str[MAXSTR]; int i; gets(str); for (i = 0; i < strlen(str); i++) switch (str[i]) { case 'a': putchar(str[i]); break; case 'i': putchar(str[i]); break; case 'u': putchar(str[i]); break; case 'e': putchar(str[i]); break; case 'o': putchar(str[i]); break; } putchar('\n'); return 0; } 実行結果: What time is it now? aieiio

  • 文字列の検索について

    こんにちわ。文字列の検索について質問があります。 ↓のコードは、 「$str という文字列の中に"<!>" という文字列が含まれていたら、その都度その位置を 知らせる」と意図したものです。 $str の中に "<!>" が3つ含まれていたら、3回それらの位置を知らせるはずです。 しかし、実際は、最後の $iの位置だけ出力されます。 どこに問題があるのでしょうか? よろしくお願いいたします。 -------コード(ココカラ)------- for ($i=1; $i<length; $i++) { $strsub=substr($str, $i, $i+2); if ($strsub == "<!>") { echo $i; echo "\r\n"; } } -------ココマデ-------

    • ベストアンサー
    • PHP

専門家に質問してみよう