简体   繁体   English

Kernighan 和 Ritchie 练习 2-2 调试?

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

I am working through K&R (2nd edition) for my own edification and encountered the following exercise (exercise 2-2 p42):我正在通过 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;

This was my solution:这是我的解决方案:

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

I was expecting the indented loops and therefore the entire program to exit normally once it encountered a newline character ( '\\n' ) or an EOF character ( Ctrl-d on my Linux machine), but to my surprise it happily soldiers on.我期待缩进循环,因此一旦遇到换行符( '\\n' )或 EOF 字符(我的 Linux 机器上的Ctrl-d ),整个程序就会正常退出,但令我惊讶的是,它高兴地继续前进。 I tried to debug it using gdb but still could not figure it out.我尝试使用 gdb 调试它,但仍然无法弄清楚。

What am I not seeing?我没有看到什么?

Addendum: I tried to reverse the sequence of tests the while loops perform and added an if statement to break out of the outer loop if c == '\\n' but am still not seeing it!附录:我试图颠倒 while 循环执行的测试顺序,并添加了一个 if 语句来跳出外循环 if c == '\\n'但我仍然没有看到它! I am also having difficulty trying to run GDB entering text into the command line and simultaneously printing the value of c , even when I tried to link gdb to the pid of a running copy of the executable.我也很难尝试运行 GDB,在命令行中输入文本并同时打印c的值,即使我尝试将 gdb 链接到可执行文件的运行副本的 pid 也是如此。 I realize that there are probably other ways to solve this exercise, eg setting an OK_TO_EXECUTE flag or variable that is true only if all three conditions are met, but I am bothered by the fact that I seem unable to find the bug in a seemingly simple program.我意识到可能有其他方法来解决这个练习,例如设置一个OK_TO_EXECUTE标志或变量,只有当所有三个条件都满足时才为真,但我似乎无法在一个看似简单的程序。 This is precisely why I am returning to K&R to go through the book more thoroughly and to solve the exercises properly.这正是我回到 K&R 更彻底地阅读本书并正确解决练习的原因。

Redone code (still buggy!!!):重做代码(仍然有问题!!!):

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

SOLVED!解决了! - I think! - 我认为! I think I have finally figured it out.我想我终于想通了。 The inner loops as written in my redone solution will still loop endlessly or at lease till lim is reached.在我重做的解决方案中写入的内部循环仍将无休止地循环或至少直到达到lim为止。 I added break statements and think I am on my way to a solution.我添加了 break 语句,并认为我正在寻求解决方案。

I am still wrestling with how to run gdb on this problem though;不过,我仍在努力解决如何在这个问题上运行 gdb; enter the command line entries AND print the value of c .输入命令行条目并print c的值。 Linking gdb to the pid of the executable still did not work as expected.将 gdb 链接到可执行文件的 pid 仍然没有按预期工作。 I even posted a separate question regarding gdb.我什至发布了一个关于 gdb 的单独问题

but to my surprise it happily soldiers on但令我惊讶的是它快乐地坚持着

You have three nested loops.您有三个嵌套循环。 A newline would terminate one of the inner loops, while the outermost loop would happily carry on (until you've hit Enter lim times).换行符将终止内部循环之一,而最外层循环将继续进行(直到您按 Enter lim次)。

I can give you a hint: you probably shouldn't be using nested loops for this.我可以给你一个提示:你可能不应该为此使用嵌套循环。

You have added loops that didn't exist in the original ... that's conceptually and logically wrong.您添加了原始版本中不存在的循环……这在概念上和逻辑上都是错误的。 The most obvious solution uses break :最明显的解决方案是使用break

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

    s[i] = c;
}

Or if you're pretending that C doesn't have break , you can do something like this (this is not exactly equivalent because i doesn't have the same value if '\\n' or EOF is encountered):或者,如果您假装 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;
}

Or you can use the Pascal approach:或者您可以使用 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;
    }
}

With gotogoto

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:

Without break , goto and with just one for , still without && and ||没有breakgoto并且只有一个for ,仍然没有&&|| . .

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

Update更新

As noted by @Jim it's way better to set order of execution explicitly by using internal ?:正如@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