开发者

Debugging a histogram in C

First question here on Stack Overflow so forgive me if this is offtopic or not per etiquette, but it seems like it should be fine. I'm doing exercise 1-13 in K&R, specifically printing a vertical histogram of the length of words in an input. Here's my code so far:

#include <stdio.h>

#define UPPER 10
#define ABOVE (UPPER+1)

main()
{
    int i, c, wcounter, j;
    int wlengths[ABOVE];
    int maxHistHeight;

    for (i = 0; i <= ABOVE; ++i)        /* Initialize everything to zero */
        wlengths[i] = 0;

    wcounter = maxHistHeight = 0;

    while((c = getchar()) != EOF){      /* Count word lengths */
        if (c != ' ' && c != '\t' && c != '\n'){
            ++wcounter;
        } 
        else if (wcounter >= ABOVE){
            ++wlengths[ABOVE];
            wcounter = 0;
        }else if (wcounter != 0){   
            ++wlengths[wcounter];
            wcounter = 0;
        }
    }

    for (i = 1; i <= ABOVE; ++i)       /*For testing purposes. Se开发者_如何学Goe if the array is holding correct values*/
        printf(" %d ",wlengths[i]);

    printf("\n");

    for (i = 1; i <= ABOVE; ++i)        /*Get the Maximum height for histogram */
        if (wlengths[i]>maxHistHeight)
            maxHistHeight = wlengths[i];

    printf("Histogram of length of words\n");   /* Print histogram */
    printf("----------------------------\n");

    for (i = maxHistHeight; i >= 0; --i){  /* Start at top of histogram, and go downwards */
        printf("\n");   
        for (j = 1; j <= ABOVE; ++j){      /*For each level of histogram, go through all the */
            if (i == 0 && j != ABOVE){     /*Arrays, and see if they contain an X in that level */
                printf(" %d ", j);
            }else if (i == 0 && j == ABOVE){
                printf(">%d",UPPER);
            }
            else if (wlengths[j]>=i){
                printf(" X ");
            }
            else{ 
                printf("   ");
            }    
        }           
    }
    printf("\n");    
}

I want to print a histogram of the length of words that are 1-10 letters long, and also that are greater than 10 letters. I want it to look like this:

Histogram of length of words

                               X 
       X  X                    X 
 1  2  3  4  5  6  7  8  9  10 >10

I'm using an array that is size 12 (not sure if this is how you would say it), with the 11th index holding all occurrences of words greater than 10 letters long. However, when I print out the histogram, it prints out an "X" in the >10 spot even if the word is only 10 letters long. So if I input this:

1234567890
123457890
1234567890

I get:

Histogram of length of words
----------------------------

                            X  X 
                         X  X  X 
 1  2  3  4  5  6  7  8  9  10 >10

I thought there must've been something with wrong with the way I was incrementing my array, so I printed the values of the array and got this:

 0  0  0  0  0  0  0  0  1  2  0 

which doesn't match what my histogram is printing. I appreciate any help!

UPDATE TO ORIGINAL QUESTION

So I fixed my array size to hold 12 elements: 10 for holding words with length 1-10, 1 for all words with length >10, and 1 for index 0, so that my index numbers match up with my word lengths. Before I had an array with just 11 elements,when I needed it to be 12, but when i printed out the values of my array, it displayed the correct values but during the printing of the histogram, it was incorrect. so given an input of this:

1234567890
1234567890
12345678901234567890
12345

I got this in the array (i'm printing from index 1 to index 11), and its correct:

 0  0  0  0  1  0  0  0  0  2  1 

But the histogram printout is different:

Histogram of length of words
----------------------------

                            X  X 
          X                 X  X 
 1  2  3  4  5  6  7  8  9  10 >10

Shouldn't they both be the same?


You array has dimension ABOVE (= 11) but you're iterating from 0 to ABOVE (inclusive) which is ABOVE + 1 (= 12) elements. The valid index range is only 0 to ABOVE - 1 so you're writing (and subsequently reading) beyond the end of the allocated array.

E.g. your initialisation loop should be:

for (i = 0; i < ABOVE; ++i)        /* Initialize everything to zero */
    wlengths[i] = 0;

I think you're probably getting muddled because C array indexes start at 0, while your histogram needs to represent word lengths from 1 to 10 and then 11 for word lengths > 10. You can approach this in one of two ways, either:

(a) adjust for the difference of 1, so words of length 1 go in bin 1, words of length 2 go in bin 1, etc, or

(b) allocate an additional element (i.e. make the array one element bigger than it needs to be) and simply don't use element 0. That way you don't have to worry about the offset of 1.


Lengths: If you declare an array as things[LEN] then the array can hold LEN things.

Indexes: But the array elements are indexed from 0 through LEN-1 and are accessed as things[0], things[1], ..., things[LEN - 1]

So you'll commonly see loops looking like this: for (i = 0; i < LEN; i++) { do something with thing[i]; }

The problem is that you want word lengths from 1 to 10, so you need to adjust the array indices accordingly.


Okay, I think I see what you guys meant. My array needs to be able to store 12 elements, assuming that I use indices 1-10 for word lengths 1-10, index 11 for all those word lengths >10, and finally, index 0 is discarded because I want the index numbers to line up with my word lengths. I set my array size to 12, or 2 more than my UPPER constant, and that seems to have done the trick. Here's my output:

Histogram of length of words
----------------------------

                            X    
             X              X  X 
 1  2  3  4  5  6  7  8  9  10 >10

given this input:

1234567890 
1234567890
12345
12345678901234567890
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜