首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kernighan和Ritchie练习2-2调试?

Kernighan和Ritchie练习2-2调试?
EN

Stack Overflow用户
提问于 2013-04-08 01:24:53
回答 2查看 795关注 0票数 0

我正在通过K&R (第二版)进行自我启迪,并遇到了以下练习(练习2-2 p42):

代码语言:javascript
复制
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;

这是我的解决方案:

代码语言:javascript
复制
#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来更彻底地阅读这本书,并适当地解决练习。

重做代码(仍有错误!):

代码语言:javascript
复制
#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;输入命令行条目并对c的值执行print操作。将gdb链接到可执行文件的pid仍然无法按预期工作。我甚至发布了一个关于gdb的separate question

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-08 03:03:27

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

代码语言:javascript
复制
for (i = 0; i < lim-1; ++i)
{
    c = getchar();
    if (c == '\n')
        break;
    if (c == EOF)
        break;

    s[i] = c;
}

或者,如果你假装C没有break,你可以这样做(这并不完全等同,因为如果遇到'\n'EOFi的值就不一样了):

代码语言:javascript
复制
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方法:

代码语言:javascript
复制
#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;
    }
}
票数 2
EN

Stack Overflow用户

发布于 2019-08-14 19:51:06

使用goto

代码语言:javascript
复制
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:

没有break,没有goto,只有一个for,仍然没有&&||

代码语言:javascript
复制
for (i=0; i < lim - 1 ? ((c=getchar()) == '\n' | c == EOF) == 0 : 0; ++i)
  s[i] = c;

更新

正如@Jim所指出的,通过使用内部?:显式地设置执行顺序是更好的方法

代码语言:javascript
复制
for (i=0; i >= lim - 1 ? 0 : (c=getchar()) == '\n' ? 0 : c != EOF; ++i)
  s[i] = c;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15865404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档