8

私は正確にどのように機能するかを理解しようとしてscanfいます。次のようなコードを作成すると:

scanf("%s %d %f", name, &age, &wage);

これを標準入力として入力します。

james 20 34000.25

次に、名前、年齢、賃金をそれぞれ出力すると、標準入力に入力したものと同じものを正確に取得できます。ただし、次のようなものを入力すると:

scanf("%s/%d/%f", name, &age, &wage);

これを標準入力として入力します。

james/20/34000.25

james/20/34000.25文字列値の文字列と、整数値と浮動小数点値のそれぞれ 0 と 0.00000を取得します。scanf最初のバージョンでスペースを扱うのと同じようにスラッシュを扱うと思いました。ユーザーがスラッシュで区切られた値を入力した場合、その値を変数に適切に割り当てることができるようにするにはどうすればよいですか?

4

2 に答える 2

7

%s非空白文字に一致します (これは貪欲な一致です: 他の一致が可能かどうかを確認するためにバックトラックするつもりはありません) 非スラッシュ文字に一致するには、次を使用します%[^/]

'/'(また、scanf 文字列内のスペース文字 (0 個以上の空白文字に一致) は、 (正確に一致)などの非スペース非パーセント文字とは非常に異なる動作をすることに注意してください'/')

于 2013-03-11T01:56:10.387 に答える
3

スペースで区切られた入力とスラッシュで区切られた入力の両方を一致させるには、適度に複雑なフォーマット文字列が必要です。

if (scanf("%[^ /]%*1[ /]%d%*1[ /]%f", name, &age, &wage) == 3)
    ...data was read properly...
else
    ...something went wrong...

最初の変換仕様は、非ブランク、非スラッシュのシーケンスを受け入れるスキャンセットです(したがって、最初のブランクまたはスラッシュで停止します)。スタックオーバーフローを回避するために、受け入れられる文字数の上限を指定するのが最善です。たとえば、の場合char name[32];%31[^ /](オフバイワンに注意してください)。2番目の変換仕様は、ブランクまたはスラッシュのいずれかで%*1[ /]ある単一の文字()を受け入れ、それを変数()に割り当てません。3番目の変換仕様は標準の数値入力であり、先頭の空白をスキップし、負の数を入力できるようにします。4番目の変換仕様は2番目と同じで、5番目はaの標準形式です(つまり、1[ /]*float34000.25有効数字7桁は、表現可能な値の範囲の外側にあります)。

「問題が発生した」部分では、エラーをユーザーに一貫して報告するのが難しいことに注意してください。これが、私を含め、多くの人々が、またはを使用することを推奨し、scanf()またはfscanf()おそらくfgets()POSIXgetlineを使用してユーザーからの行を読み取り、それsscanf()を分析するために使用することを推奨する理由です。問題をはるかに簡単に報告できます。scanf()また、からの戻り値は成功した割り当ての数であることに注意してください。を含む変換仕様はカウントされません*

于 2013-03-11T02:19:19.377 に答える