In the last article we describe how to print a horizontal histogram of the lenths of words. In this article we will describe how to print a vertical one.
Let's review how we draw the horizontal histogram:
Exercise1_13_1.c
#include <stdio.h>
#define OUT 0
#define IN 1
#define WORD_MAX_LENGTH 20
int main() {
int i, c, state, len, overLen;
int wordLength[WORD_MAX_LENGTH + 1];
state = OUT;
len = 0;
overLen = 0;
for (i = 0; i < WORD_MAX_LENGTH + 1; i++)
wordLength[i] = 0;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t' || c == '\n') {
wordLength[0]++;
if(state == IN) {
if (len > WORD_MAX_LENGTH)
overLen++;
else
++wordLength[len];
len = 0;
}
state = OUT;
} else {
if (state == OUT) {
len++;
state = IN;
} else
len++;
}
}
for (i = 1; i < WORD_MAX_LENGTH + 1; i++) {
printf("%2d - %2d : ", i, wordLength[i]);
while (wordLength[i]) {
printf("-");
wordLength[i]--;
}
printf("\n");
}
return 0;
}
We use a for loop in the last to print the histogram. And now we should change the following part to generate a vertical histogram:
This should be changed:
for (i = 1; i < WORD_MAX_LENGTH + 1; i++) {
printf("%2d - %2d : ", i, wordLength[i]);
while (wordLength[i]) {
printf("-");
wordLength[i]--;
}
printf("\n");
}
Before the histogram we should print the title line, otherwise no one can know what the bar in the diagram are meant.
for (i = 1; i < WORD_MAX_LENGTH + 1; i++)
printf("%2d-%2d ", i, wordLength2[i]);
This piece of code will let us seen some output like below:
1-41 2-29 3-13 4-12 5- 6 6- 6 7- 4 8- 3 9- 1 10- 2 11- 1 12- 1 13- 2 14- 0 15- 5 16- 3 17- 0 18- 1 19- 0 20- 0
1-41 means that there are 41 words with the length of 1.
And now let us start to print the vertical histogram. By now we already have had the statistical result which is stored in the array wordLength[]. Before we go into the for loop, we should notice that we shold properly handle the output width so that each bar column can align to its head line like 1-41 . The head line is printed as printf("%2d-%2d ", ...) , so its width is 6, not 5. If we want the bar shows in the middle of the alignment, we should put 2 spaces front and 3 spaces behind. like this:
printf(" | ")
Because in an usual vertical histogram, the column is birthed from the bottom to the top. And when we draw it on a papper, we always like to draw from the lower to the higher. But in a program, now we can only draw them from the top to the bottom, with the head line at the very end of the output. It is easy to think this roughly but hard to exactly express it, step by step.
So let us see what tools we have to solve this problem, for loop. Of course we will use that. It is easy to think that the for loop prints the histogram line by line. And how many lines will it print? In most case the output time should be equal to the max value in the array wordLength[]. Otherwise that max value cannot be fully showed. At this time we can see that the line number or row number should be the iteration and it has a top-line which is the max value in wordLength[] .
Now we have a final problem need to bu solved. The output principle. We should defined at which line, what kind of output should be. In another word, when we enter the nth line, at which column we should print a bar and at which column we should not. Notice this, each column always has a height, and when the line is above the height, there shoule be no bar at that column.
Include all these notes, let us see the output code:
// to find the height of the whole histogram
maxLen = 0;
for (i = 1; i < WORD_MAX_LENGTH + 1; i++)
if(maxLen < wordLength[i])
maxLen = wordLength[I];
// output the histogram
while (maxLen) {
for (i = 1; i < WORD_MAX_LENGTH + 1; i++) { // each iteration of this for loop will draw a line
if (wordLength[i] >= maxLen) {
printf(" | ");
wordLength[i]--;
} else {
printf(" ");
}
}
putchar('\n');
maxLen--;
}
Finally let's combine all of this and see the output:
//Exercise1_13_2.c
#include <stdio.h>
#define OUT 0
#define IN 1
#define WORD_MAX_LENGTH 20
int main() {
int i, c, state, len, overLen, maxLen;
int wordLength[WORD_MAX_LENGTH + 1];
state = OUT;
len = 0;
overLen = 0;
for (i = 0; i < WORD_MAX_LENGTH + 1; i++)
wordLength[i] = 0;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t' || c == '\n') {
wordLength[0]++;
if(state == IN) {
if (len > WORD_MAX_LENGTH)
overLen++;
else
++wordLength[len];
len = 0;
}
state = OUT;
} else {
if (state == OUT) {
len = 1;
state = IN;
} else
len++;
}
}
maxLen = 0;
for (i = 1; i < WORD_MAX_LENGTH + 1; i++)
if(maxLen < wordLength[i])
maxLen = wordLength[i];
//----------------------------Version1----------------------------------
// for (i = 1; i < WORD_MAX_LENGTH + 1; i++)
// printf("%2d-%2d ", i, wordLength[i]);
// putchar('\n');
// while (maxLen) {
// for (i = 1; i < WORD_MAX_LENGTH + 1; i++) {
// if (wordLength[i] > 0) {
// printf(" | ");
// wordLength[i]--;
// } else {
// printf(" ");
// }
// }
// putchar('\n');
// maxLen--;
// }
//----------------------------Version2----------------------------------
int wordLength2[WORD_MAX_LENGTH+1];
for (i = 1; i < WORD_MAX_LENGTH + 1; i++)
wordLength2[i] = wordLength[i];
while (maxLen) {
for (i = 1; i < WORD_MAX_LENGTH + 1; i++) {
if (wordLength[i] >= maxLen) {
printf(" | ");
wordLength[i]--;
} else {
printf(" ");
}
}
putchar('\n');
maxLen--;
}
for (i = 1; i < WORD_MAX_LENGTH + 1; i++)
printf("%2d-%2d ", i, wordLength2[i]);
putchar('\n');
return 0;
}
> ./Exercise1_13_2 < Exercise1_13_2.c
|
|
|
|
|
|
|
|
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
| | |
| | |
| | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
| | | | | |
| | | | | | |
| | | | | | |
| | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | | |
| | | | | | | | | | | | | | |
1-79 2-67 3-23 4-19 5- 7 6- 7 7- 6 8- 9 9- 4 10- 2 11- 0 12- 0 13- 1 14-10 15-11 16- 5 17- 0 18- 1 19- 0 20- 0
之所以选择用英文写是因为最近的工作恰好英文使用较多,所以想顺带在写博客的同时练习一下英文表达。可能会有部分语法不当的地方,敬请见谅。