/* File: word.c -- zu Kap. 2.9 Beispiele (aus Kernighan)
   Fkt.: Eingabe eines Files, Ordnen und Zaehlen der Worte in
	 einem binaeren Baum und Ausgabe von Anzahl je Wort */
#include <stdio.h>

#define LETTER 'a'
#define MAXWORD 20

/* Header fuer tree search */

struct tnode {
	char *word;		/* Pointer to next word */
	int count;		/* number of occurrences */
	struct tnode *left;	/* left child */
	struct tnode *right;	/* right child */
};

main()		/* word frequency count */
{
	struct tnode *root, *tree();
	char word[MAXWORD];
	int t;

	root = NULL;
	while ((t = getword(word, MAXWORD)) != EOF)
		if (t == LETTER)
			root = tree(root,word);
	treeprint(root);
}

struct tnode *tree(p, w)	/* install w at or below p */
struct tnode *p;
char *w;
{
	struct tnode *talloc();
	char *strsave();
	int cond;

	if (p == NULL) { 	/* a new word was arrived */
		p = talloc();	/* make a new node */
		p->word = strsave(w);
		p->count = 1;
		p->left = p->right = NULL;
	} else if ((cond = strcmp(w, p->word)) == 0)
		p->count++;	/* repeated word */
	else if (cond < 0)	/* lower goes into left subtree */
		p->left = tree(p->left,w);
	else			/* greater into right subtree */
		p->right = tree(p->right, w);
	return(p);
}

treeprint(p)		/* print tree p recursively */
struct tnode *p;
{
	if (p != NULL) {
		treeprint(p->left);
		printf("%4d %s\n", p->count, p->word);
		treeprint(p->right);
	}
}
#include <ctype.h>
#define MAX 5000
#define BUFSIZE 100

getword(w, lim)		/* get next word from input */
char *w;
{	int c, t;
	if (! isalpha (c = *w++ = getch())) {
		*w = '\0';
		return(c);
	}
	while (--lim > 0 ) {
		if (! isalnum (c = *w++ = getch())) {
			ungetch(c);
			break;
		}
	}
	*(w-1) = '\0';
	return(LETTER);
}
char buf[BUFSIZE];	/* buffer for ungetch */
int bufp = 0;		/* next free position in buf */
getch()			/* get next character */
{
	return(bufp > 0 ? buf[--bufp] : getchar());
}
ungetch(c)		/* push character back on input */
int c;
{	if (bufp > BUFSIZE)
		fprintf(stderr, "ungetch: too many characters\n");
	else
		buf[bufp++] = c;
}
struct tnode tf[MAX];
int ti = 0;
char wf[MAX][MAXWORD];
int wi;
struct tnode *talloc()
{
	if (++ti >= MAX) {
		fprintf(stderr, "talloc: too many words - abort\n");
		exit(1);
	}
	return( &tf[ti] );
}
char * strsave(s)
char *s;
{	int i;
	char *p;
	if (++wi >= MAX) {
		fprintf(stderr, "talloc: too many words - abort\n");
		exit(1);
	}
	strcpy( wf[wi], s);
	return( wf[wi] );
}
