2016-09-04 2 views
2

私は自己学習Cで、現在ScanfとPrintfの機能を研究しています。Scanf/Printf in C ...ここで何が起こっていますか?

私は自分自身をテストする場合は、このプログラムを適応:私はscanfの機能の理解とどのように「繊細」彼らは可能を把握するため

char topping[24]; 
int slices; 
int day, year; 
float cost; 
char month[10]; 

printf(" How much does a pizza cost in your area?\n"); 
printf("$"); 
scanf(" %f", &cost); 

printf("What is your favorite one-word pizza topping?\n"); 
scanf(" %s",topping); 
printf("How many slices of %s pizza, topping can you eat in one sitting\n",topping); 
scanf(" %d", &slices); 

printf(" What is today's date (enter in the following format 1-Jan-2016)\n"); 
scanf(" %d-%s-%d", &day, month, &year); 
printf("\nWhy not treat yourself to dinner on %d-%s-%d and have %d slices of %s pizza ? It will only cost you %.2f", day, month, year,slices, topping,cost); 

運動の目的です。

私のテストプログラムはここでうまくいきます...年変数の出力は例外です。

なぜ年変数の出力がばかげているのですが、どうすれば修正できますか?

ありがとうございます。

+1

"%d-%9 [^ - ] - %d"と試してください –

+2

デバッガを使用してコードをステップ実行して動作を確認する方法を学んでください –

答えて

5

ここに問題があります。 %s指定子は、次の空白まで文字を読み取ることを意味します。したがって、%d-1-と一致した後、%sJan-2016と一致します。次に一致するものが残っていないので、次の%dが失敗します。

最初に返り値scanfをチェックして、一致するエラーがあるかどうかを確認する必要があります。たとえば、この場合:

if (3 != scanf(" %d-%s-%d", &day, month, &year)) 
{ 
    printf("Matching failure occurred.\n"); 
    // do something else... 
} 
else 
{ 
    printf("Why not treat yourself... 

第2に、実際にこの問題を回避する。あなたが見ることができるように、scanf関数はかなり制限されています。 (同じエラーチェックで)

scanf(" %d-%9[^-]-%d", &day, month, &year) 

:代わりに空白の他の区切り文字を使用するには、代わりにスキャンセット指定子%[.....]を使用することができます。スキャンセット指定子とは、^が次の文字と一致しないことを示していることを除いて、[]内の文字に一致する任意の文字(恐らく空白を含む)を読み取ることを意味します。だから、これはすべて次の-まで読むでしょう。また、サイズ9+1のバッファがあふれないように、9を追加しました。

もちろん、人が別のタイプを入力しない場合は、-となり、プログラムがちょっと変わってきます。書式文字列をますます複雑にすることでこれを修正できます。代わりにfgetsで行全体を読み取ってから、sscanf関数を前述の文字列とともに使用することもできます。これは、別の-と入力する前に、Enterキーを押した人のケースをキャッチします。

実際には、一度に1行全体を読み込んでから、その行に戻って処理することをお勧めします。

いくつかの段階では、恐ろしいscanfが疲れて、独自のパーサを作成することがあります。

+0

'%['は新しいC99。 – unwind

+0

@unwindあなたは...固定されています –

関連する問題