web-dev-qa-db-ja.com

scanf()形式の文字列の末尾の空白の影響は何ですか?

このコードのscanf("%d")scanf("%d ")の違いは何ですか。違いは、フォーマット文字列の末尾の空白です。

_#include <stdio.h>

int main(void)
{
    int i, j;

    printf("enter a value for j ");
    scanf("%d  ",&j);
    printf("j is %d\n", j);
    printf("enter a value for i ");
    scanf("%d", &i);
    printf("i is %d\n", i);
    return 0;
}
_

scanf()のようなフォーマット指定子の後にスペースを追加すると、scanf("%d ", &j);関数は実際にどのように機能しますか?

20
Vikas Verma

Scanf形式の空白文字を使用すると、できるだけ多くの空白文字を明示的に読み取って無視します。したがって、scanf("%d ", ...を使用すると、数値を読み取った後も文字の読み取りが続行され、入力に空白以外の文字が表示されるまですべての空白が破棄されます。その空白以外の文字は、入力関数によって読み取られる次の文字として残されます。

あなたのコードで:

printf("enter a value for j ");

scanf("%d  ",&j);

printf("j is %d \n", j);

最初の行を出力してから、数値を入力するのを待ち、次にその後も待ち続けます数値。だからあなたがタイプするだけなら 5Enter、ハングしているように見えます—続行するには、空白以外の文字を含む別の行を入力する必要があります。次に入力すると 6Enter、これがiの値になるため、画面は次のようになります。

enter a value for j 5
6
j is 5
enter a value for i i is 6

また、ほとんどのscanf%-変換では先頭の空白もスキップされるため(%c%[、および%nを除くすべて)、スペースbefore%-変換は関係ありません( "%d"" %d"は同じように動作します)。したがって、ほとんどの場合、scanf変換では、特殊な効果のためにスペースが特に必要であることがわかっている場合を除いて、スペースを避ける必要があります。

19
Chris Dodd

フォーマット文字列の空白文字(スペース、改行、水平および垂直タブ)は、入力内の任意の数の空白文字と一致します。
最初のケースでは

  scanf("%d  ",&j);

空白文字(WSC)' 'に遭遇すると、ユーザーが入力した\nを含むすべての空白を押して食べます。 Enter そしてそれは非WSCに入ることを期待するでしょう。この場合、プログラムはを押して終了します CtrlZ

6
haccks

scanf形式の空白文字は、isspaceで記述されている任意の数の空白文字と一致します。したがって、末尾のスペース、改行、タビュレーター、またはその他の空白文字がある場合は、戻る前にscanfによっても消費されます。

4
Sergey L.

違いは(明らかですが)異なるフォーマット文字列です。次の行を入力した場合:

_"3  "_

scanf()は正常に戻ります。それ以外の場合は、提供された入力によって異なります。 scanf()は基本的に空白(タブ、スペース、改行)をスキップし、入力ストリーム内の英数字値を検索します。これは末尾の空白であるため、を押すと、入力の最後に末尾の改行文字が集中します。 ENTER、したがって、それはほとんど重要ではありません。

scanf()は、提供された入力が、提供されたフォーマット文字列と完全に一致することを期待します。ただし、連続する空白文字は単一の空白文字に圧縮されます。これは、文字列処理に相当するsscanf()を使用してデータの大きな文字列を解析する場合に、非常に重要になります。

これをさらにテストするための良い演習は、次のようになります。

_#include<stdio.h>

int main(void)
{
   int a=0,b=0,c=0;

   printf("Enter values for A, B, C, in the format: \"A B  -  C\"\n");
   scanf("%d %d  -  %d", &a, &b, &c);

   printf("Values: A:%d, B:%d, C:%d\n", a, b, c);
}
_

その後、正しくフォーマットされたコンソール入力と誤ってフォーマットされたコンソール入力(スペースとハイフン)の両方を提供した後、これらの整数の値が何であるかを確認してください。これがいくつかの実行例です。最初は誤った入力を使用し、2番目は正しくフォーマットされた入力を使用しました。最初のケースでは、Cが設定されていないことに注意してください。これは、入力文字列とフォーマット文字列が一致しない場合、scanf()が予期しない動作を提供するためです。一般に、fgets()のようなものを使用してユーザーから入力の文字列を取得してから、さまざまな検索関数(strstr()、strch()、strcat、strcpyなど)を使用することをお勧めします。文字列を解析するには、scanf()を使用するよりもはるかに安全であり、ユーザーが誤ってまたは故意に間違いを犯さないと想定します。

_Enter values for A, B, C, in the format: "A B  -  C"
1 2 3
Values: A:1, B:2, C:0

Enter values for A, B, C, in the format: "A B  -  C"
1 2  -  3
Values: A:1, B:2, C:3
_

ここで、最後の実行について考えてみましょう。scanf()は、複数の連続する空白文字を1つの文字に圧縮するため、これらの最後の実行が実際に成功する理由は次のとおりです。

_Enter values for A, B, C, in the format: "A B  -  C"
1 2 - 3
Values: A:1, B:2, C:3

Enter values for A, B, C, in the format: "A B  -  C"
1     2           -                     3
Values: A:1, B:2, C:3
_
1
Cloud