0

私は自分自身の啓蒙のために K&R (第 2 版) に取り組んでおり、次の演習 (演習 2-2 p42) に遭遇しました。

Write a loop equivalent to the following without using && or ||:

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

これが私の解決策でした:

#include <stdio.h>

/* write a loop equivalent to the following without using && or ||

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

int main()
{
    int counter = 0, lim = 1000;
    int s[lim], c;

    while(counter < lim-1)
    {
        while((c = getchar()) != '\n')
        {
            while(c != EOF)
            {
                s[counter] = c;
            }
        }
        counter++;
    }   
    return 0;
}

インデントされたループを期待していたので、改行文字 ( '\n') または EOF 文字 (Ctrl-d私の Linux マシン上) に遭遇すると、プログラム全体が正常に終了することを期待していましたが、驚いたことに、うまくいきました。gdb を使用してデバッグしようとしましたが、まだ理解できませんでした。

何が表示されないのですか?

補遺: while ループが実行する一連のテストを逆にして、外側のループ if から抜け出すために if ステートメントを追加しようとしましたが、c == '\n'まだ表示されません! cまた、実行可能ファイルの実行中のコピーの pid に gdb をリンクしようとした場合でも、GDB を実行してコマンド ラインにテキストを入力し、同時に の値を出力しようとするのが困難です。この演習を解決するには、おそらく他の方法があることを認識しています。たとえば、OK_TO_EXECUTE3 つの条件がすべて満たされた場合にのみ true になるフラグまたは変数を設定するなどです。 . まさにこれが、私が K&R に戻って本をより徹底的に読み、演習を適切に解決する理由です。

コードをやり直しました(まだバグがあります!!!):

#include <stdio.h>

/* write a loop equivalent to the following without using && or ||

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

int main()
{
    int counter = 0, lim = 1000;
    int s[lim], c;



    while((c = getchar()) != EOF)
    { 
        if ( c == '\n')
            break;

        while(c != '\n')
        {
            while(counter < lim-1)
            {
                s[counter] = c;
                counter++;
            }
        }
    }   
    return 0;
}

解決しました!- おもう!やっと分かった気がします。私のやり直したソリューションに書かれている内部ループlimは、到達するまで無限にループするか、少なくともループします。break ステートメントを追加しましたが、解決策に向かっていると思います。

ただし、この問題で gdb を実行する方法にまだ取り組んでいます。コマンド ライン エントリとprintの値を入力しますc。gdb を実行可能ファイルの pid にリンクしても、期待どおりに動作しませんでした。gdb に関する別の質問も投稿しました。

4

3 に答える 3

2

オリジナルには存在しなかったループを追加しました...それは概念的にも論理的にも間違っています。最も明白な解決策は次を使用しますbreak

for (i = 0; i < lim-1; ++i)
{
    c = getchar();
    if (c == '\n')
        break;
    if (c == EOF)
        break;

    s[i] = c;
}

または、C に がないふりをしている場合は、次のようなことができます (またはが検出された場合、 は同じ値を持たないbreakため、これはまったく同等ではありません)。i'\n'EOF

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

または、パスカル アプローチを使用できます。

#include <stdbool.h>
...
i = 0;
bool more = i < lim-1;

while (more)
{
    c = getchar();
    if (c == '\n')
        more = false;
    else if (c == EOF)
        more = false;
    else
    {
        s[i++] = c;
        more = i < lim-1;
    }
}
于 2013-04-07T19:03:27.273 に答える
0

goto

i=0;
loop:
if( i >= lim - 1) goto end;
c = getchar();
if(c == '\n') goto end;
if(c == EOF) goto end;
s[i++] = c;
goto loop;
end:

なしbreakgotoおよび 1 つだけforで、まだ&&およびなし||

for (i=0; i < lim - 1 ? ((c=getchar()) == '\n' | c == EOF) == 0 : 0; ++i)
  s[i] = c;

アップデート

@Jim が指摘したように、 internal を使用して明示的に実行順序を設定する方が良い方法です?:

for (i=0; i >= lim - 1 ? 0 : (c=getchar()) == '\n' ? 0 : c != EOF; ++i)
  s[i] = c;
于 2019-08-14T11:51:06.143 に答える