- ベストアンサー
printfの書式指定での2バイト文字の巾
2バイト文字、1バイト文字どちらもありうる(構成が不明である)文字列をバイト単位で桁揃えして出力したいのですが、 use encoding 'cp932'; printf "|%2s\n|","あ"; printf "|%2s\n|","aa"; とすると、出力結果は当然 | あ| |aa| となって、桁が揃わないですよね。「バイト単位で2バイト分の巾」という指定を実現するにはどうしたらいいのでしょうか。日本語処理ではよくある問題だと思うのですが。
- Perl
- 回答数2
- ありがとう数3
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
ちょっと裏技的に use Encode ; binmode(STDOUT,":bytes") ; # バイトコードをそのまま出力させるように変更 printf "|%2s\n|",Encode::encode('cp932',"あ"); # cp932にencodeすれば、2バイト文字は「2バイト=2文字」扱いになる 既出の方法の方が汎用性はありますけど。
その他の回答 (1)
- _--_1l1_1_
- ベストアンサー率67% (102/152)
# 表示がくずれるので空白2文字を全角空白にしていることに注意 use strict; use warnings; use utf8; use Encode; use Encode::CJKConstants; my @hello_list = ( 'こんにちは、世界!!', 'Hello World!!', 'HELLO WORLD!!', 'こんにちは、World。', "コンニチハ 世界.", '世界,你好!' ); binmode STDOUT, ":encoding(utf8)"; for my $hello (@hello_list) { my $view_length = count_view_length($hello); my $char_length = length $hello; my $format = '%-' . ( 32 - ( $view_length - $char_length ) ) . 's :'; printf $format, $hello; print "\n"; } # result。等幅フォントで見れば : (コロン)が揃っている # こんにちは、世界!! : # Hello World!! : # HELLO WORLD!! : # こんにちは、World。 : # コンニチハ 世界. : # 世界,你好! : sub count_view_length { my $str = shift; my $view_length = 0; for my $char ( split q{}, $str ) { my $sjis_char = encode( 'sjis', $char ); if ( $char =~ m/\p{InBasicLatin}/ ) { $view_length += 1; } elsif ( $sjis_char =~ m/^$Encode::CJKConstants::RE{SJIS_KANA}$/ ) { $view_length += 1; } else { $view_length += 2; } } return $view_length; }
お礼
大変参考になりました。どうもありがとうございました。
関連するQ&A
- 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 の扱いとしては一般的なものと思われますが、ネット上を検索しても有効な対処が見つかりませんでした。 どなたかよい知恵をお持ちの方がいらっしゃいましたら、知恵を分けてくれるようお願いします。
- ベストアンサー
- C・C++・C#
- printfがなくても文字が現れるのはなぜ!?
#include <stdio.h> #include <string.h> int main() { int hensuu = 0; int *p; p = &hensuu; printf("p=%p &hensuu=%p\n", p, &hensuu); printf("*p=%d\n", *p); *p = 100; printf("*p=%d\n", *p); printf("hensuu=%d\n", hensuu); } 以下、出力結果です。 p=0xff930a1c &hensuu=0xff930a1c *p=0 *p=100 hensuu=100 以上が結果ですが! *p=100 は*p = 100;で終わっていますが!出力結果として文字が出てきたいるのはなぜですか! 宜しくお願いします。
- ベストアンサー
- C・C++・C#
- printfの書式%.*s
海外のサイトに掲載されているサンプルコード中のprintfの書式がわかりません。 printf("%2d: %.*s\n", i, ovector[2*i+1] - ovector[2*i], str + ovector[2*i]); PCREのサンプルの中に出てくるコードですが、上記の「%.*s」は、どういった意味になりますか? よろしくお願いいたします。 http://stackoverflow.com/questions/1421785/how-can-i-use-pcre-to-get-all-match-groups
- ベストアンサー
- C・C++・C#
- printf()関数の第一引数の文字列のアドレスを知りたいんですが。
C言語を色々試して実験中です。 たとえば、 printf("あなたは100歳です\n"); という文をprintf関数で出力するとすると、この文字列定数「あなたは100歳です」のアドレスを調べたいんです。調べる事はできますか?よろしくお願いしますm(_ _)m
- ベストアンサー
- C・C++・C#
- 文字列の探索
ファイル名を指定して文字列の探索を行うというプログラムをC言語で作成したのですが、 コンパイルのときに警告で「問題のあるポインタの変換(関数 main )」と出て、うまい具合に動きません。改良点を教えてください。 #include<stdio.h> #include<string.h> #include<stdlib.h> unsigned char *s1; unsigned char *s2; unsigned char *cp; FILE *fp; char fname[64]; void TestStrStr(void); main(){ s1 = calloc(256, sizeof(unsigned char)); s2 = calloc(256, sizeof(unsigned char)); printf("Input Filename..."); scanf("%s",fname); while(1){ fp = fopen(fname, "r"); if(fp == NULL){ printf("ファイルを開くことができません...\n"); printf("Input Filename..."); scanf("%s",fname); }else break; } s1=fp; // printf("文字列1を入力してください:"); // scanf("%s",s1); printf("文字列2を入力してください:"); scanf("%s",s2); TestStrStr(); return 0; } void TestStrStr(void){ cp = strstr(s1, s2); if(cp == NULL) printf("'%s'に'%s'のいずれの文字も含まれない.\n", s1, s2); else printf("'%s'の中に現れる'%s'という文字列は%d文字目にある.\n", s1, s2, cp - s1 + 1); free(s1); free(s2); }
- ベストアンサー
- C・C++・C#
- NSString文字列をprintfで出力するには
Objective-CでNSStringクラスの文字列をprintf関数で出力しようとするとコンパイルエラーになります。 どうすればprintfで出力できるようになるでしょうか。 実行環境はMacOSX。Xcodeをインストールしています。 ソースコードとエラーメッセージは以下です。 #import <Foundation/NSObject.h> #import <stdio.h> int main(void){ NSString *str01 = @"test"; printf("%s\n", [str01 UTF8String]); return 0; } <コンパイルエラーメッセージ> warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘id’
- ベストアンサー
- その他(プログラミング・開発)
- printfを代入する?
#include <stdio.h> int main(void) { int kaerichi,nyuuryokumoji; char moji[40]; printf("\n数字を入力してください:"); scanf("%d",&nyuuryokumoji); kaerichi=printf("%d",nyuuryokumoji); printf("\n入力数字の桁数は%dです\n",kaerichi); printf("\n文字を入力してください:"); scanf("%s",&moji); kaerichi=printf("%s",moji); printf("\n入力された文字は%dです\n",kaerichi); return(0); } このプログラムでkaerichi=print("d",nyuuryokumoji); とありますがどういう意味でしょうか? 変数に数字などを入れるのはわかるのですが printfをいれるというのがあまりよくわかりません あとどうして桁数がでるのでしょうか?
- ベストアンサー
- C・C++・C#
- printfの出力について
初歩的な事ですが、 short *a; short b; a = &b; printf("%04x\n",x++); だとどのように出力されるのですか? 本を読むと、4つの幅をもたせて16進数で表すと思うのですが、 実行してもよくわからないのでよろしければ教えてください。 bのアドレスは、0x1234としておきます。
- ベストアンサー
- C・C++・C#
- ビット幅とその出力について
C言語を習い始めた者ですが、ビット幅とその出力についてわからないことが二つでてきました。以下のソースコードを見てください。 #include <stdio.h> int main(void) { char ss[] = "ABCDEF"; void *vpt; int idt; vpt = ss; idt = * (char *)vpt; printf("char:%x\n", idt); idt = *(int *)vpt; printf("char:%x\n", idt); return 0; } 出力結果は char:41 char:44434241 となります。 一つ目のわからないことは char:41 についてです。私はchar型のビット幅は8ビットで文字ABの16進数を出力すると予想していました。ところが結果は 文字A の16進数の41のみが出力されました。Aの二進数は 1010、 Bの二進数は1011で それぞれ4ビットずつ持っていて合わせて8ビットになるのでそう考えていました。よくわかりませんが結果から、文字一文字に対して8ビットつまり1バイトに相当するのでしょうか? 二つ目は char:44434241 についてです。一つ目の質問に書いた推測が正しければ1文字を1バイトと考えて16進数にすると Aは41 Bは42 Cは43 Dは44 になります。しかしポインタの先頭のアドレスはAになっているはずなのになぜか出力は char:41424344 ではなくchar:44434241になっています。順序が逆になっているのでしょうか? Cをはじめたばかりなので基本的なところがわかっていないかもしれませんが、説明に不足があればつけたしますのでどうかよろしくお願いします。
- ベストアンサー
- C・C++・C#
- printfの%eで指数部分の桁数を調整する方法?
書式指定子の%eで、8文字までで出力しなければなりません。 printf("data = %8.3e\n",data); 仮にdataが6.456e5の場合、 data = 6.456e+005 (既に10文字でオーバー) となってしまい、指数部の桁数が3桁になってしまうと 有効数字部分が少なくなってしまうので、 指数部を、1桁にする方法はあるのでしょうか? こんな感じで出力できるでしょうか? data = 6.456e+5
- ベストアンサー
- C・C++・C#
お礼
とりあえずはこの方法が簡単そうですので採用させていただこうかと思います。 どうもありがとうございました。