#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define xmalloc malloc
#define xfree free
#define xrealloc realloc
#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)) == 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)) == NULL) {
xfree(outbuff_malloc);
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);
return NULL;
}
struct node {
void *data;
struct node *left;
struct node *right;
};
void *push(struct node **root, void *data, int (*cmp)(void *, void *)) {
struct node *p;
int c;
if (!*root) {
p = xmalloc(sizeof(struct node));
p->data = data;
p->left = p->right = NULL;
*root = p;
return data;
}
if ((c = (*cmp)(data, (*root)->data)) != 0) {
if (c < 0) {
return push(&((*root)->left), data, cmp);
} else {
return push(&((*root)->right), data, cmp);
}
}
return (*root)->data;
}
void *pop(struct node **root) {
struct node *p;
void *data;
if (*root == NULL) {
return NULL;
}
if ((*root)->left) {
data = pop(&((*root)->left));
return data;
}
assert((*root)->left == NULL);
p = *root;
data = p->data;
*root = p->right;
xfree(p);
return data;
}
/*------------------------------------------------------------*/
struct data1 {
char *groupe;
double j, m, e;
int n;
};
int cmp_const1(char *a, char *b) {
return 1;
}
void cut_tsv(char *line, struct node **root) {
int s;
char *p, *q, *col, c;
p = q = line;
do {
c = *p;
if (c == '\t' || c == '\0') {
*p = '\0';
s = strlen(q);
if (s > 0) {
col = xmalloc(s + 1);
strcpy(col, q);
} else
col = NULL;
push(root, col, (int (*)(void *, void *))cmp_const1);
p++;
q = p;
} else {
p++;
}
} while (c);
}
void usr_analyze_tsv(struct node **root, char **col1, char **col2, int *col3, int *col4, int *col5) {
int i;
char *p;
for (i = 0; i < 5; i++) {
if ((p = pop(root)) != NULL) {
switch (i) {
case 0:
*col1 = p;
break;
case 1:
*col2 = p;
break;
case 2:
*col3 = atoi(p);
xfree(p);
break;
case 3:
*col4 = atoi(p);
xfree(p);
break;
case 4:
*col5 = atoi(p);
xfree(p);
break;
}
} else {
switch (i) {
case 0:
*col1 = NULL;
break;
case 1:
*col2 = NULL;
break;
case 2:
*col3 = -1;
break;
case 3:
*col4 = -1;
break;
case 4:
*col5 = -1;
break;
}
}
}
}
void release_tsv(struct node **root) {
char *p;
while ((p = pop(root)) != NULL)
xfree(p);
}
int cmp_data1(struct data1 *p, struct data1 *q) {
if (!(p->groupe) || !(q->groupe))
return 0;
return strcmp(p->groupe, q->groupe);
}
void sum(struct node **root, char *line) {
struct node *tsvroot;
struct data1 *p, *q;
int j, m, e;
char *col1, *col2;
tsvroot = NULL;
cut_tsv(line, &tsvroot);
usr_analyze_tsv(&tsvroot, &col1, &col2, &j, &m, &e);
release_tsv(&tsvroot);
xfree(col1);
if (col2 == NULL || j < 0 || m < 0 || e < 0)
return;
p = xmalloc(sizeof(struct data1));
if (!p) {
fprintf(stderr, "cannot allocate enough memory.(analyze: struct data1)\n");
exit(-1);
}
p->groupe = col2;
p->n = 1;
p->j = j;
p->m = m;
p->e = e;
if ((q = push(root, p, (int (*)(void *, void *))cmp_data1)) != p) {
/*printf("analyze/push main/sol\n");*/
xfree(col2);
xfree(p);
(q->n)++;
(q->j) += j;
(q->m) += m;
(q->e) += e;
} else {
/* printf("analyze/push main/dup\n");*/
}
}
void makeInfoCompare(double j, double m, double e, int infoCompare[]) {
int i, k;
double a, b;
for (i = 0; i < 3; i++) {
switch (i) {
case 0:
a = j;
break;
case 1:
a = m;
break;
case 2:
a = e;
break;
}
for (k = 0; k < 3; k++) {
switch (k) {
case 0:
b = j;
break;
case 1:
b = m;
break;
case 2:
b = e;
break;
}
infoCompare[i * 3 + k] = (a > b) ? 1 : ((a < b) ? -1 : 0);
}
}
}
void listout(struct data1 *d, int infoCompareAve[], char *line) {
struct node *tsvroot;
char *col1, *col2;
int j, m, e;
int i, flag;
int infoCompareStudent[3 * 3];
tsvroot = NULL;
cut_tsv(line, &tsvroot);
usr_analyze_tsv(&tsvroot, &col1, &col2, &j, &m, &e);
release_tsv(&tsvroot);
if (col2 == NULL || j < 0 || m < 0 || e < 0)
return;
if (!strcmp(col2, d->groupe)) {
makeInfoCompare((double)j, (double)m, (double)e, infoCompareStudent);
flag = 1;
for (i = 0; i < 3 * 3; i++) {
if (infoCompareAve[i] == 0)
continue;
if (infoCompareStudent[i] != infoCompareAve[i]) {
flag = 0;
break;
}
}
if (flag) {
printf("name: %s : jpn:%d math:%d eng:%d\n", col1, j, m, e);
}
}
xfree(col1);
xfree(col2);
}
int main(int argc, char *argv[]) {
FILE *fp;
struct node *root;
struct data1 *d;
int infoCompare[3 * 3];
char *p;
if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return -1;
}
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "cannot opne the file '%s'\n", argv[1]);
return -1;
}
root = NULL;
while ((p = mygetline(fp))) {
sum(&root, p);
xfree(p);
}
while ((d = pop(&root))) {
printf("groupe: %s\n", d->groupe);
printf("jpn:%.1f, math:%.1f, eng:%.1f\n", d->j / d->n, d->m / d->n, d->e / d->n);
makeInfoCompare(d->j, d->m, d->e, infoCompare);
fseek(fp, 0, SEEK_SET);
clearerr(fp);
printf("---------------------\n");
while ((p = mygetline(fp))) {
listout(d, infoCompare, p);
xfree(p);
}
putchar('\n');
xfree(d->groupe);
xfree(d);
}
fclose(fp);
/* xmallocdump(); */
return 0;
}
/* end */