繁体   English   中英

Kernighan 和 Ritchie 练习 2-2 调试?

[英]Kernighan and Ritchie Exercise 2-2 Debugging?

我正在通过 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 字符(我的 Linux 机器上的Ctrl-d ),整个程序就会正常退出,但令我惊讶的是,它高兴地继续前进。 我尝试使用 gdb 调试它,但仍然无法弄清楚。

我没有看到什么?

附录:我试图颠倒 while 循环执行的测试顺序,并添加了一个 if 语句来跳出外循环 if c == '\\n'但我仍然没有看到它! 我也很难尝试运行 GDB,在命令行中输入文本并同时打印c的值,即使我尝试将 gdb 链接到可执行文件的运行副本的 pid 也是如此。 我意识到可能有其他方法来解决这个练习,例如设置一个OK_TO_EXECUTE标志或变量,只有当所有三个条件都满足时才为真,但我似乎无法在一个看似简单的程序。 这正是我回到 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 的单独问题

但令我惊讶的是它快乐地坚持着

您有三个嵌套循环。 换行符将终止内部循环之一,而最外层循环将继续进行(直到您按 Enter lim次)。

我可以给你一个提示:你可能不应该为此使用嵌套循环。

您添加了原始版本中不存在的循环……这在概念上和逻辑上都是错误的。 最明显的解决方案是使用break

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

    s[i] = c;
}

或者,如果您假装 C 没有break ,您可以执行以下操作(这并不完全等效,因为如果遇到'\\n'EOF i没有相同的值):

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;
}

或者您可以使用 Pascal 方法:

#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;
    }
}

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并且只有一个for ,仍然没有&&|| .

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

更新

正如@Jim 所指出的那样,最好使用内部?:显式设置执行顺序?:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM