Print a character frequencies as a vertical graph I've been solving K&amp;R 1-14.

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

After several edits, it looks good to me now. But it's my first time to write a long code(it's long to me). I wonder if there is more simple and shorter code with the same logic or I wrote a bad style code or not. I also wonder whether my vertical graph looks good and well written.  Any suggestion will be so appreciated!
#include &lt;stdio.h&gt;

/*  print a graph of the frequencies of different characters */

#define GRAPH_HEIGHT 20

main()
{
    int af[26] = {0};
    int max = 1;
    int c;
    int i, j;

    /* get characters */
    while ((c = getchar()) != EOF) {
        if (c &gt;= 'a' &amp;&amp; c &lt;= 'z') 
            if (++af[c - 'a'] &gt; max) {
                ++max;
                continue;
            }
        if (c &gt;= 'A' &amp;&amp; c &lt;= 'Z')
            if (++af[c - 'A'] &gt; max)
                ++max;
    }

    /* calculate a relative frequencies */
    for (i = 0; i &lt; 26; ++i) {
        af[i] = GRAPH_HEIGHT * af[i] / max;
    }

    /* print characters on a graph */
    for (i = GRAPH_HEIGHT; i &gt; 0; --i) {
        printf(&quot;%2d |&quot;, i);
        for (j = 'a'; j &lt;= 'z'; ++j) {
            if (af[j - 'a'] == i) {
                printf(&quot; | &quot;);
                --af[j - 'a'];
            }
            else
                printf(&quot;   &quot;);
        }
        printf(&quot;\n&quot;);
    }

    printf(&quot;   &quot; &quot;*&quot; &quot;---------------&quot; &quot;---------------&quot; &quot;---------------&quot; &quot;---------------&quot; &quot;---------------&quot; &quot;---&quot;  &quot;\n&quot;);
    printf(&quot;   &quot;);
    for (i = 'a'; i &lt;= 'z'; ++i) {
        printf(&quot;%3c&quot;, i);
    }

    printf(&quot;\n&quot;);
}
This is a pretty good start.  You should be warned that K&amp;R describes a very early version of C, and the language has evolved considerably since the 1980s.
For example, we normally always write function declarations as prototypes, i.e. specifying the argument types, and we don't depend on the implicit int.  So:
int main(void)

Also, we don't need to declare all variables at the start of their scope any more; instead, we can declare them where they are initialised:
for (int i = 0;  i &lt; 26;  ++i)

Although the problem statement says that you should chart the frequency of different characters, we have implemented something different here, because we're only counting the characters between a and z and between A and Z.
While looking at that, there's a non-portable assumption in this code that 'Z'-'A' and 'z'-'a' are both 25.  That is true on ASCII systems, but definitely not true on EBCDIC systems, for example, where this code will index af outside its bounds.
You could solve this by declaring af differently:
#define AZ_COUNT ('z' - 'a' + 1)
unsigned int af[AZ_COUNT] = {0};

I think I would store counts of all different characters, and filter to just the alphabetic ones later (and use isalpha() for that, from &lt;ctype.h&gt;):
#include &lt;limits.h&gt;
unsigned int af[UCHAR_MAX+1] = {0};

That can make it easier to adapt the printing part (e.g. to show digits and punctuation characters) later.  (Note the use of unsigned int, too - a negative count makes no sense).
I think the printing part would be better if it didn't modify the counts.  We can ensure that if we split the counting and printing into separate functions:
void count_chars(FILE *in, unsigned int *frequencies);
void print_graph(FILE *out, const unsigned int *frequencies);

That const helps us write code that's more reusable.

With my changes, the code looks more like this (not perfect, but I hope it has some items to learn from):
#include &lt;ctype.h&gt;
#include &lt;limits.h&gt;
#include &lt;stdio.h&gt;

/*  print a graph of the frequencies of different characters */

#define GRAPH_HEIGHT 20

static void count_chars(FILE *in, unsigned int *frequencies)
{
    int c;
    while ((c = fgetc(in)) != EOF) {
        ++frequencies[(unsigned char)c];
    }
}

static void print_graph(FILE *out, const unsigned int *frequencies)
{
    /* start at 1 to avoid division by 0 later */
    unsigned int max = 1;
    for (unsigned int i = 0;  i &lt;= UCHAR_MAX;  ++i) {
        if (frequencies[i] &gt; max) {
            max = frequencies[i];
        }
    }

    /* print characters on a graph */
    for (unsigned int i = GRAPH_HEIGHT;  i &gt; 0;  --i) {
        fprintf(out, &quot;%2d |&quot;, i);
        for (int c = 0;  c &lt;= UCHAR_MAX;  ++c) {
            if (!isalnum(c)) { continue; }
            char bar = frequencies[c] &gt;= i * max / GRAPH_HEIGHT ? '|' : ' ';
            fprintf(out, &quot; %c &quot;, bar);
        }
        fputs(&quot;\n&quot;, out);
    }

    /* print the base line */
    fputs(&quot;   +&quot;, out);
    for (int c = 0;  c &lt;= UCHAR_MAX;  ++c) {
        if (!isalnum(c)) { continue; }
        fputs(&quot;---&quot;, out);
    }
    fputs(&quot;\n&quot;, out);
    for (int c = 0;  c &lt;= UCHAR_MAX;  ++c) {
        if (!isalnum(c)) { continue; }
        fprintf(stdout, &quot;%3c&quot;, c);
    }
    fputs(&quot;\n&quot;, out);
}

int main(void)
{
    unsigned int af[UCHAR_MAX+1] = {0};
    count_chars(stdin, af);
    print_graph(stdout, af);
}