• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:続:日本語(マルチバイト)でのwordwrap処理)

日本語でのwordwrap処理に関する問題と解決方法

このQ&Aのポイント
  • 日本語の文字列を指定した字数で折り返す処理に関して、改行後の文字列先頭に「>」を付加する処理が不足している問題があります。
  • 現在のコードでは、追加部分の文字の拾い方が間違っており、改行が正しく検知されない可能性があります。
  • ローカルの環境がSJISであるため、mb関数が正しく動作していない可能性も考えられます。

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

すみません、直接的回答ではないのですが、 私なら、元の部分が1行を処理するルーチンなので、 処理させる部分を変更するのではなく、 処理させる前に、処理できる形に変更する方法でやります。 $data; #データに改行が含まれている文字列 $list=preg_split("/\n/", $data);#改行で分解 $n=10; # 改行させる文字数 foreach($list as $line){ #foreachで一行ずつ処理させる $len=0;#以下元の部分のまま for($i=0;$i<mb_strlen($line);$i+=$len){ for($j=1;$j<=$n;$j++){ $wk=mb_substr($line,$i,$j); if(strlen($wk)>=$n) break; } $len=mb_strlen($wk); print ">$wk\n"; } } --------------------------------------------- 改行パターンがうまくマッチしない場合は \rや \r\nなどを試してみてください。 回答になってなくてすみません。

dokumori
質問者

お礼

いえいえ、すみませんなんて、とんでもない。 回答になってます。一発でいきました。 なるほど。配列にしてから一行ずつ処理していくわけですね。 preg_splitなんて関数知りませんでした。 助かっただけでなく、大変勉強になりました。 BLUEPIXYさん、度々ありがとうございました。

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

関連するQ&A

  • 日本語(マルチバイト)でのwordwrap処理

    簡易メーラーのようなものを作っており、返信の際に改行と”>”が入る処理をしたいと思っています。 しかし、wordwrapを使って分割しようとすると、文字列の途中に半角文字が奇数個入っている場合、その後の文字が化けてしまいます。 mb_splitという関数がありますが、これはまだ実験段階ということなので、今の時点での利用は避けたいと思っています。他のマルチバイト関数を一通り見てみましたが、mb_split以外にwordwrapのような機能は無いように見えました。 どのようにすれば日本語で自動改行処理ができますでしょうか。ご教授下さい。宜しくお願いします。

    • ベストアンサー
    • PHP
  • C言語で分からないところがあるのですが

    すみません。C言語のポインタで分からないことがあって来ました。 ポインタの理屈は理解してはいるのですが、いざソースコードを書いてみようということになると全く手がつけられずにいます。 以下のソースコードですが、strlen()と同じ働きをする関数mystrlen()と、strcmp()と同じ働きをする関数mystrcmpを、ポインタを使って作成するものです。どこをどうすればいいのか教えてくださいませんか。 #include <stdio.h> int main(void) { char str1[80], str2[80]; int i, j; int len1, len2; printf("第1の文字列を入力してください: "); gets(str1); printf("第2の文字列を入力してください: "); gets(str2); /* * 文字列の長さを確認する */ /* NULL文字(文字列の最後)まで読み飛ばす */ for (len1 = 0; len1 < 80 && str1[len1] != '\0'; len1++) ; /* ループ終了後、len1 に文字列の長さが入っている */ if (len1 < 80) { printf("%s は %d 文字の長さです\n", str1, len1); } else { printf ("第1の文字列が80字以上あります\n"); } /* str2 についても同様 */ for (len2 = 0; len2 < 80 && str2[len2] != '\0'; len2++) ; if (len2 < 80) { printf("%s は %d 文字の長さです\n", str2, len2); } else { printf ("第2の文字列が80字以上あります\n"); } if (len1 < 80 && len2 < 80) { for (i = 0; i < 80 && str1[i] != '\0' && str2[i] != '\0' && str1[i] == str2[i]; i++) ; if (str1[i] == str2[i]) { /* 両者同時に == '\0' のはず*/ printf("文字列は等しい\n"); } else if (str1[i] < str2[i]) { /* str1[i] == '\0' のはず*/ printf("%s は %s より小さい\n", str1, str2); } else { /* str2[i] == '\0' のはず*/ printf("%s は %s より大きい\n", str1, str2); } } /* * 十分なスペースがあれば、str2をstr1の最後に連結する */ if (len1 + len2 < 80) { /* str1 の末尾を探す */ for (i = 0; str1[i] != '\0'; i++) ; /* ループを抜けた段階では i は len1 と同じはずなので、 上記のループを作らず、i の代わりに len1 を用いるのも可 */ /* それ以降に str2 の中身をコピーする */ for (j = 0; str2[j] != '\0'; j++) { str1[i+j] = str2[j]; } str1[i+j] = '\0'; printf("%s\n", str1); } else { printf ("文字列をつなげた長さが80字以上あります\n"); } /* * str2をstr1にコピーする */ if (len1 + len2 < 80) { for (i = 0; str1[i] != '\0'; i++) { str1[i] = str2[i]; } str1[i] = '\0'; printf("%s %s\n", str1, str2); } return 0; }

  • 処理が異常に遅い原因はわかりますか?

    久しぶりに、(perlのXSのために)C言語を組んでみましたが、 以下のコードが、異常に遅いようでした。 (実際には、違う処理ですが、これでも遅くなりましたので、単なる文字コピーです) 例えでいえば、同じことをする数文字のperlの正規表現処理の数100倍の時間がかかっていました。 void hoge(char *dst, char *src, int len) { int i; for(i = 0; i < len; i++) { *dst++=*src++; /* ここをなくすと、爆速になる */ } } ※strlenで当初は試していましたが、ほとんどかわりありません。 どこが、原因でしょうか? 以下のコードは、きちんと爆速で動作してくれます。 void hoge(char *dst, char *src) { for(; *dst++ = *src++;); } コンパイルオプションは gcc -O2 または gcc -O3 で、CPUは、x86_64でなっています。(AMD FX-4170) 処理した文字列は、約100Mバイト分になります。 宜しくお願いします。

  • enterでループ終了

    #include <stdio.h> int main(void) { char str[255]; int i, len; while (1){ printf("文字列を入力してください:"); if (fgets(str, sizeof(str), stdin) == NULL) { break; } len = strlen(str); if (len > 0 && str[len - 1] == '\n') str[len - 1] = '\0'; if (str[0] == '\0') break; enterで終了するプログラムの例ですが、 if (fgets(str, sizeof(str), stdin) == NULL) のNULLはどういった理由で必要ですか? また、 if (len > 0 && str[len - 1] == '\n') str[len - 1] = '\0'; を消して、 if (str[0] == '\0') break; を、if (str[0] == '\n') break; と書き換えれば、終了すのではないですか?不適な理由がありますか?

  • 作ったプログラミングC何だけど、評価していただけませんが?不足があれば、教えてください!

    文字列「abc」の各アルファベットを1文字ずらすと文字列「bcd 」になり、 文字列「nisidate」の各アルファベットを2文字ずらすと文字 列「pkukfcvg」となる。さらに、 文字列「kibishii」の各アルファベットを2文字ずらすと文字 列「mkdkujkk」となる。 このような、任意の文字列の各要素を任意の文字数ずらすプロ グラムを作成する、なお、zを1文字ずらしたとき のアルファベットはaとする。 #include <stdio.h> #include <string.h> int main(void) { char str[27]="abcdefghijklmnopqrstuvwxyz",str1[50], str2[50]; int x,i,j,len; printf("文字列を入力---> "); scanf("%s", str1); printf("何文字ずらすかを入力---> "); scanf("%d",&x); len=strlen(str1); for(i=0;i<len;i++) { for(j=0;j<27;j++) { if(str1[i]=='z') { str2[i]=str[x-1]; } if(!(str1[i]=='z')) { if(str1[i]==str[j]) { str2[i]=str[j+x]; } } } } printf("%d文字ずらした文字列は%sです\n", x, str2); return 0; } よろしくお願いします!!

  • ファイルへの書込み処理が異常に遅い

    以下のファイルへの書込みを行なうプログラムの処理速度が極端に遅く困惑しています。 -------------------------------------------------------------------------------- /*  文字列"0,"をファイルに約2MB出力するプログラム  (2000文字で改行、1行毎にfopen&fclose) */ #include<stdio.h> void main( int argc, char *argv[] ) {   FILE *fp;   for( int i = 0; i < 1000; i++ )   {     if( !(fp = fopen( "C:\hogehoge.log", "a" ) ) )     {       exit( 1 );     }     for( int j = 0; j < 1000; i++ )     {       fprintf( fp "0," );     }     fprintf( "\n" );     fclose( fp );   }   exit( 0 ); } -------------------------------------------------------------------------------- 処理時間は5分程度です。 出力する文字列を"0#"に変えると5~6秒で終了します。 カンマが入ると違うのでしょうか? OSはWinXP、コンパイラはVC++7.0です。 原因と解決策をご存知の方、よろしくご教示下さい。

  • C言語の文字列について

    abcdefghという文字列を入力した時に以下のように表示させたいのですがわかりません。(入力した文字を逆から表示させて、且つ文字数を4分割させて改行させる) hg fe dc ba 自分で考えたソースは以下のようです。(これではhgfedcbaと表示するだけなのです)どうしてもわからないので教えてください。宜しくお願いします。 #include <stdio.h> #include <string.h> int main(void) { char input[20]; size_t len,h,k,j; size_t i; gets( input); len=strlen(input); h=len/5; k=h; for(j=1; j<=5;++j) { for(h=k*(j-1); h<k*j; ++h) { printf( "%c", input[len - h - 1]); } } scanf( "%20s", input); return 0; }

  • ファイルから1行ずつ読み込み

    とても基礎なことかもしれませんが、質問させてください。 あるファイルに 1 23 3 4 53 3 32 89 7 4 5 3 4 3 4 5 6 7 といった数字の列が入っていて、 それを1行ずつ、読み込み、配列A[]に代入するにはどうすればよいでしょうか? 例えば上の例では、 A[0]には1、A[1]には23、A[2]には3・・・という感じで代入して処理を行った後、2回目は A[0]には32、A[1]には89、A[2]には7・・・ として処理を行う、といった作業を繰り返したいです。 for (i=0;;i++){  fscanf(fp,"%d",&j);  if(j == '\n') break;  s[i] = j; } としたのですが改行が判別できないらしく、1行はなく最後まで読み込まれてしまいます。

  • 文字列配列のほしい部分だけを抜き出して数値にする方法(PIC)

    現在PICマイコンでPCからGPSの座標データを取得し,そのデータ列から必要な部分だけ抜き出す処理をくんでいるんですがうまくいきません。 pcとマイコンの接続はrs23-2c コンパイラはccsc pic:16f877 GPSデータ↓ @051125012151N3529558E13638533G009+00021E0000N0000D0003 このデータのN以降の「3529558」とE以降の「13638533」の文字列を数値にしたい。 delay_ms(300); output_b(0b00000001);//デバック用LED点灯 delay_ms(300); gets(mes);    //ここでGPSデータをmesに代入する output_b(0b00000011); len_N=0; for(i=0;i<58;i++){  if(mes[i]=='N'){   len_N=i;   break;  } } printf("\r\n"); n=atoi(mes[len_N+1]); //ここで試しに一文字分だけ数値にする処理を行ったが処理が停止する。 printf("n:%ld",n); アドバイスお願いします

  • こんな処理は可能ですか?(動的な命名)

    以下のように、switchでnumの値を分岐させてその値ごとに tmp[j][i]に格納する変数を変えたいのですが、こういうことはもっと スマートにできないでしょうか? int num = (ランダムな数取得); for ( int j = 0; j < 100; j++ ){   for ( int i = 0; i < 100; i++ ){     switch ( num ){     case 1: tmp[j][i] = num1[j][i]; break;     case 2: tmp[j][i] = num2[j][i]; break;     case 3: tmp[j][i] = num3[j][i]; break;      ・      ・      ・     }   } } ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 上のコードを int num = (ランダムな数取得); char *str = "num"; strcat( str, (char *)num ); //文字列の連結 tmp[j][i] = (*str)[j][i]; 見たいな雰囲気でスマートにできるのではないかと思ったのですが・・。 動的な関数呼び出しとか##演算子とかそういうのと組み合わせてこんなことは 実現できないでしょうか?