//Tema d'esame 15.VI.17 #include #include //Strutture dati //Prototipi funzioni char *pref(char *s, char *t); /* Restituisce il max prefisso comune fra s e t. Restituisce la stringa vuota se il prefisso comune e' vuoto, e NULL se una delle due stringhe e' NULL. */ char *leggi_riga(FILE *fp); /* Legge una riga dal file fp, che e' supposto aperto in lettura, restituendola come stringa ripulita dal ritorno a capo finale e terminata da \0. Restituisce NULL se fp e' NULL. */ void leggi_term(char *); /* Funzione aux: legge stringa da terminale, pulendo '\n' */ int lung(char *); /* Funzione aux: calcola lunghezza stringa */ int max(int, int); /* Funzione aux: calcola max degli args */ int main(void) { char strcor[BUFSIZ]; //Stringa corrente int strOK=0; //Variabile di stato: stringa corrente esiste char filcor[BUFSIZ]; //Nome file corrente int filOK=0; //Variabile di stato: stringa corrente esiste FILE *fp=NULL; //Puntatore a file aperto corrente int scelta, cont=1; int maxl=0; char menu[]="1.\tInserisci stringa.\n2.\tInserisci nome file.\n3.\tVisualizza stringa corrente.\n4.\tVisualizza file corrente.\n5.\tCalcola prefissi.\n6.\tLunghezza max dei prefissi.\n7.\tEsci.\n>"; do { printf("%s",menu); scanf("%d%*c", &scelta); switch(scelta) { case 1: { printf("Scrivi la stringa: "); leggi_term(strcor); printf("Nuova stringa corrente impostata: %s\n",strcor); strOK=1; } break; case 2: { printf("Scrivi il nome del file: "); leggi_term(filcor); if ( (fp=fopen(filcor,"r"))==NULL) { printf("Errore nell'apertura del file: %s\n", filcor); filOK=0; break; } printf("File corrente impostato e aperto.\n"); filOK=1; } break; case 3: { if (!strOK) { printf("Nessuna stringa specificata.\n"); break; } printf("Stringa corrente: %s\n",strcor); } break; case 4: { if (!filOK) { printf("Nessun file specificato.\n"); break; } printf("File corrente:\n"); char *r; while ( (r=leggi_riga(fp)) != NULL) { printf("%s\n", r); free(r); //Dealloca la memoria che contiene la riga } rewind(fp); //reimposta il punto di lettura all'inizio del file } break; case 5: { if (!strOK) { printf("Nessuna stringa specificata.\n"); break; } if (!filOK) { printf("Nessun file specificato.\n"); break; } char *r, *p; while ( (r=leggi_riga(fp)) != NULL) { p=pref(r,strcor); printf("%s\n", p); maxl=max(lung(p),maxl); free(r); //Dealloca la memoria che contiene la riga free(p); //Dealloca la memoria che contiene il prefisso comune } rewind(fp); //Reimposta il punto di lettura all'inizio del file } break; case 6: { printf("La lunghezza massima riscontrata fra i prefissi calcolati finora e': %d\n", maxl); } break; case 7: { if (filOK) fclose(fp); cont=0; } break; default: printf("Scelta inesistente.\n"); } } while (cont); return 0; } char *pref(char *s, char *t) { if ( (s==NULL) || (t == NULL) ) return NULL; char *p=NULL, *aux; int i; /* Soluzione con diverse chiamate realloc. Putre possibile una risoluzione con una sola chiamata malloc, previo calcolo della lunghezza del prefisso comune. */ //Alloca stringa prefisso comune for (i=0; s[i]!='\0' && t[i]!='\0'; i++) if (s[i]==t[i]) { if ( (aux=realloc(p, sizeof(char)+i))==NULL ) { printf("Errore nell'allocazione della memoria.\n"); exit(EXIT_FAILURE); } p=aux; p[i]=s[i]; } //Aggiunge terminatore '\0' if ( (aux=realloc(p, sizeof(char)+i))==NULL ) { printf("Errore nell'allocazione della memoria.\n"); exit(EXIT_FAILURE); } p=aux; p[i]='\0'; return p; } char *leggi_riga(FILE *fp) { if (fp==NULL) return NULL; char buf[BUFSIZ]; if ( fgets(buf,BUFSIZ,fp) == NULL ) return NULL; /* Implementazione con una sola chiamata a malloc, invece che con diverse chiamate a realloc */ //Calcola memoria necessaria char *s=NULL; int i; for (i=0; buf[i]!='\n'; i++); //Alloca la memoria if ( (s=malloc(sizeof(char)*(i+1))) ==NULL ) { printf("Errore nell'allocazione della memoria.\n"); exit(EXIT_FAILURE); } for (int j=0;jy) return x; return y; }