- ベストアンサー
C言語、スキャン集合について
下記のプログラムはスキャン集合を使って入力された文字列の先頭に 並んでいる数字を読み込んで捨て、その後に続く文字列を読み込んで 表示するものです。 #include <stdio.h> int main(void) { char str[80]; printf("数字に続けて文字列を入力してください\n"); scanf("%*[0-9]%s", str); printf("%s", str); return 0; } 【質問】%*[0-9] を %[^0-9] に置き換えてコンパイルして実行すると、 意味不明の文字列が出力されるのはなぜでしょうか? 置き換えても同じ結果になる気がするのですが…
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>対応する引数が指している文字配列がstrで、 >%sの引数がないから、意味不明な文字列が表示されるのですか? その認識で概ねいいと思います。 もう少し正確に言うと、scanfなどの書式指定子では、 書式に見合うだけの実引数がないときの動作は未定義なので、 strにはもしかしたら %[^0-9] にマッチするものが 入っているかも知れませんし、入らないかも知れません。 とにかく何が起こるかはわからないのです。
その他の回答 (5)
- jacta
- ベストアンサー率26% (845/3158)
質問に対する回答はすでに出ているようですが... %[^0-9]のように、0-9が0123456789であることを期待しているのであれば、それは処理系の独自仕様に依存しています。 移植性を考慮するなら、%[^0123456789]と書かなければなりません。 一応念のため。
お礼
ご指摘ありがとうございます! 私が使っている(勉強している)本に、 『厳密にいえば、ハイフンを使って範囲を指定する方法はANSI C標準 には規定されていません。しかし、この方法はほとんどのCコンパイラ で有効です』 と書いてあります。 なので、一応知っているつもりですが…
- yaemon_2006
- ベストアンサー率22% (50/220)
言葉足らず。 対応する引数に対する読み込みを止めろ。 です。
お礼
回答ありがとうございます!! >" 0-9 以外を読み込め。"ではなく、 >" 0-9 の文字に出会ったら読み込みを止めろ。"です。 >対応する引数に対する読み込みを止めろ。 ご指摘どおり、勘違いしていました・・・0-9がその文字列から捨てられる ものだと勘違いしていました。捨てられるのは「%*」の「フィールドの代入 の抑制」でした
- yaemon_2006
- ベストアンサー率22% (50/220)
平たく言うと、[^0-9]は、 " 0-9 以外を読み込め。"ではなく、 " 0-9 の文字に出会ったら読み込みを止めろ。"です。 どんな文字列から、どんな数字を読み飛ばすのかわからないけど、 例えば、 scanf("%*d%s", str) とするとか。
- aris-wiz
- ベストアンサー率38% (96/252)
もう一点。 *は「代入抑止のフラグ」であり、 任意の数にマッチするわけではありません。 %[^0-9]%sでは、実引数がたりません。
お礼
さっそくの回答ありがとうございます! なぜ、数字を後ろに入力すると取り除かれるのですか? 逆に、文字列の前に入力すると取り除かれる気がするのですが? (%sより前に%[^0-9]があるから) 私の使っている本に、 『scanf()はスキャン集合に出合うと、スキャン集合に対応する引数が指 している文字配列に入力を読み込みはじめます。』 とあるので、%[^0-9] に置き換えた場合、対応する引数が指している文 字配列がstrで、%sの引数がないから、意味不明な文字列が表示される のですか?
- aris-wiz
- ベストアンサー率38% (96/252)
正規表現と書式指定子を混合しているように思います。 C言語でのscanfなどの書式指定子では[^]は以下のように動作します 左角括弧の直後がアクサンシルコンフレックス(^)であるときの 走査文字集合は、そのアクサンシルコンフレックスと 「右角括弧の間にある走査文字の並びに現れないすべての文字」 とする。 つまり、「 %[^0-9]」とした場合だと、 数字列を後ろに入力した場合にのみ取り除かれ、 その後の%sにマッチする文字列が無いことでscanfが失敗し 自動変数内の不正な文字列が表示されているのだとおもいます。
お礼
返答ありがとうございます! 大変勉強になりました。 回答ありがとうございました。