K& R C答案书练习1.13(我不了解具体的构造)

时间:2013-12-26 13:06:01

标签: c

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

你好。我对编程有些新意。我之前已经阅读过这本书的一些内容,并在几年前看过另一本c教程。我又要经历了。我能够制作水平直方图。我在Stackoverflow上复制了输出与其他人一起看的方式。问题是我的程序打印一个“X”表示每个给定长度的单词数量,并且在C答案簿中,它会进行某种计算以显示每个给定长度的单词数量与其余部分的比率。词语的

首先是我的计划:

<code>

#include <stdio.h>
#define MAXLENGTH 10
#define BORDERLENGTH 50
int main()
{
int i, j, c, count;
int ccount[MAXLENGTH];

count = 0;

for (i = 0; i < MAXLENGTH; ++i)
    ccount[i] = 0;
while ((c = getchar()) != EOF){
    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <=  'Z'))
        ++count;
    else if (count != 0){
        ++ccount[count - 1];
        count = 0;
    }
}
for (i = 0; i < BORDERLENGTH; ++i)
    printf("-");
printf("\n");
count = 0;
for (i = 1; i <= MAXLENGTH; ++i){
    printf("%2d|", i);
    for (j = 0; j < ccount[count]; ++j )
        printf("x");
    ++count;
    printf("\n");
}
for (i = 0; i < BORDERLENGTH; ++i)
    printf("-");

getchar();
return 0;
} 
</code>

请注意,我已将一个单词定义为顺序中的任何数字或字母,而在它们之间或之后没有任何标点符号。

更重要的是,再次注意,我的程序输出x个“X”,其中x是每个给定字长的字数。考虑到练习的要求,我的输出方法是否会被认为是正确的?我甚至不太熟悉直方图。

现在这是C答案书中的程序:

<code>

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

getchar();
return 0;
}
</code>

请注意,此程序定义的单词与我的不同。它还包含溢出检查。无论如何,我困惑的部分是:     

if (wl[i] > 0){
    if ((len = wl[i] * MAXHIST / maxvalue) <= 0)
    len = 1;
}
else
    len = 0;
</code>

if语句中的计算是做什么的?这是其他地方使用的突出公式吗?

编辑:我实际上是从数学角度询问这个结构是做什么的,而不是从语法的角度来看。

我想知道这个公式是做什么的(wl [i] * MAXHIST / maxvalue),以及这实际上是如何创建单词之间的比率。

再次注意,输出根据每个给定单词长度的单词数量的比率创建一个星形,并且它不仅仅输出每个单词长度的每个单词的确切星数(在我的情况下为x)像我一样。

3 个答案:

答案 0 :(得分:2)

此计算规范化用于在直方图中显示它们的值。该程序的设置方式是始​​终将最高计数的单词显示为MAXHIST(即15)星号,而不管计算了多少单词。这样做是为了避免使用很长行的星号产生多行的直方图。

例如,如果您的文件包含200个单词,其中150个长度为4,其余50个长度为2,则直方图将显示四个字母单词的15个*个字符,并且两个字母单词的5 *个字符。如果你给那个程序一个2000字的文件,其中1500个有4个字母,500个有2个字母,那么生成的直方图就完全一样了。

请注意,如果以直接的方式应用此方案会产生不正确的结果:例如,如果您的文件包含3000个四个字母的单词且只有一个双字母单词,则规范化3000到15个字符将构成双字线星号小于一个字符宽。这就是为什么有一个if条件,如果一个计数非零,至少必须打印一个星号。

答案 1 :(得分:1)

只是计算wl[i] * MAXHIST / maxvalue并将其分配给len。然后检查len是否小于或等于0

很抱歉误解了你的观点。 数学计算是缩小0MAXHIST之间的值,这称为normalization。它很有用,因为maxvalue是不可预测的并且可能很大。标准化使它们处于极限状态。

wl[i] / maxvalue缩小01之间的值,您可以使用任何想要扩展的因子,在这种情况下MAXHIST

答案 2 :(得分:1)

它将结果缩放到适合直方图的最大幅度。 MAXHIST是直方图中元素的最大数量,maxvalue是遇到的最长元素的长度。因此,MAXHIST / maxvalue为您提供了一个缩放因子,当乘以当前单词的实际长度时,您会得到直方图中该条形图中要绘制的元素数量。