Exercise 1-13. Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.
The code I wrote:
#include <stdio.h>
#define MAXWLEN 35 /* assuming no word longer than 35 characters will appear in the input */
#define IN 0
#define OUT 1
int main()
{
int c, len, longest, state, chart[MAXWLEN];
for (int i = 0; i < MAXWLEN; ++i)
chart[i] = 0;
len = 0; /* length of the current word */
longest = 0; /* the longest word appearing in the input */
state = OUT; /* the state of being inside or outside a word */
while ((c = getchar()) != EOF)
{
if (c == ' ' || c == '\t' || c == '\n')
{
if (state == IN)
if (longest < ++chart[len-1])
longest = chart[len-1];
state = OUT;
len = 0;
}
else
{
state = IN;
++len;
}
}
char q[2][3] = {"", " "};
for (int i = longest; i; --i)
for (int j = (c = putchar('\n')) - c; j < MAXWLEN; ++j)
(i <= chart[j]) ? printf(" * ") : printf("%s", q[chart[j] > 0]);
putchar('\n');
for (int i = 1; i <= MAXWLEN; ++i)
if(chart[i-1])
printf("%2d ", i);
putchar('\n');
return 0;
}
1 Answer 1
for (int j = (c = putchar('\n')) - c;
is too clever to be good. You save one line of vertical space by the price of a reviewer's mental effort. Don't do this. Be explicit:putchar('\n'); for (int j = 0; ....)
is much more readable.
Ditto for
(i <= chart[j]) ? printf(" * ") : printf("%s", q[chart[j] > 0]);
As said in the comment, more functions please. There are clearly
init_chart
,fill_chart
, andprint_chart
(every loop deserves to be a function).getword
is also nice to have. It lets you avoid aIN/OUT
state machine.c == ' ' || c == '\t' || c == '\n'
is insufficient. At least there is\v
(vertical tab) and\f
(formfeed). Preferisspace
(don't forget to#include <ctype.h>
. (I know that it the K&R times it was not available)putchar
may fail. Be prepared.
getword()
. \$\endgroup\$