《C程序设计语言》第二版 Exercise1-14

Exercise 1-14. Write a program to print a histogram of the frequencies of different characters in its input.

This Exercise is much like the exercise before. Let us solve it step by step.

First of course we need an array to store the occurrence number of every character. If you have ever known the ACII codes, it is easy to see that at this time we can store the occurrnece nubers in the array with length of 128. So lets do this in the main() function.

/*
---------------Before Main Function----------------
*/
#define ASCII_NUM 128

/*
---------------In Main Function--------------------
*/

    int i, c, maxLen1, maxLen2;
    int character[ASCII_NUM], character2[ASCII_NUM];

    for (i = 0; i < ASCII_NUM; i++)
        character[i] = 0;

    while ((c = getchar()) != EOF) {
        character[c]++;
    }

    for (i = 0; i < ASCII_NUM; i++)
        character2[i] = character[I];

    /*
    More code ...
    */

We will see later why we need two arrays. And now let's constrate on how to draw the histogram, vertical version.

There is an obvious problem is that if you try to draw all elemets using one graph, the output window may fold your result, depending on your screen size. First fold the graph of bar and then the axis, which will be hard to read. It is a good idea to divide the histogram into many parts. For me, 2 part will suit my screen. First part is from NULL to character 'Z'. Second part is from character '[' to del.

To draw the first part, we should frist know how many lines we have to output, which is also the hight of histogram.

//Part1
    maxLen1 = 0;
    for (i = 0; i <= 'Z'; i++)
        if (maxLen1 < character[i])
            maxLen1 = character[i];

Then we can darw the graph row by row. And use '*' to from every bar. When we draw the n-th row, we need to walk through the character array and check whether we should put a '*' at this corresponding place: If the line we draw is highter than some value in array - e.g. : n > charachter['A'], than we should not draw a '*' at this place because the bar of 'A' is lower than this hight. In the other case we put a '*'.

    while (maxLen1) {
        for (i = 1; i < 'Z'; i++) {
            if (character[i] > 0 ) {
                if (character[i] >= maxLen1){
                    printf("*  ");// add a space here for easier understanding
                    character[i]--;
                } else {
                    printf("   ");
                }
            }
        }
        putchar('\n');
        maxLen1--;
    }

Finally we should add a axis for the graph. Because we have already used character[] for graph printing, the value in character[] are all 0. So we use the substitute array character2[] here.

// print character
    for (i = 0; i <= 'Z'; i++) {
        if (character2[i] > 0){
            if (i == ' ')
                printf("\\b ");
            else if (i == '\t')
                printf("\\t ");
            else if (i == '\n')
                printf("\\n ");
            else
                printf("%c  ", i);
        }
    }
    putchar('\n');

Now we have finished the first part of histogram. For second part, use the same pattern. And finally we can see the whole program as below:

#include <stdio.h>

#define ASCII_NUM 128

int main() {
    int i, c, maxLen1, maxLen2;
    int character[ASCII_NUM], character2[ASCII_NUM];

    for (i = 0; i < ASCII_NUM; i++)
        character[i] = 0;

    while ((c = getchar()) != EOF) {
        character[c]++;
    }

    for (i = 0; i < ASCII_NUM; i++)
        character2[i] = character[i];

    maxLen1 = 0;
    for (i = 0; i <= 'Z'; i++)
        if (maxLen1 < character[i])
            maxLen1 = character[i];

    while (maxLen1) {
        for (i = 1; i < 'Z'; i++) {
            if (character[i] > 0 ) {
                if (character[i] >= maxLen1){
                    printf("*  ");
                    character[i]--;
                } else {
                    printf("   ");
                }
            }
        }
        putchar('\n');
        maxLen1--;
    }
    
    for (i = 0; i <= 'Z'; i++) {
        if (character2[i] > 0){
            if (i == ' ')
                printf("\\b ");
            else if (i == '\t')
                printf("\\t ");
            else if (i == '\n')
                printf("\\n ");
            else
                printf("%c  ", i);
        }
    }
    putchar('\n');
    
    maxLen2 = 0;
    for (i = 'Z' + 1; i < ASCII_NUM; i++)
        if (maxLen2 < character[i])
            maxLen2 = character[i];
    
    while (maxLen2) {
        for (i = 'Z' + 1; i < ASCII_NUM; i++) {
            if (character[i] > 0 ) {
                if (character[i] >= maxLen2){
                    printf("*  ");
                    character[i]--;
                } else {
                    printf("   ");
                }
            }
        }
        putchar('\n');
        maxLen2--;
    }

    for (i = 'Z' + 1; i < ASCII_NUM; i++) {
        if (character2[i] > 0){
            if (i == ' ')
                printf("\\b ");
            else if (i == '\t')
                printf("\\t ");
            else if (i == '\n')
                printf("\\n ");
            else
                printf("%c  ", i);
        }
    }
    putchar('\n');
    
    return 0;
}

And you can see output like this:

> ./Exercise1_14 < test.txt      
      *              
*     *              
*  *  *  *           
*  *  *  *  *  *  *  
\n ,  .  /  1  2  3  
*              
*              
*     *        
*     *  *  *  
*  *  *  *  *  
a  b  d  f  s  

 End.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值