Syntax rewrite, more docs
[tcpl.git] / ch1 / 13.c
blobabb84c63610328dac3dfb94dd77d21b33595b746
1 /*
2 * Example 1-13:
3 * Write a program to print a histogram of the lengths of words in its input.
4 * It is easy to draw the histogram with the bars horizontal;
5 * a vertical orientation is more challenging.
6 */
8 /*
9 * NOTE: Word separator tokens are isspace() and EOF.
11 * TODO: Split giant main() into functions?
12 * Make output graph even more flexible
13 * Eliminate all fixed graph output
14 * Support MAX_CHARS > 100
15 * Prove working (unit tests?)
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <ctype.h> /* for isspace() */
22 #define MAX_CHARS 10 /* [< 100] longer words placed in separate column */
23 #define BAR_CHAR '*' /* char used in bars */
24 #define BAR_SEP " " /* spaces between bars */
26 int
27 main(void)
30 * Occurance freqs of n-character words - words[n].
31 * words[MAX_CHARS+1] is for words > MAX_CHARS.
32 * Init all indices to 0.
34 int words[MAX_CHARS+1] = {0};
37 * Read input: Count char num in each word (n); store as words[n-1].
38 * Record last char as lastchar, only needed to check for newline.
40 int lastchar = EOF; /* last input char */
41 int chars = 0; /* chars in each word */
42 int c;
43 while ( (c = getchar()) ) {
44 if (!isspace(c) && c != EOF)
45 ++chars;
46 else {
47 // End of word/file; bump freq for last word's length.
48 if (chars <= MAX_CHARS)
49 ++words[chars-1];
50 else
51 ++words[MAX_CHARS]; /* long word, last col */
53 if (EOF == c)
54 break;
55 chars = 0; /* prep for next word */
56 lastchar = c; /* newlines are isspace() */
60 // Ensure we're on a new line before printing.
61 if (lastchar != '\n') {
62 putchar('\n');
65 // Longest bar needs first print; find it.
66 int longest_bar = 0;
67 for (int bar = 1; bar <= MAX_CHARS; ++bar)
68 if (words[longest_bar] < words[bar])
69 longest_bar = bar;
72 * Print main graph.
74 for (int y = words[longest_bar]; y > 0; --y) {
75 // Y-axis
76 printf("%4d | ", y);
78 // Bars
79 for (int bar = 0; bar < MAX_CHARS; ++bar) {
80 if (words[bar] >= y)
81 putchar(BAR_CHAR);
82 else
83 putchar(' ');
84 printf(BAR_SEP); /* bar separator */
86 putchar(BAR_CHAR);
87 putchar('\n'); /* avoid extra spaces */
90 // Print bottom border.
91 printf(" +-");
92 for (int bar = 0; bar < MAX_CHARS; ++bar)
93 printf("---");
94 printf("--\n"); /* avoid extra spaces */
96 // Print x-axis.
97 printf(" ");
98 for (int bar = 0; bar < MAX_CHARS; ++bar)
99 printf("%2d ", bar+1);
101 // Avoid extra spaces, and use '>' for last bar.
102 printf(">%d\n", MAX_CHARS);
104 return EXIT_SUCCESS;