arevans
arevans

Reputation: 63

The C Programming Language (K&R) - Exercise 1-13

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

Answers (3)

Andrei
Andrei

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

metal
metal

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

Mad Physicist
Mad Physicist

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

Related Questions