#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define DEBUG
#if defined(DEBUG)
#include "xmalloc.h"
#else
#define xmalloc(x, y) malloc(x)
#define xfree(x, y) free(x)
#define xrealloc(x, y, z) realloc(x, y)
#define xmallocdump()
#endif
/* for xmalloc.c */
#define ID_GETLINE 1004
#define ID_NODE 1005
#define ID_WORD 1006
struct node {
char *data;
struct node *left, *right;
};
void *push(struct node **root, void *data, int (*cmp)(void *, void *)) {
struct node *p;
int c;
if (!*root) {
if ((p = xmalloc(sizeof(struct node), ID_NODE)) == 0) {
fprintf(stderr, "cannot allocate enough memory(struct node), aborted\n");
exit(-1);
}
p->data = data;
p->left = p->right = 0;
*root = p;
return data;
}
if ((c = (*cmp)(data, (*root)->data)) != 0) {
if ((*cmp)(data, (*root)->data) < 0) {
return push(&((*root)->left), data, cmp);
} else {
return push(&((*root)->right), data, cmp);
}
} else {
return (*root)->data;
}
}
void *pop(struct node **root) {
struct node *p;
void *data;
if (*root == 0) {
return 0;
}
if ((*root)->left) {
data = pop(&((*root)->left));
return data;
}
p = *root;
data = p->data;
*root = p->right;
xfree(p, ID_NODE);
return data;
}
void release(struct node **root, void (*f)(void *)) {
if (*root != 0) {
release(&((*root)->left), f);
release(&((*root)->right), f);
f((*root)->data);
xfree(*root, ID_NODE);
*root = 0;
}
}
void *mostleft(struct node *root) {
if (root == 0)
return 0;
if (root->left == 0)
return root->data;
else
return mostleft(root->left);
}
void *mostright(struct node *root) {
if (root == 0)
return 0;
if (root->right == 0)
return root->data;
else
return mostright(root->right);
}
#define BUFFSIZE 3 /* >= 2 */
char *mygetline(FILE *fp) {
static char inbuff[BUFFSIZE];
char *outbuff_malloc, *tmpbuff;
char *p, *r;
int fEOL;
if ((outbuff_malloc = xmalloc(1, ID_GETLINE)) == NULL) {
return NULL;
}
*outbuff_malloc = '\0';
fEOL = 0;
do {
r = fgets(inbuff, BUFFSIZE, fp);
if (r == NULL)
break;
for (p = inbuff; *p != '\0'; p++)
;
if (*(p - 1) == '\n')
fEOL = 1;
if ((tmpbuff = xrealloc(outbuff_malloc, strlen(outbuff_malloc) + strlen(inbuff) + 1, ID_GETLINE)) == NULL) {
xfree(outbuff_malloc, ID_GETLINE);
return NULL;
}
strcat(tmpbuff, inbuff);
outbuff_malloc = tmpbuff;
} while (!fEOL);
if (strlen(outbuff_malloc) > 0) {
for (p = outbuff_malloc; *p != '\0'; p++)
;
if (*(p - 1) == '\n')
*(p - 1) = '\0';
return outbuff_malloc;
}
xfree(outbuff_malloc, ID_GETLINE);
return NULL;
}
int isSep(char *p) { return (*p == ' ' || *p == '\t' || *p == '\n'); }
char *cutToken(char *p, char **s) {
char *t, *q;
int flag;
if (p == 0)
return 0;
flag = 0;
for (q = p; isSep(q) && *q != '\0'; q++)
;
if (*q == '\0')
return 0;
t = q;
q++;
for (; !isSep(q) && *q != '\0'; q++)
;
if (*q == '\0')
flag = 1;
*q = '\0';
if (flag)
*s = 0;
else
*s = q + 1;
return t;
}
void reg(char *s) {
char *p;
for (p = s; *p != 0; p++)
if (isalpha(0xff & *p) && *p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
}
struct word {
int n;
char w[1];
};
void release_word(struct word *p) {
xfree(p, ID_WORD);
}
int cmp1(struct word *p, struct word *q) { return strcmp(p->w, q->w); }
int cmp2(struct word *p, struct word *q) { return strlen(p->w) - strlen(q->w); }
int main() {
#define N 1024
static char filename[N];
FILE *fp;
char *p, *q, *r;
struct word *t, *s;
struct node *dic = 0;
struct node *dic2 = 0;
printf("filename: "); fgets(filename, N, stdin);
for (p = filename; *p != '\0'; p++)
;
--p;
while (*p == '\n' || *p == '\r')
--p;
p++;
*p = '\0';
if ((fp = fopen(filename, "r")) == 0) {
fprintf(stderr, "cannot open the file: %s aborted.\n", filename);
exit(1);
}
while ((p = mygetline(fp)) != 0) {
q = p;
while ((r = cutToken(q, &q)) != 0) {
if ((t = xmalloc(sizeof(struct word) + strlen(r), ID_WORD)) != 0) {
strcpy(t->w, r);
reg(t->w);
t->n = 1;
if ((s = push(&dic, t, (int (*)(void *, void *))cmp1)) != t) {
s->n++;
xfree(t, ID_WORD);
}
}
}
xfree(p, ID_GETLINE);
}
fclose(fp);
t = mostleft(dic); printf("the first word: %s\n", t->w);
t = mostright(dic); printf("the last word: %s\n", t->w);
while ((t = pop(&dic)) != 0)
if ((s = push(&dic2, t, (int (*)(void *, void *))cmp2)) != t) {
xfree(t, ID_WORD);
}
t = mostright(dic2); printf("the longest word: %s\n", t->w);
release(&dic, (void (*)(void *))release_word);
release(&dic2, (void (*)(void *))release_word);
xmallocdump();
return 0;
}
/* end */