【问题标题】:The C Programming Language (K&R) - Exercise 1-13C 编程语言 (K&R) - 练习 1-13
【发布时间】:2014-02-07 16:12:44
【问题描述】:

这里的编程相对较新,我正在尝试通过第二版 K&R 的“C 编程语言”。我有练习题的答案,但我在练习 1-13 上被卡住了,所以我看了一下它以获得一个想法。

任务是这样的:“编写一个程序来打印其输入中单词长度的直方图。用水平条绘制直方图很容易;垂直方向更具挑战性。”

而答卷中给出的代码如下:

#include <stdio.h>

#define MAXHIST 15  
#define MAXWORD 11  
#define IN 1        
#define OUT 0      


main()
{

    int c, i, nc, state;
    int len;
    int maxvalue;
    int ovflow;
    int wl[MAXWORD];

    state = OUT;
    nc = 0;         
    ovflow = 0;

    for (i = 0; i < MAXWORD; i++)
        wl[i] = 0;  

    while ((c = getchar()) != EOF)
    {
        if(c == ' ' || c == '\n' || c == '\t')
        {
            state = OUT;            
            if (nc > 0)
            {
                if (nc < MAXWORD)   
                    ++wl[nc];       
                else
                    ++ovflow;       
            }                       
            nc = 0;                 
        }
        else if (state == OUT)
        {
            state = IN;             
            nc = 1;                 
        }
        else
            ++nc;                   
    }

    maxvalue = 0;
    for (i = 1; i < MAXWORD; ++i)
    {
        if(wl[i] > maxvalue)
            maxvalue = wl[i];       
    }

    for(i = 1; i < MAXWORD; ++i)
    {
        printf("%5d - %5d : ", i, wl[i]);
        if(wl[i] > 0)
        {
            if((len = wl[i] * MAXHIST / maxvalue) <= 0)
                len = 1;
        }
        else
            len = 0;

        while(len > 0)
        {
            putchar('*');
            --len;
        }
        putchar('\n');
    }

    if (ovflow > 0)
        printf("There are %d words >= %d\n", ovflow, MAXWORD);

    return 0;

}

我可以理解其中的绝大多数,但是这个特定的部分给我带来了麻烦:

for(i = 1; i < MAXWORD; ++i)
{
    printf("%5d - %5d : ", i, wl[i]);
    if(wl[i] > 0)
    {
        if((len = wl[i] * MAXHIST / maxvalue) <= 0)
            len = 1;
    }
    else
        len = 0;

    while(len > 0)
    {
        putchar('*');
        --len;
    }
    putchar('\n');
}

现在,我了解到 if 函数 if((len = wl[i] * MAXHIST / maxvalue) &lt;= 0) 正在规范化数组中的值。我不明白的是它设置了len = 1。如果len 始终为1,那么putchar('*') 函数不应该只为大于0 的任何给定值打印一个星号吗?

提前感谢您的帮助。

【问题讨论】:

  • 程序流到达len = 1;的唯一时间是当分母maxvalue变得大于分子wl[i] * MAXHIST 时,由于特定字长的高频率。 a a a a a a a a a a a a a a a a so(16 个字长为 1,1 个字长为 2)就是这种情况的一个例子。

标签: c


【解决方案1】:

条件

if((len = wl[i] * MAXHIST / maxvalue) <= 0)
        len = 1;

实际上永远不会小于零,因为它只应用于正数wl[i]。如您所想,len 被标准化为最大数量的星号。请注意,在 if 语句本身中,(len = wl[i] * MAXHIST / maxvalue)。所以len 只是标准化。只有当归一化截断为零(因为这是整数除法对小于 1 的数字所做的),len 才会被设置为1。这只是确保将为非零条打印至少一个星号。

【讨论】:

    【解决方案2】:

    它是这样说的:

    如果我们有一个非零字长,但归一化值是 0,我们希望通过将其增加到 1 来区分它与 0。否则我们使用归一化值(在 if 语句本身中设置) -- 按照大多数现代编码标准来说,这不是一个好的做法)。

    【讨论】:

      【解决方案3】:

      将这个if 分成几部分可能更容易。

      len = wl[i] * MAXHIST / maxvalue;
      if (len <= 0)
          len = 1;
      

      现在应该清楚len 只有在其计算值不大于 0 时才会设置为 1。

      【讨论】:

      • 感谢您的快速回复。不过,还有一件小事让我很困惑。为什么 else 语句将len 设置为0?我可能只是在这里有点密集,但似乎 len 将始终设置为 0 或 1?
      • @arevans,不,并非总是如此。如果wl[i] 大于0,则将计算len。如果它低于 0,则 len 将变为 1。最后,如果 wl[i] 为 0,len 将为 0。您可能希望选择每种情况(例如 -1、0、1)并手动检查代码看看会发生什么
      • 啊,我看到了!在 if 语句之外设置 len 当然更容易。我将它作为语句中的一个单独的条件来阅读,而不是变量赋值和后续测试。非常感谢!
      猜你喜欢
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多