if (/^COUNT/)とsprintf("%%0%dld", $figure)とsprintf("%ld", $count)の意味は?

[上に] [前に] [次に]
!!! [E-Mail] 2000/02/01(火) 20:03:18
とほほカウンターのスクリプトを見ていたんですが、
わからないところがあったんです。
if (/^COUNT/) {

$cntstr = sprintf(sprintf("%%0%dld", $figure), $count);

$cntstr = sprintf("%ld", $count);
の意味がわからないんですけど、教えてくれませんか?

気まぐれ 2000/02/01(火) 23:49:48
>if (/^COUNT/) {
もし $_ の文字列が COUNT で始まっているなら { 以降のコマンドを実行

>$cntstr = sprintf(sprintf("%%0%dld", $figure), $count);
$cntstr という変数に $fingure を整形して代入

>$cntstr = sprintf("%ld", $count);
同上

明日、本屋さんで Perl解説本を買う!が正解

mm 2000/02/02(水) 00:27:25
>明日、本屋さんで Perl解説本を買う!が正解
賛成!
…ですが、
>$cntstr = sprintf(sprintf("%%0%dld", $figure), $count);
については、C言語の sprintf で使える幅指定子の * が perl ではサポートされて
いないってことで、オンラインマニュアルには、↓のように書かれています。
>(長さの間接指定のための * 文字はサポートされていませんが、
> 変数をパターン内で展開すれば、同じ結果となります。)
これに従えば、
$cntstr = sprintf("%0${figure}ld", $count);
と書くのが吉でしょう。

B-Cus 2000/02/02(水) 00:56:27
perl5.00404/5.00503 では
  % perl -e 'printf "%0*d\n",7,123'
  0000123
となりましたので、* もOKのようです。perl4 ではダメですね。

mm 2000/02/02(水) 08:13:19
>となりましたので、* もOKのようです。perl4 ではダメですね。
あっ、ホントだ。ありがとうございます。ぜんぜん知らんかった(^^;

perl5(たぶん極初期バージョンは除く?)では、↓でもいいことになりますね。
$cntstr = sprintf("%0*ld", $figure, $count);

!!! [E-Mail] 2000/02/04(金) 20:33:13
%%0%dldや
%ldの意味も知りたいんですけど…

mm 2000/02/05(土) 00:46:58
printfやsprintfの書式文字列の書き方は、結構ややこしいので、
perlかC言語のちゃんとした解説をどこかで読まれた方がいいんじゃないかなぁ…

B-Cus 2000/02/05(土) 07:47:52
> 明日、本屋さんで Perl解説本を買う!が正解
で、こういう素晴らしいアドバイスをもらったのに、本は買わないの?
# …ま、ずっと初心者でいたければ、他人に聞き続けてもいいけどさ。


以下、FreeBSD jpman プロジェクトが作成した日本語訳の抜粋。
長くてゴメン。

     フォーマット文字列は、0 以上の命令から構成されています。この命令には、出
     力ストリームに変更されずにコピーされる通常文字 (% 以外)、およびゼロ以上の
     後続引数を取り出す変換指定があります。それぞれの変換指定は、文字 % で導入
     されます。引数は、タイププロモーション後に変換指示子に適切に対応する必要
     があります。 % の後には、以下が順番に現れます。

     o   後に $ が続く 10 進数文字列から構成され、次にアクセスする引数を指定す
         る任意のフィールド。このフィールドを指定しないと、最後にアクセスされ
         た引数に続く引数が使用されます。引数には 1 から始まる番号が付きます。
         フォーマット文字列で、アクセスできない引数がアクセスできる引数に点在
         する場合、結果は不定になります。

     o   0 個以上の以下のフラグ

         -   値を「代替フォーム」に変換することを指定する # 文字。 c, d, i, n,
             p, s, および u 変換の場合、このオプションは効果を発揮しません。 o
             変換の場合は、数値の精度が上がり、出力文字列の最初の文字が 0 にな
             ります (明確な精度の 0 で 0 が出力される場合を除く)。 x 変換と X
             変換の場合は、0 以外の結果の前に文字列 `0x' (X 変換の場合は `0X')
             が付きます。 e, E, f, g, および G 変換の場合は、小数点以下がなく
             ても小数点が結果に常に含まれます (通常の場合、小数点以下がある場
             合にかぎり、変換結果に小数点が付きます)。 g および G 変換の場合
             は、後続の 0 が通常の場合のように結果から削除されません。

         -   0 のパディングを指定する `0' 文字。 n 変換を除くすべての変換で
             は、変換値の左にブランクではなく 0 が付きます。数値変換 (d, i, o,
             u, i, x, および X) で精度が指定されている場合、 `0' フラグは無視
             されます。

         -   負のフィールド幅を示す `-' フラグ。変換値はフィールド境界の左で揃
             えられます。 n 変換以外では、変換値の左にブランクか 0 が付くので
             はなく、変換値の右にブランクが付きます。 `-' と `0' を両方とも指
             定した場合は `0' が無効になります。

         -   スペース。符号付き変換 (d, e, E, f, g, G, および i) で作成される
             正の数値の前にブランクが残ります。

         -   `+' 文字。符号付き変換で作成される数値の前に常に符号が付きます。
             `+' とスペースを両方とも指定した場合はスペースが無効になります。

     o   任意の 10 進数文字列。最低フィールド幅を指定します。変換値の文字数が
         フィールドの幅より少ない場合は、左にスペースが付いて (左揃えフラグを
         指定した場合は右にスペースが付いて) フィールドの幅に合わせられます。

     o   ピリオド `.' の次に任意の数字文字列が続く形式の精度。数字文字列を省略
         した場合、精度はゼロになります。 d, i, o, u, x, および X 変換では、こ
         の精度の最低桁数が出力されます。 e, E, および f 変換では、小数点以下
         にこの精度の桁数が出力されます。 g および G 変換では、この精度の最大
         有効桁数が出力されます。 s 変換では、この精度の最大文字数が文字列から
         出力されます。

     o   オプション文字 h。後の d, i, o, u, x, および X 変換が short int 引数
         か unsigned short int 引数に対応すること、または後の n 変換が short
         int 引数のポインタに対応することを指定します。

     o   オプション文字 l。後の d, i, o, u, x, および X 変換が long int 引数か
         unsigned long int 引数のポインタに適用されること、または後の n 変換が
         long int 引数のポインタに対応することを指定します。

     o   オプション文字 q。後の d, i, o, u, x, および X 変換が quad int 引数か
         unsigned quad int 引数に対応すること、または後の n 変換が quad int 引
         数のポインタに対応することを指定します。

     o   オプション文字 L。後の e, E, f, g, および G 変換が long double 引数に
         対応することを指定します。 long double の値が、 VAX コンパイラと
         Tahoe コンパイラではサポートされていないことに注意してください。

     o   適用する変換のタイプを指定する文字。

     フィールド幅か精度、またはその両方は、アスタリスク `*'、または数字文字列
     の代わりに 1 つ以上の 10 進数と `$' が続くアスタリスクで指定できます。こ
     の場合、 int 引数はフィールド幅か精度を提供します。負のフィールド幅は、正
     のフィールド幅が続く左揃えフラグとして扱われます。負の精度は、欠落してい
     るものとして扱われます。1 つのフォーマット命令に位置引数 (nn$) と位置以外
     の引数が混在している場合、結果は未定義になります。

     変換指示子とその意味は次のとおりです。

     diouxX  int 引数 (または適切な可変引数) が、符号付き 10 進 (d と i)、符号
             なし 8 進 (o)、符号なし 10 進 (u)、符号なし 16 進 (x と X) に変換
             されます。 x 変換には文字 abcdef、 X 変換には文字 ABCDEF が使用さ
             れます。精度は、出力する最低桁数を指定します。変換値で少ない桁し
             か必要ない場合は、左に 0 が付きます。

     DOU     long int 引数が、符号付き 10 進、符号なし 8 進、符号なし 10 進
             に、それぞれのフォーマットが ld, lo, lu であるかのように変換され
             ます。この変換文字には問題があるので、最終的には出力されません。

     eE      double 引数が丸められ、 [-]d.ddde+-dd のスタイルに変換されます。
             小数点以上は 1 桁で、小数点以下の桁数は精度と等しくなります。精度
             が指定されていない場合は 6 が仮定されます。精度がゼロである場合、
             小数点は出力されません。 E 変換では、文字 E (e ではない) が使用さ
             れて指数が導入されます。指数には、最低 2 桁が常に含まれます。値が
             0 である場合、指数は 00 になります。

     f       double 引数が丸められ、 [-]ddd.ddd のスタイルで 10 進に変換されま
             す。小数点以下の桁数は、精度指定に等しくなります。精度が指定され
             ていない場合は 6 が仮定されます。精度が 0 である場合、小数点は出
             力されません。小数点が出力される場合は、小数点以上に最低 1 桁が出
             力されます。

     g       double 引数が、スタイル f か e (G 変換の場合は E) で変換されま
             す。精度は有効桁数を指定します。精度が指定されていない場合は 6 が
             仮定されます。精度がゼロである場合は 1 として扱われます。変換後の
             指数が -4 より小さいか精度以上である場合は、スタイル e が使用され
             ます。後続のゼロは、結果の小数部から削除されます。小数点は、小数
             点以下に最低でも 1 桁ある場合に出力されます。

     c       int 引数が unsigned char に変換され、変換された文字が出力されま
             す。

     s       ``char *'' 引数が、文字型の配列を指すポインタ (文字列へのポイン
             タ) とみなされます。配列の文字は、最後のナル文字まで出力されます
             (ナル文字は出力されません)。精度が指定されている場合、指定された
             数以上は出力されないので、ナル文字は必要ありません。精度が指定さ
             れていない場合、または精度が配列のサイズ以上である場合、配列の最
             後にはナル文字が必要です。

     p       ``void *'' ポインタ引数が、16 進で `(%#x' か `%#lx' でのように)
             出力されます。

     n       これまでに出力された文字数が、 ``int *'' ポインタ引数 (または可変
             ポインタ引数) が指定する整数に保存されます。引数は変換されませ
             ん。

     %       `%' が出力されます。引数は変換されません。完全な変換指定は `%%'
             です。

     フィールド幅が存在しない場合、またはフィールド幅が小さい場合でも、フィー
     ルドは切り捨てられません。変換結果がフィールド幅より大きい場合、フィール
     ドは変換結果を収容できるようになるまで拡張されます。


# printf のマニュアルが理解できる頃には、既に printf は
# 使いこなせている、という説もある :-)

!!! [E-Mail] 2000/02/05(土) 13:05:52
> 明日、本屋さんで Perl解説本を買う!が正解
> で、こういう素晴らしいアドバイスをもらったのに、本は買わないの?
そう言われても、私は小学生なので、それだけ高い本を買うお金がなかなかたまらないので、なかなか買えません。
%%0%dldはこうなるのであってますか?
%%0%dld 桁数の数字(仮に5)
↓ ↓
% 05 ld
%05ldになって、
仮にその後の数字を123とすると
0が付いている事によって、桁数の余りを0でうめることにする。
その後の5で5桁にすることにする。
l、よくわからない。
dで10進数の数字にすることにする。
00123
となる、であってますね。
long int 引数か
unsigned long int 引数のポインタに適用されること、
が理解できません。

B-Cus 2000/02/05(土) 15:48:39
> そう言われても、私は小学生なので
親にねだりましょう。

> %%0%dldはこうなるのであってますか?
合ってます。

> l、よくわからない。
要は、h は2バイト整数と見なす、ということです。
l は4バイト。でも元々 perl の数は 4バイトなので、
この場合は l を付ける意味はありません (よね?)。

   % perl -e '$i=32767; printf("%d %ld %hd\n",$i,$i,$i)'
   32767 32767 32767
   % perl -e '$i=32768; printf("%d %ld %hd\n",$i,$i,$i)'
   32768 32768 -32768
   % perl -e '$i=65535; printf("%d %ld %hd\n",$i,$i,$i)'
   65535 65535 -1
   % perl -e '$i=65536; printf("%d %ld %hd\n",$i,$i,$i)'
   65536 65536 0

わからなければわからなくていいです。
こんなの perl では使わないし (C でもまず使わんでしょう)。

!!! [E-Mail] 2000/02/05(土) 20:56:30
[[解決]]
これでわかりました。
ありがとうございます。

[上に] [前に] [次に]