私の目的は、の区切り文字scanf
を「\n
」に変更することです。使用してみscanf("%[^\n]s",sen);
ましたが、単一入力で正常に動作します。しかし、同じ行を複数の文のループ内に置くと、for
ガベージ値が返されます。
誰かが理由を知っていますか?
これが私のコードです:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
この(C99)コードを考えてみましょう:
#include <stdio.h>
int main(void)
{
char buffer[256];
while (scanf("%255[^\n]", buffer) == 1)
printf("Found <<%s>>\n", buffer);
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
それを実行して文字列を入力すると、「スペースTABTABタブが豊富なものなら何でも!」と表示されます。
Found <<absolutely anything with spaces tabs galore!>>
Failed on character 10 (
)
もちろん、 ASCII(UTF-8)1010は改行です。
これはあなたの問題を理解するのに役立ちますか?
この場合(単一行の場合)は機能しますが、配列の配列に複数行の入力を取りたい場合は失敗します。
scanf
そして、私はあなたのコードでどのように値を返すのかわかりませんか?
多くの(ほとんど?)経験豊富なCプログラマーが疫病を避けscanf()
、好む理由があります。fscanf()
正しく動作させるのは難しすぎます。を使用して、この代替手段をお勧めします。sscanf()
これは、と同じ実行を取得しませscanf()
んfscanf()
。
#include <stdio.h>
int main(void)
{
char line[256];
char sen[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%255[^\n]", sen) != 1)
break;
printf("Found <<%s>>\n", sen);
}
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
これは入力行を読み取り(これを使用しfgets()
てバッファオーバーフローが発生しないようにします(gets()
関数を聞いた場合は、コンピュータを金属とシリコンのプールに溶かします)、sscanf()
その行を処理するために使用します。これは改行を処理します。 、これは元のコードの失敗です。
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
問題:
scanf()
成功したかどうかはチェックしません。scanf()
scanf()
(ISO / IEC 9899:1999から)の定義は次のとおりです。
§7.19.6.4scanf関数
あらすじ
#include <stdio.h> int scanf(const char * restrict format, ...);
説明
2この関数は、の引数の前に引数を挿入した
scanf
場合と同等です。fscanf
stdin
scanf
戻り値
3
scanf
変換前に入力エラーが発生した場合、この関数はマクロEOFの値を返します。それ以外の場合、scanf
関数は割り当てられた入力項目の数を返します。これは、早期のマッチングが失敗した場合に、提供された数より少なくなるか、ゼロになる可能性があります。
最初のプログラムのループが終了すると、scanf()
EOFではなく0が返されたためであることに注意してください。
%[^\n]
改行をバッファに残します。%[^\n]%*c
改行文字を食べます。いずれの場合も、%[^\n]
任意の数の文字を読み取ることができ、バッファオーバーフローまたはそれ以上の事態を引き起こす可能性があります。フォーマット文字列を使用して%*[^\n]%*c
、ファイルからの入力行の残りの部分をゴブリングします。たとえば、数値を読み取り、行の残りを。で破棄できます%d%*[^\n]%*c
。これは、番号の後にコメントやラベルがある場合、またはその他の不要なデータがある場合に役立ちます。
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
getchar();
}
これがお役に立てば幸いです...実際には「\n」はストリーム入力バッファに残ります...Eeはscanfが再度呼び出される前にそれをフラッシュする必要があります
遅れていることはわかっていますが、久しぶりにCをテストしたところ、同じ問題が発生しました。
ここでの問題は、新しい行が次の反復の入力と見なされることです。
だから、これが私の解決策ですgetchar()
、入力ストリームの改行を破棄するために使用します:
char s[10][25];
int i;
for(i = 0; i < 10; i++){
printf("Enter string: ");
scanf("%s", s[i]);
getchar();
}
それが役に立てば幸い :)
scanf("%[^\n]", sen)
ループで使用しているときに発生する問題\n
は、入力バッファー内にとどまり、フラッシュされないことです。その結果、次回、同じ入力構文が使用されると、を読み取り、\n
それをnull入力と見なします。この問題に対処するためのシンプルで効果的な解決策は、次を使用することです。
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]%*c",sen);
printf("%s\n",sen);
}
%*c
\n
入力バッファ内の文字を削除します。