当前位置:  开发笔记 > 编程语言 > 正文

K&R练习:我的代码有效,但感觉很臭; 建议清理?

如何解决《K&R练习:我的代码有效,但感觉很臭;建议清理?》经验,为你挑选了2个好方法。

我正在研究K&R书.我读的比我做的更进一步,主要是因为时间不够.我正赶上来,并完成了第1章的几乎所有练习,这是本教程.

我的问题是练习1-18.练习是:

编写程序以从输入行中删除尾随空白和制表符,并删除完全空行

我的代码(下面)做到了,并且有效.我的问题是我实施的修剪方法.感觉......错......不知何故.就像我在代码审查中看到C#中的类似代码一样,我可能会疯了.(C#是我的专长之一.)

任何人都可以提供一些关于清理它的建议 - 所述建议只能使用K&R第1章的知识.(我知道有很多方法可以使用完整的C库来清理它;我们'我只是在这里谈论第1章和基本的stdio.h.)另外,在给出建议时,你能解释它为什么会有用吗?(毕竟,我是在努力学习!谁比这里的专家更好地学习?)

#include 

#define MAXLINE 1000

int getline(char line[], int max);
void trim(char line[], char ret[]);

int main()
{
    char line[MAXLINE];
    char out[MAXLINE];
    int length;

    while ((length = getline(line, MAXLINE)) > 0)
    {
        trim(line, out);
        printf("%s", out);
    }

    return 0;
}

int getline(char line[], int max)
{
    int c, i;

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

    if (c == '\n')
    {
        line[i] = c;
        ++i;
    }

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

void trim(char line[], char ret[])
{
    int i = 0;

    while ((ret[i] = line[i]) != '\0')
        ++i;

    if (i == 1)
    {
        // Special case to remove entirely blank line
        ret[0] = '\0';
        return;
    }

    for (  ; i >= 0; --i)
    {
        if (ret[i] == ' ' || ret[i] == '\t')
            ret[i] = '\0';
        else if (ret[i] != '\0' && ret[i] != '\r' && ret[i] != '\n')
            break;
    }

    for (i = 0; i < MAXLINE; ++i)
    {
        if (ret[i] == '\n')
        {
            break;
        }
        else if (ret[i] == '\0')
        {
            ret[i] = '\n';
            ret[i + 1] = '\0';
            break;
        }
    }
}

编辑:我感谢我在这里看到的所有有用的提示.我想提醒大家,我仍然是一个带有C的n00b,特别是还没有达到指针.(记住关于K&R的Ch.1的一点 - 第1章没有指针.)我"有点"得到一些解决方案,但它们仍然是一个先进的触摸我...

我正在寻找的大多数是修剪方法本身 - 特别是我循环3次(感觉很脏)的事实.我觉得如果我只是一个更聪明的触摸(即使没有C的高级知识),这可能更清洁.



1> Eric Z Beard..:

如果你坚持第1章,这看起来对我很好.以下是我从代码审查的角度推荐的内容:

在C中检查相等性时,始终先将常量置于其中

if (1 == myvar)

这样你就不会意外地做这样的事情:

if (myvar = 1)

你无法在C#中使用它,但它在C中编译得很好并且可能是一个真正的调试恶魔.


它使代码的可读性降低.更好的解决方案是将编译器警告级别设置得足够高,以将其标记为警告.
我同意当你说"if 1等于myvar"时,它的可读性较差,不太自然.我没有意识到有一个编译器标志,我会更高兴.
我将再次进行投票:1 == var它与问题所指的"uglines"无关.我确实讨厌这个惯例 - 它让我为编译器做了工作,但我将它视为无关紧要和偏离主题.

2> Ferruccio..:

没有理由有两个缓冲区,您可以修改输入线

int trim(char line[])
{
    int len = 0;
    for (len = 0; line[len] != 0; ++len)
        ;

    while (len > 0 &&
           line[len-1] == ' ' && line[len-1] == '\t' && line[len-1] == '\n')
        line[--len] = 0;

    return len;
}

通过返回行长度,可以通过测试非零长度行来消除空行

if (trim(line) != 0)
    printf("%s\n", line);

编辑:假设ASCII编码,您可以使while循环更简单.

while (len > 0 && line[len-1] <= ' ')
    line[--len] = 0;

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有