Ti posto il tuo codice ritoccato e funzionante; dove ho aggiustato è commentato; principalmente la funzione che dava problemi era la strcln: sia nella fase iniziale, quando stampavi a video le varie famiglie, sia quando poi andavi a memorizzare nella tavola i nomi (manteneva per alcuni nomi, in particolare gli ultimi figli di ogni famiglia anche il carattere 'a capo', perchè sono l'ultimo elemento della riga del file, così poi quando usavi la ascii, questa dava risultati diversi per uno stesso nome, in quanto quello che prendeva da console, dalle funzioni figlio o genitore, non conteneva il carattere a capo, mentre quello presente nella tavola si); le altre cose che ho toccato sono minime, ma comunque commentate.
spero di essere stato chiaro
#include <stdio.h>
#include <string.h>
#define MAXLENGTH 10000
#define SIZE 50
//struttura nodo genealogico
typedef struct node {
char nome[30]; // nome persona nodo genealogico
char consorte[30]; // nome eventuale consorte (NULL)
struct node *next; // punta al successivo nella lista fratelli
//struct gnode *prev; // punta al precedente nella lista fratelli
struct node *head; // se padre punta alla testa della lista dei figli
int figli; // numero di figli
} gnode;
//PROTOTIPI
int Hash_Insert(gnode *[], gnode *); //inserimento puntatore nodo
int Hash_Search(gnode *[], char *); //ricerca nodo
int Hash_F(int, int); //funzione hash
int ascii(char *); //ID univoco
char *strcln(char *);
gnode *newGenNode(char *); //genera nuovo nodo genealogico
void enqueue(gnode *[], gnode *); //inserimento coda
gnode *dequeue(gnode *[]); //estrazione coda
int empty(); //coda vuota
void genitore(char *, char *);
void figlio(char *, char *);
void antenato(char *, char *);
void discendente(char *, char *);
//VARIABILI GLOBALI
char buf[MAXLENGTH]; //buffer...
char *prompt = "query_>"; //prompt stampato per l'utente
char *answer = "answer_>"; //stampa per la risposta
gnode *hashTab[SIZE]; //tabella hash (puntatori nodi genealogici)
gnode *queue[SIZE]; //coda puntatori nodi genealogici
int head, tail; //coda...
//METODI E FUNZIONI
int ascii(char *a) { //converte stringa nome in ID univoco intero
int x, i, sum;
sum = 0; i = 0;
while(*(a+i) != '\0') {
x = (int) *(a+i);
sum = sum + x;
i++;
}
return sum;
}
int Hash_Insert(gnode *T[], gnode *k) {
int i, j, sum;
i = 0;
sum = ascii(k->nome); //somma caratteri ascii nome univoco
while(i < SIZE) {
j = Hash_F(sum, i);
if (*(T+j) == NULL /*|| T[j] == FLAG*/) {
*(T+j) = k;
return j;
}
else {
i++;
}
}
return -1;
}
int Hash_Search(gnode *T[], char *k) {
int i, j, sum;
gnode *tmp;
char *n;
i = 0;
sum = ascii(k); //somma caratteri ascii nome univoco
while(i < SIZE) {
j = Hash_F(sum, i);
if(*(T+j) == NULL)
break;
tmp = *(T+j);
n = tmp->nome;
if (strcmp(n, k) == 0)
return j;
i++;
}
return -1;
}
int Hash_F(int k, int i) { //Hash basato su Quadratic Probing
int a, b, j, m;
m = SIZE;
a=39;
b=276;
return (((k % m) + (a * i) + (b * i * i)) % m);
}
char *strcln(char *full) {
int i = 0;
int j = 0;
char* p = (char*)malloc(sizeof(char)*200);//come avevi messo te prima non funzionava bene, certe volte restituiva una stringa vuota
while(*(full+i) != '\0') {
if(*(full+i) != ' ' && *(full+i) != '(' && *(full+i) != ')' && *(full+i) != ';' && *(full+i) != '\n') {//ho aggiunto questa ultima condizione perchè manteneva per alcuni nomi anche il carattera 'a capo', dando poi problemi nella funzione ascii
*(p+j) = *(full+i);
j++;
}
i++;
}
*(p+j) = '\0';
return p;
}
gnode *newGenNode(char *c) {
gnode *g = (gnode *)malloc(sizeof(gnode));
strcpy(g->nome,c);
g->consorte[0] = '\0';
g->head = NULL;
g->next = NULL;
//g->prev = NULL;
g->figli = 0;
return g;
}
int empty() {
return (head == tail);
}
void enqueue(gnode *Q[], gnode *x) {
if (tail == SIZE) {
printf("Queue overflow\n");
exit(1); //coda piena
}
*(Q+tail) = x;
tail++;
}
gnode *dequeue(gnode *Q[]) {
gnode *x;
if (head == -1) {
printf("Queue underflow\n");
exit(2); //coda vuota
}
x = *(Q+head);
head++;
return x;
}
void genitore(char *x, char *y) {
return figlio(y, x);
}
void figlio(char *x, char *y) {
int j;
gnode *p, *f, *tmp;
if((j = Hash_Search(hashTab, x)) != -1) {
f = *(hashTab+j);
}
else {
printf("%s non esiste\n", x);
return;
}
if((j = Hash_Search(hashTab, y)) != -1) {
p = *(hashTab+j);
}
else {
printf("%s non esiste\n", y);
return;
}
tmp = p->head;
if(p->head == NULL) {
printf("no\n", x); //non ha figli
return;
}
for (j = 0; j < (p->figli); j++) {
if (strcmp(tmp->nome, f->nome) == 0) {
printf("si\n");
return;
}
tmp = tmp->next; //prossimo lista fratelli
}
printf("no\n");
return;
}
void antenato(char *x, char *y) {
return discendente(y,x);
}
void discendente(char *x, char *y) {
int j, i;
gnode *v, *g, *tmp;
if((j = Hash_Search(hashTab, x)) != -1) {
g = *(hashTab+j);
}
else {
printf("%s non esiste\n", x);
return;
}
if((j = Hash_Search(hashTab, y)) != -1) {
v = *(hashTab+j);
}
else {
printf("%s non esiste\n", y);
return;
}
head = 0;
tail = 0;
if(v->head == NULL) {
printf("no\n");
return;
}
enqueue(queue, v);
while(empty() != 1) {
v = dequeue(queue);
tmp = v->head;
for(i=0; i<(v->figli); i++) {
if ((strcmp(tmp->nome, x)) == 0) {
printf("si\n");
return;
}
enqueue(queue, tmp);
tmp = tmp->next;
}
}
printf("no\n");
return;
}
int main(int argc, char *argv[]) {//avevi messo come secondo argomento un array di puntatori a stringhe, invece devi mettere una array a puntatori di char, quindi un'array di stringhe
int j;
gnode *p, *c, *s, *prev;
FILE *fp;
char *str, *strToken, parents[200], progenies[200], *name;
char No[40];
int cont = 0;
//inizializzazione tabella hash
for(j=0; j<SIZE; j++)
*(hashTab+j) = NULL;
//controllo parametri
if (argc != 2) {
printf("Numero di parametri errato. USAGE: gentree FILE\n");
exit(1); //errore parametri
}
//controllo consistenza file
if ((fp = fopen(argv[1], "r")) == NULL) {
printf("Impossibile aprire il file %s\n", argv[1]);
exit(2); //errore file
}
//lettura da file e generazione nodi, albero genealogico
while((str = fgets(buf, MAXLENGTH-1, fp)) != NULL) {
prev = NULL;
strToken = strtok(str, "#"); //separa stringa genitori e figli
strcpy(parents,strToken); //stringa genitori
strToken = strtok(NULL, "#");
strcpy(progenies,strToken); //stringa figli
//NODO GENITORE (CONSORTE)
strToken = strtok(parents, "+");
name = strcln(strToken);
printf("\nPadre = _%s_",name);
j = Hash_Search(hashTab, name);
if (j == -1) {
p = newGenNode(name);
if (Hash_Insert(hashTab, p) == -1) { //inserimento hash
printf("dimensione hash insufficiente: gestire collisioni\n");
exit(3); //dimensione hash; collisioni
}
}
else {
p = *(hashTab+j); //puntatore da hash
}
strToken = strtok(NULL, "+"); //aggiorno il-la consorte (NULL)
name = strcln(strToken);
printf("\nMadre = %s",name);
strcpy(p->consorte,name);
j = Hash_Search(hashTab, name);
if (j == -1) {
c = newGenNode(name);
if (Hash_Insert(hashTab, c) == -1) { //inserimento hash
printf("dimensione hash insufficiente: gestire collisioni\n");
exit(3); //dimensione hash; collisioni
}
}
else {
c = *(hashTab+j); //puntatore da hash
}
strcpy(c->consorte,p->nome);
//NODI FIGLI
strToken = strtok(progenies, "+");
int i = 0;
while (strToken != NULL) {
//creo un nuovo nodo figlio
p->figli++; c->figli++; //aggiorno numero figli
name = strcln(strToken);
printf("\nFigli = %s",name);
s = newGenNode(name);
if (p->head == NULL) { //padre -> primo figlio
p->head = s;
c->head = s;
}
if (Hash_Insert(hashTab, s) == -1) {//inserimento hash
printf("dimensione hash insufficiente: gestirecollisioni\n");
exit(3); //dimensione hash; risolvere collisioni
}
if(prev != NULL)
prev->next = s;
prev = s;
strToken = strtok(NULL, "+");
} //end while
s->next = p->head; //chiusura lista fratelli
printf("\n-----------------------\n");
}//end while
fclose(fp); //chiusura file genealogico sorgente
//ciclo di ascolto comandi utenti
char* com = (char*)malloc(sizeof(char)*100);
char* x = (char*)malloc(sizeof(char)*100);
char* y = (char*)malloc(sizeof(char)*100);
char g;
while(1) {
printf("%s", prompt);
int k;
int input = 0;
for(j=0; j<100; j++) { // pulizia buffers
com[j]='\0';
x[j]='\0';
y[j]='\0';
}
k = 0;
while((g=getchar()) != '\n') {
if(k == 100) {
printf("buffer comando overflow");
break;
}
if(input == 0) {
if(g == '(') {
input++;
k = 0;
} else {
com[k++] = g;
}
}
else {
if(input == 1) {
if(g == ',') {
input++;
k = 0;
} else {
x[k++] = g;
}
}
else {
if(input == 2) {
if(g == ')') {
input++;
k = 0;
}
else {
y[k++] = g;
}
}
}
}
}
if(!strcmp(com, "exit"))
exit(0);
//ti ho sistemato la scelta multipla, prima era molto incasinata
if(!strcmp(com, "figlio")) {
figlio(x,y);
}
else if(!strcmp(com, "discendente")) {
discendente(x,y);
}
else if(!strcmp(com, "genitore")) {
genitore(x,y);
}
else if(!strcmp(com, "antenato")) {
antenato(x,y);
}
else if(!strcmp(com, "help")) {
printf("uso del comando:\n\tfiglio x y\n\tgenitore x y");
printf(" \n\tdiscendente x y\n\tantenato x y\n");
}
else {
printf("comando non conosciuto\ndigitare help\n");
}
}//end while(1)
return;
}
[/code]