Reputation: 63
Relatively new to programming here, and I'm attempting to make my way through the second edition of K&R's "The C Programming Language." I've got the answer book to the exercises, and I got horribly stuck on Exercise 1-13, so I took a look at it to get an idea.
The task is this: "Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging."
And the code given in the answer book is the following:
#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;
}
I can understand the vast majority of it, but this particular section is giving me trouble:
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');
}
Now, I understand that the if function if((len = wl[i] * MAXHIST / maxvalue) <= 0)
is normalising the values in the array. What I don't understand is that it sets len = 1
. If len
is always 1
, shouldn't the putchar('*')
function only print one asterisk for any given value above 0?
Thanks in advance for your help.
Upvotes: 3
Views: 4868
Reputation: 56716
It might be easier to separate this if
into to parts.
len = wl[i] * MAXHIST / maxvalue;
if (len <= 0)
len = 1;
Now it should be clear that len
will be set to 1 only if its calculated value is not greater than 0.
Upvotes: 1
Reputation: 6332
It's saying this:
If we have a non-zero word length, but the normalized value is 0, we want to distinguish it from 0 by bumping it up to 1. Otherwise we use the normalized value (which is set in the if-statement itself -- not a good practice by most modern coding standards).
Upvotes: 1
Reputation: 114518
The condition
if((len = wl[i] * MAXHIST / maxvalue) <= 0)
len = 1;
Will never actually be less than zero since it is only applied to positive wl[i]
. As you supposed, len
is being normalized to a maximum number of asterisks. Notice that in the if
statement itself, (len = wl[i] * MAXHIST / maxvalue)
. So len
is just normalized. Only if the normalization truncates to zero (because that is what integer division does to numbers less than 1), will len
be set to 1
. This just ensures that at least one asterisk will be printed for the non-zero bars.
Upvotes: 1