3

ここでの単純なコードでは、期待される出力が得られません。

#include<stdio.h>

int main()
{
   char buf[1024];
   while(1)
   {
      fgets(buf,strlen(buf),stdin);
      printf("%s",buf);
      printf("hello");
   }
}

上記のコードでは、キーボードから入力した文字列を同じように出力してから、こんにちは。私が知っているように、 fgets() は、キーボードから文字列を入力して ENTER を押すまでブロック関数であり、その時までプログラムをブロックします。したがって、実行すると、次のようになります

$ ./a.out
I input some text here <ENTER>
I input some text here 
hello

しかし、実際に出力されているのは、端末に出力された「こんにちは」の無限ループです。fgets() がプログラムをブロックしないのはなぜですか? 何か案が?

4

4 に答える 4

6

問題はstrlen(buf)、buf [0]がたまたま0であったために0が返されることです(保証されていません)。sizeof(buf)代わりに使用する必要があります:

fgets(buf,sizeof(buf),stdin);
于 2012-10-05T06:55:29.630 に答える
2

fgets()呼び出しを次のように変更します。

fgets(buf,sizeof(buf),stdin)
//        ^^^^^^

初期化されていないものを呼び出すstrlen()と、buf誰が何を知っているかが返されます。strlen()戻ってくる可能性があり0、その場合fgets()はすぐに戻ります。

于 2012-10-05T06:54:56.650 に答える
2

これstrlenは、バッファがおそらくゼロであるためです。代わりに使用する必要がsizeofあります。これにより、配列に含まれる文字列の長さ (ここでは不定) ではなく、配列のサイズ (1024) が得られます。

呼び出しがまったくブロックされていないため、特定のケース ( ) ではおそらくサイズゼロの文字列です。実際には、標準が次のように述べているため、長さを 1 にすることもできます。*buf == '\0'fgets

fgets 関数は、stream が指すストリームから s が指す配列に、n で指定された文字数より最大で 1 つ少ない文字を読み取ります。改行文字 (保持されます) の後またはファイルの終わりの後、追加の文字は読み取られません。ヌル文字は、配列に読み込まれた最後の文字の直後に書き込まれます。

実際には、初期化されていないローカル変数には何でもbuf含まれている可能性があるため、それに依存するのは賢明ではありません (null ターミネータがまったく含まれていない場合は、実行時にコアをダンプしていることに気付くかもしれません)。最後から)。strlen

実証済みの入力機能が必要な場合は、こちらを参照してください。バッファ オーバーフロー保護、プロンプト表示、末尾の改行の削除、長すぎる場合の残りの行のクリアがあります。この回答をより自己完結型にするために、以下のコードを複製します。

#include <stdio.h>
#include <string.h>

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}
于 2012-10-05T06:56:21.713 に答える
0

次のように、strlen(buf)の代わりにsizeof(buf)を使用する必要があります。

 fgets(buf,sizeof(buf),stdin); 

または直接:

 fgets(buf,1024,stdin);
于 2012-10-05T07:02:02.253 に答える