5

私は現在、C の有名な本である The C Programming Language, 2Ed を勉強しています。そして、P.29 のコードを試してみると、getline 関数に何か問題があると思います。

int getline(char s[], int lim) {
    int c, i;

    for (i=0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; i++)
        s[i] = c;
    if (c == '\n') {
        s[i] = c;
        i++;
    }

    s[i] = '\0';
    return i;
}

for ループが終了したとき、i == lim-1そしてc == '\n'? s[lim]この場合、 「\0」に設定されるため、配列は境界外になると思います。

これは間違っていると思う人はいますか?ご協力いただきありがとうございます。

4

5 に答える 5

4

オペレーターには&&「アーリーアウト」セマンティクスがあります。これは、 ifi == lim-1の残りの条件が実行されないことを意味します。特に、c = getchar()は呼び出されません。

これは、この場合、cはループの最後の反復からの値を持つことを意味します。ループ条件には が含まれているためc != '\n'、この値はあり得ません'\n'(またはループは前回終了したはずです)。

limこれはが 1 より大きい限り真であり、これは関数の前提条件でなければなりません ( lim1 以下で関数を呼び出すと、 の初期化されていない値cが読み取られるため)。

于 2013-06-27T02:33:28.420 に答える
2

それでは、いくつかのケースを見てみましょう。

: の場合lim == 0、これは未定義の動作を行います。これが発生する場所は 2 つあります。

  • と を与えて for ループの繰り返しを実行しませi == 0c == undefined
  • 次に にアクセスc(c == '\n')ます。まだ定義された値がないため、未定義の動作です。
  • 次に、次のものでオーバーフローsすることにより、未定義の動作を再び引き起こします。s[i] = '\0';

もしもlim == 1

  • 条件が満たされないため、for ループは実行されません。
  • lim == 0値がないため、のように未定義の動作にヒットしcます。
  • 最後の行は正常に機能します。

lim == 2で、入力文字列が の場合"ab":

  • for ループは を取得'a'し、 に配置しsます。
  • for ループは次の反復で終了しますが、値は のcまま'a'です。
  • if 条件は失敗します。
  • null 文字の追加は正常に機能します。
  • そうs == "a\0"

lim == 2入力文字列が次の場合"a\n"(心配している場合):

  • for ループは を取得'a'し、 に配置しsます。
  • for ループは次の反復で終了しますが、値は のcまま'a'です。
  • if 条件は失敗します。
  • null 文字の追加は正常に機能します。
  • そうs == "a\0"
于 2013-06-27T02:37:10.877 に答える
0

あると同時にあるiことは不可能です。の場合はfalse になるため、次の文字を読み取ることはありません。だった場合、ループは になる前に終了していたでしょう。lim-1c'\n'i==lim-1i<lim-1c'\n'ilim-1

ループはこれと同等です:

i=0;
while (i<lim-1) {
    c = getchar();
    if (c==EOF) break;
    if (c=='\n') break;
    s[i] = c;
    i++;
}
于 2013-06-27T02:30:35.760 に答える
0

i < lim-1条件が真になるまでループを続け i == lim - 1ますs[lim -2]

于 2013-06-27T02:37:07.433 に答える
0

私はあなたが正しいと思います。-しかし、別の方法で。問題があった可能性があります。限界に達する必要がi==lim-1あり、 c は\n前のループからの値を持っていましたが、前のループc!='\n'が終了したため、これは発生しません。

これの問題lim <=1です。for ループは終了し、cまだ初期化されていないため、 での動作は未定義if (c == '\n')です。で修正できます

int c = 0;

他の人が述べたように、およびには追加の問題がlim = 0ありますs[i] = '\0';

于 2013-06-27T02:37:57.793 に答える