# Preparazione Midterm # Esercizio 01 - TDE Settembre 2024 Si scriva una funzione **conta** che riceve in ingresso una stringa **S** contenente più parole separate da virgole e contenenti solamente lettere minuscole (oltre ad eventuali parametri aggiuntivi utili per lo sviluppo della funzione). La funzione **conta** deve restituire al chiamante la lettera dell’alfabeto che compare più frequentemente tra le iniziali delle parole (si supponga per semplicità sia unica). Si scriva quindi una seconda funzione **elimina** che riceve in ingresso la stringa **S** (contenente più parole e solo caratteri minuscoli), un carattere **C** (oltre ad eventuali parametri aggiuntivi ritenuti utili per lo sviluppo della funzione), e riporta al chiamante una stringa **T** contenente le sole parole di **S** che iniziano per **C**, separate da virgole. Nel main si stampi il vettore restituito dalla funzione elimina. ```c // Librerie #include <stdio.h> #include <string.h> // Macro #define LEN 100 #define ASCII 256 // Prototipi char conta(char []); void elimina(char [], char, char []); void soloIniziali(char [], char []); // Main int main(){ // Variabili char S[LEN] = "cane,gatto,albero,fiore,acqua,sole,amico,giardino,pietra,vento"; char senza_carattere[LEN]; char lettera_frequente, da_eliminare = 'g'; printf("Stringa iniziale: %s\n", S); // Conto lettera_frequente = conta(S); printf("L'iniziale più frequente è: %c\n", lettera_frequente); // Elimino dalla stringa elimina(S, da_eliminare, senza_carattere); printf("Stringa rislutante con parole che iniziano solo per %c: %s\n", da_eliminare, senza_carattere); return 0; } // Funzioni void soloIniziali(char src[], char dest[]){ // Variabili int len = strlen(src), len_dest = 0, i; // Scorro la stringa e copio (senza buchi) i caratteri di src se: // sono al primo carattere // il carattere precednete è una virgola for(i=0; i<len; i++){ if(i == 0 || src[i-1] == ','){ dest[len_dest] = src[i]; len_dest++; } } // Aggiungo il carattere di terminazione per rendere dest una stringa dest[len_dest] = '\0'; return; } char conta(char src[]){ // Varibili int count[ASCII] = {0}, i, len, max_id = 0, max_count = 0; char solo_iniziali[LEN]; // Prendo le sole iniziali delle parole soloIniziali(src, solo_iniziali); printf("Stringa delle sole iniziali: %s\n", solo_iniziali); // Uso un vettore di interi che rappresenta il numero di volte che una lettera // in posizione ID (secondo ASCII) appare in src // scorro la stringa e incremento il valore dell'array count // ogni volta che incremento verifico se deo aggiornare il massimo len = strlen(solo_iniziali); for(i=0; i<len; i++){ count[solo_iniziali[i]]++; if(max_count < count[solo_iniziali[i]] && max_id != solo_iniziali[i]) { max_id = solo_iniziali[i]; max_count = count[solo_iniziali[i]]; } } // restituisco max_id che l'id ascii corrispondente alla lettera che appare // di più return max_id; } void elimina(char src[], char rim, char dest[]){ // Variabili int len = strlen(src), len_dest = 0, i = 0; // Scorro la stringa e se i=0 oppure il carattere precendente è ',' // verifico che il carattere è uguale a rim // se non lo è scorro fino all'indice dopo la virgola // se lo è copio fino alla prossima virgola o fino a '\0' while(i < len){ if(i == 0 || src[i-1] == ','){ if(src[i] == rim){ // copio fino alla virgola while(src[i] != ',' && i < len){ dest[len_dest] = src[i]; i++; len_dest++; } // copio anche la virgola if(i < len){ dest[len_dest] = ','; len_dest++; i++; } } else{ // incremento l'indice fino alla prossima virgola o fino alla fine // della stringa while(src[i] != ',' && i < len) i++; if(i < len) i++; // se non sono alla fine punto alla prima lettera dopo la virgola } } } // Rimuovo ultima virgola e inserisco il carattere di terminazione della stringa if(dest[len_dest-1] == ',') len_dest = len_dest - 1; dest[len_dest] = '\0'; return; } ``` --- # Esercizio 02 - TDE Marzo 2017 Scrivere una funzione che riceve due stringhe: *parola* e *elimina*. La funzione cerca in *parola* tutti i caratteri che compongono la stringa *elimina*, e li rimuove solamente se li trova tutti e nell’ordine in cui compaiono in *elimina*, anche se non consecutivi. L’operazione viene ripetuta finché in *parola* è contenuta un’intera istanza della stringa *elimina*. La funzione, oltre a modificare l’array *parola*, restituisce il numero di volte che ha eliminato i caratteri dell’intera stringa *elimina* da *parola*. Nell’eliminare caratteri non devono essere lasciati buchi, ma *parola* dev’essere ricompattata. **Esempio** parola: amaarrreeeemmmmarrreeaaaarrrmae elimina: mare La funzione trova tutte le lettere di “mare” in “aMAaRrrEeeemmmmarrreeaaaarrrmae” che diventa “aarreeemmmmarrreeaaaarrrmae” La funzione trova tutte le lettere di “mare” in “aarreeeMmmmARrrEeaaaarrrmae” che diventa “aarreeemmmrreaaaarrrmae” La funzione trova tutte le lettere di “mare” in “aarreeemmMrreAaaaRrrmaE” che diventa “aarreeemmrreaaarrma” Poi non trova più tutte le lettere e restituisce 3 ```c // Librerie #include <stdio.h> #include <string.h> // Macro #define LEN 100 // Prototipi int eliminaStringa(char [], char []); int trovaIndici(char [], char [], int []); void rimuoviIndici(char [], int [], int); // Main int main(){ // Variabili char stringa[LEN] = "amaarrreeeemmmmarrreeaaaarrrmae"; char elimina[LEN] = "mare"; int n; printf("Stringa originale: %s\n", stringa); printf("Stringa da rimuovere: %s\n", elimina); // Elimina da stringa n = eliminaStringa(stringa, elimina); printf("La stringa è stata eliminata %d volte\n", n); printf("Stringa risultante: %s\n", stringa); return 0; } // Funzioni int eliminaStringa(char src[], char elimina[]){ int n = 0, idxs[LEN]; while(trovaIndici(src, elimina, idxs)){ rimuoviIndici(src, idxs, strlen(elimina)); n++; } return n; } int trovaIndici(char src[], char elimina[], int idxs[]){ int i, j=0; // Scorro la stringa e se src[i] = elimina[j] salvo in idxs l'indice da // rimuovere e incremento l'indice di j for(i = 0; i < strlen(src); i++){ if(src[i] == elimina[j]){ idxs[j] = i; j++; } } // restituisco 1 se ho trovato tutta la stringa elimina e 0 altrimenti if(j == strlen(elimina)) return 1; else return 0; } void rimuoviIndici(char src[], int idxs[], int n){ int i, j, len; // parto dal fondo se no cambiano gli indici della parola for(i=n-1; i>=0; i--){ len = strlen(src); for(j = idxs[i]; j < len; j++){ src[j] = src[j+1]; } } } ``` --- # Esercizio 03 - TDE Gennaio 2022 Si scriva una funzione rimuoviValori che prende in ingresso una matrice M di interi di dimensioni NxN (con #define N 4), un intero x e ulteriori variabili aggiuntive, se necessarie. La funzione identifica i valori di M che sono a distanza minima da x e modifica M mettendo a zero tutti i valori che stanno sulla parallela alla diagonale principale passante per i valori sopra identificati. Si guardino gli esempi sotto per evitare fraintendimenti su quali elementi mettere a zero. N.B. Qualora ci fossero più valori in M alla stessa distanza da x, la funzione rimuoviValori ripete l’operazione per tutti i valori a distanza minima. N.B. Si consiglia fortemente l’uso di funzioni ausiliarie per produrre un codice semplice, leggibile e compatto Si scriva nel main l’invocazione alla funzione rimuoviValori e si stampi la matrice nel main, non in rimuoviValori. ```c #include <stdio.h> #define N 4 // Prototipi delle funzioni void rimuoviValori(int [][N], int); int distanzaMinima(int [][N], int); void azzeraParallela(int [][N], int, int); int val_assoluto(int); int main() { int M[N][N] = { {1, 3, 5, 3}, {5, 6, 7, 5}, {5, 6, 2, 1}, {3, 6, 9, 4} }; int x = 7; // oppure 8 // Stampa matrice printf("Matrice originale:\n"); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%d ", M[i][j]); } printf("\n"); } // Chiamata alla funzione rimuoviValori rimuoviValori(M, x); // Stampa matrice printf("\nMatrice modificata:\n"); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%d ", M[i][j]); } printf("\n"); } return 0; } // Funzione principale che rimuove i valori sulla parallela alla diagonale void rimuoviValori(int M[N][N], int x) { int minDist = distanzaMinima(M, x); // Per ogni elemento della matrice, controlla se ha la distanza minima da x for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (val_assoluto(M[i][j] - x) == minDist) { azzeraParallela(M, i, j); // Azzera la parallela } } } } // Calcola la distanza minima tra x e gli elementi di M int distanzaMinima(int M[N][N], int x) { int minDist = val_assoluto(M[0][0] - x); // Inizializza con la distanza del primo elemento for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { int dist = val_assoluto(M[i][j] - x); if (dist < minDist) { minDist = dist; } } } return minDist; } // Imposta a zero tutti gli elementi sulla parallela alla diagonale principale passante per (row, col) void azzeraParallela(int M[N][N], int row, int col) { int offset; // Azzera gli elementi sulla parallela alla diagonale principale verso l'alto a sinistra for (offset = -N; offset <= N; offset++) { int r = row + offset; int c = col + offset; if (r >= 0 && r < N && c >= 0 && c < N) { M[r][c] = 0; } } } int val_assoluto(int n){ int v_n = n; if(v_n < 0) v_n = -v_n; return v_n; } ``` --- # Esercizio 04 - TDE Gennaio 2023 Si una funzione riordina che prende in ingresso due vettori **u** e **v** (più eventuali variabili necessarie) e che riordina gli elementi del primo vettore passato in input (**u** nel nostro caso) nel seguente modo: - tutti gli elementi di **u** che non compaiono in **v** saranno nelle prime posizioni di **u** dopo l'invocazione - tutti gli elementi di **u** che compaiono in **v** saranno nelle ultime posizioni di **u** dopo l'invocazione Si faccia riferimento all'esempio sotto per eventuali dubbi su come modificare **u.** Si invochi quindi la funzione relativamente al seguente codice e si stampi il contenuto del vettore **u** a schermo. N.B. non è possibile stampare all'interno della funzione riordina u = [4, 1, 3, 7, 0] e v = [1, 6, 8, 4] → u = [3, 7, 0, 4, 1] **NOTA:** Nella soluzione proposta ci sono due versioni. riordinaIneff è inefficiente ma intuitiva, riordina è efficiente. ```c // Librerie #include <stdio.h> // Macro #define N 5 // Prototipi void stampaArray(int [], int); void riordina(int [], int [], int, int); void riordinaIneff(int [], int [], int, int); // Main int main(){ int u[N] = {4,1,3,7,0}, v[N] = {1,6,8,4}; // Stampa array printf("Vettore u: "); stampaArray(u, N); printf("Vettore v: "); stampaArray(v, N-1); // Riordina // riordina(u, v, N, N-1); riordinaIneff(u, v, N, N-1); // Stampa array modificato printf("Vettore u dopo la modifica: "); stampaArray(u, N); return 0; } // Funzioni void stampaArray(int v[], int dim){ int i; printf("["); for(i=0; i<dim; i++){ printf("%d, ", v[i]); } printf("]\n"); return; } void riordina(int u[], int v[], int u_dim, int v_dim){ int i, j, res[N], r_dim = 0, flag, dopo = 0; // Sposto all'inizio gli elementi di u che non appartengono a v // E sposto alla fine gli element di u che sono anche in v for(i=0; i<u_dim; i++){ flag = 1; // metto flag FALSE se NON devo mettere u[i] enlla r_dim parte for(j=0; j<v_dim && flag; j++){ if(u[i] == v[j]) flag = 0; } if(flag){ res[r_dim] = u[i]; r_dim++; } else{ res[u_dim - 1 - dopo] = u[i]; dopo++; } } // copio l'array girando l'ultima parte for(i=0; i<r_dim; i++){ u[i] = res[i]; } for(i=r_dim; i < u_dim; i++){ u[i] = res[u_dim - (i - r_dim) - 1]; } } void riordinaIneff(int u[], int v[], int u_dim, int v_dim){ int i, j, res[N], r_dim = 0, flag; // Sposto all'inizio gli elementi di u che non appartengono a v for(i=0; i<u_dim; i++){ flag = 1; // metto flag FALSE se NON devo mettere u[i] enlla r_dim parte for(j=0; j<v_dim && flag; j++){ if(u[i] == v[j]) flag = 0; } if(flag){ res[r_dim] = u[i]; r_dim++; } } // Sposto alla fine gli elementi di u che appartengono a v for(i=0; i<u_dim; i++){ flag = 0; // metto flag FALSE se NON devo mettere u[i] enlla r_dim parte for(j=0; j<v_dim && !flag; j++){ if(u[i] == v[j]) flag = 1; } if(flag){ res[r_dim] = u[i]; r_dim++; } } // copio l'array girando l'ultima parte for(i=0; i<u_dim; i++){ u[i] = res[i]; } } ``` --- # Esercizio 05 - Alleanze tra Università Definire un tipo di dato University che descrive un'università. Ogni università è caratterizzata da una stringa che indica il nome per esteso (ad esempio, "Politecnico di Milano", "École Polytechnique Fédérale de Lausanne", etc.), una stringa che descrive la sigla (ad esempio, "Polimi", "EPFL", etc), due caratteri che contengono la sigla della nazione in cui si trova la sede principale (ad esempio, "IT", "CH", etc), un intero che rappresenta il numero di studenti immatricolati (ad esempio, 42496, 13445, etc) e un numero reale che descrive il punteggio ottenuto dall'università secondo il ranking SDD (ad esempio, 46.7, 277.0, etc). Definire un tipo di dato Alleanza che descrive una lista di università che collaborano insieme. Fare anche la versione con una struct alleanza che mantiene come campo anche il numero di università nell’alleanza. Implementare le seguenti funzioni: 1. ricerca(): la funzione verifica se è presente nell'alleanza un'università con un dato nome esteso. Se presente, ritorna le informazioni dell'università, altrimenti segnala al chiamante l'assenza. 2. filtraPerNazione(): la funzione restituisce una nuova lista contenente solo le università dell'alleanza che appartengono a una specifica nazione dall'utente. 3. sostituisci(): la funzione sostituisce un'università nell'alleanza, identificata dal nome corto, con un'altra università passata in ingresso. La funzione ritorna l'università appena rimossa. La funzione comunica al chiamante se la sostituzione è avvenuta o meno. 4. massimoStudentiPerNazione(): la funzione ricerca, per ogni nazione nell'alleanza, l'università con il maggior numero di studenti, e restituisce un lista con le università con il numero massimo di studenti per nazione. ## Versione Struct ```c // VERSIONE CON STRUCT // Librerie #include <stdio.h> #include <string.h> // Macro #define LEN 100 #define N 5 // Tipi typedef char Stringa[LEN]; typedef struct{ Stringa nome_lungo; Stringa nome_corto; char sigla[3]; int n_studenti; float score; } Uni; typedef struct{ int n_uni; Uni lista_uni[N]; } Alleanza; // Prototipi Uni ricerca(Alleanza, char [], int*); void stampaUni(Uni); void stampaAlleanza(Alleanza); Alleanza filtraNazione(Alleanza, char []); Uni sostituisciUni(Alleanza*, Uni, char [], int *); Alleanza massimoNumeroStudentiPerNazione(Alleanza); // Main int main(){ // Variabili per Uni Uni poli, eth, epfl, sapienza, luiss; Alleanza alle_1, alle_2; poli.score = 1000; poli.n_studenti = 10000; strcpy(poli.nome_lungo, "Politecnico di Milano"); strcpy(poli.nome_corto, "PoliMi"); strcpy(poli.sigla, "IT"); eth.score = 2000; eth.n_studenti = 20000; strcpy(eth.nome_lungo, "Eidgenossische Technische Hochschule Zurich"); strcpy(eth.nome_corto, "ETH"); strcpy(eth.sigla, "CH"); epfl.score = 500; epfl.n_studenti = 3000; strcpy(epfl.nome_lungo, "École Polytechnique Fédérale de Lausanne"); strcpy(epfl.nome_corto, "EPFL"); strcpy(epfl.sigla, "CH"); sapienza.score = 7000; sapienza.n_studenti = 100000; strcpy(sapienza.nome_lungo, "Università degli Studi di Roma La Sapienza"); strcpy(sapienza.nome_corto, "uniroma1"); strcpy(sapienza.sigla, "IT"); luiss.score = 100; luiss.n_studenti = 2000; strcpy(luiss.nome_lungo, "Libera Università degli Studi Sociali"); strcpy(luiss.nome_corto, "luiss"); strcpy(luiss.sigla, "IT"); alle_1.n_uni = 2; alle_1.lista_uni[0] = eth; alle_1.lista_uni[1] = poli; alle_2.n_uni = 3; alle_2.lista_uni[0] = epfl; alle_2.lista_uni[1] = sapienza; alle_2.lista_uni[2] = luiss; // Altre variabili printf("\n\n*RICERCA*\n"); Uni res; int err; Stringa nome = "Politecnico di Milano"; // Ricerca err = 0; res = ricerca(alle_1, nome, &err); if(err){ printf("%s non è nell'alleanza cercata\n", nome); } else{ stampaUni(res); } err = 0; res = ricerca(alle_2, nome, &err); if(err){ printf("%s non è nell'alleanza cercata\n", nome); } else{ stampaUni(res); } // Filtro per nazione printf("\n\n*FILTRO*\n"); Alleanza alle_filtro = filtraNazione(alle_2, "IT"); printf("Alleanza Filtro IT\n"); stampaAlleanza(alle_filtro); // Sostituisci printf("\n\n*SOSTITUZIONE*\n"); Uni rm; char nome_corto[LEN] = "luiss"; err = 0; rm = sostituisciUni(&alle_2, eth, nome_corto, &err); if(err){ printf("%s non è nell'alleanza\n", nome_corto); } else{ printf("Uni rimossa\n"); stampaUni(rm); printf("Alleanza Modificata\n"); stampaAlleanza(alle_2); } // Numero studenti max per nazione in un'alleanza printf("\n\n*MAX STUDENTI PER NAZIONE*\n"); Alleanza max_studenti = massimoNumeroStudentiPerNazione(alle_2); printf("Università con massimo numero di studenti per nazione\n"); stampaAlleanza(max_studenti); } // Funzioni Uni ricerca(Alleanza alle, char nome[], int * err){ int i, flag; Uni res = alle.lista_uni[0]; flag = 1; for(i=0; i<alle.n_uni && flag; i++){ if(!strcmp(alle.lista_uni[i].nome_lungo, nome)){ flag = 0; res = alle.lista_uni[i]; } } *err = flag; return res; } Alleanza filtraNazione(Alleanza alle, char sigla[]){ int i, len = 0; Alleanza dest; for(i=0; i<alle.n_uni; i++){ if(!strcmp(alle.lista_uni[i].sigla, sigla)){ dest.lista_uni[len] = alle.lista_uni[i]; len++; } } dest.n_uni = len; return dest; } Uni sostituisciUni(Alleanza * alle, Uni uni, char nome_corto[], int * err){ int i, flag = 1; Uni rm = alle->lista_uni[0]; for(i=0; i<alle->n_uni && flag; i++){ if(!strcmp(alle->lista_uni[i].nome_corto, nome_corto)){ flag = 0; rm = alle->lista_uni[i]; alle->lista_uni[i] = uni; } } *err = flag; return rm; } Alleanza massimoNumeroStudentiPerNazione(Alleanza src){ int i, j, len = 0, flag, max_studenti = 0; Alleanza res; Uni max_uni; Stringa sigle[LEN]; res.n_uni = 0; // Raccolgo tutte le sigle for(i=0; i < src.n_uni; i++){ flag = 1; for(j=0; j<len && flag; j++){ if(!strcmp(src.lista_uni[i].sigla, sigle[j])){ flag = 0; } } if(flag){ strcpy(sigle[len], src.lista_uni[i].sigla); len++; } } // Per ogni sigla estraggo l'uni con il numero massimo di studenti e la salvo // nell'alleanza da restituire for(i=0; i<len; i++){ max_studenti = 0; for(j=0; j<src.n_uni; j++){ if(!strcmp(src.lista_uni[j].sigla, sigle[i])){ if(max_studenti < src.lista_uni[j].n_studenti){ max_uni = src.lista_uni[j]; max_studenti = src.lista_uni[j].n_studenti; } } } res.lista_uni[res.n_uni] = max_uni; res.n_uni++; } return res; } void stampaUni(Uni uni){ printf("Nome: %s\n", uni.nome_lungo); printf("Nome corto: %s\n", uni.nome_corto); printf("Studenti: %d\n", uni.n_studenti); printf("Score: %.2f\n", uni.score); printf("Sigla: %s\n", uni.sigla); } void stampaAlleanza(Alleanza alle){ int i; if(alle.n_uni == 0){ printf("Alleanza vuota\n"); } else{ printf("Alleanza\n"); for(i=0; i<alle.n_uni; i++) stampaUni(alle.lista_uni[i]); } } ``` ## Versione Array ```c // VERSIONE CON ARRAY #include <stdio.h> #include <string.h> // Macro #define LEN 100 #define N 5 // Tipi typedef char Stringa[LEN]; typedef struct { Stringa nome_lungo; Stringa nome_corto; char sigla[3]; int n_studenti; float score; } Uni; typedef Uni Alleanza[N]; // Alleanza è ora un array di Uni // Prototipi Uni ricerca(Alleanza, int, char[], int*); void stampaUni(Uni); void stampaAlleanza(Alleanza, int); int filtraNazione(Alleanza, int, Alleanza, char[]); Uni sostituisciUni(Alleanza, int*, Uni, char[], int*); int massimoNumeroStudentiPerNazione(Alleanza, int, Alleanza); // Main int main(){ // Inizializzazione delle università Uni poli = {"Politecnico di Milano", "PoliMi", "IT", 10000, 1000}; Uni eth = {"Eidgenossische Technische Hochschule Zurich", "ETH", "CH", 20000, 2000}; Uni epfl = {"École Polytechnique Fédérale de Lausanne", "EPFL", "CH", 3000, 500}; Uni sapienza = {"Università degli Studi di Roma La Sapienza", "uniroma1", "IT", 100000, 7000}; Uni luiss = {"Libera Università degli Studi Sociali", "luiss", "IT", 2000, 100}; // Definizione delle alleanze come array di Uni Alleanza alle_1 = {eth, poli}; int n_alle_1 = 2; Alleanza alle_2 = {epfl, sapienza, luiss}; int n_alle_2 = 3; // Ricerca printf("\n\n*RICERCA*\n"); Uni res; int err; Stringa nome = "Politecnico di Milano"; err = 0; res = ricerca(alle_1, n_alle_1, nome, &err); if(err){ printf("%s non è nell'alleanza cercata\n", nome); } else{ stampaUni(res); } err = 0; res = ricerca(alle_2, n_alle_2, nome, &err); if(err){ printf("%s non è nell'alleanza cercata\n", nome); } else{ stampaUni(res); } // Filtro per nazione printf("\n\n*FILTRO*\n"); Alleanza alle_filtro; int n_alle_filtro = filtraNazione(alle_2, n_alle_2, alle_filtro, "IT"); printf("Alleanza Filtro IT\n"); stampaAlleanza(alle_filtro, n_alle_filtro); // Sostituisci printf("\n\n*SOSTITUZIONE*\n"); char nome_corto[LEN] = "luiss"; err = 0; Uni rm = sostituisciUni(alle_2, &n_alle_2, eth, nome_corto, &err); if(err){ printf("%s non è nell'alleanza\n", nome_corto); } else{ printf("Uni rimossa\n"); stampaUni(rm); printf("Alleanza Modificata\n"); stampaAlleanza(alle_2, n_alle_2); } // Numero studenti max per nazione in un'alleanza printf("\n\n*MAX STUDENTI PER NAZIONE*\n"); Alleanza max_studenti; int n_max_studenti = massimoNumeroStudentiPerNazione(alle_2, n_alle_2, max_studenti); printf("Università con massimo numero di studenti per nazione\n"); stampaAlleanza(max_studenti, n_max_studenti); return 0; } // Funzioni Uni ricerca(Alleanza alle, int n_uni, char nome[], int * err){ int i, flag = 1; Uni res = alle[0]; for(i = 0; i < n_uni && flag; i++){ if(!strcmp(alle[i].nome_lungo, nome)){ flag = 0; res = alle[i]; } } *err = flag; return res; } int filtraNazione(Alleanza alle, int n_uni, Alleanza dest, char sigla[]){ int i, len = 0; for(i = 0; i < n_uni; i++){ if(!strcmp(alle[i].sigla, sigla)){ dest[len] = alle[i]; len++; } } return len; // Numero di università filtrate } Uni sostituisciUni(Alleanza alle, int *n_uni, Uni uni, char nome_corto[], int * err){ int i, flag = 1; Uni rm = alle[0]; for(i = 0; i < *n_uni && flag; i++){ if(!strcmp(alle[i].nome_corto, nome_corto)){ flag = 0; rm = alle[i]; alle[i] = uni; } } *err = flag; return rm; } int massimoNumeroStudentiPerNazione(Alleanza src, int n_uni, Alleanza res){ int i, j, len = 0, max_studenti; char sigle[N][3]; int n_sigle = 0; // Raccogli tutte le sigle for(i = 0; i < n_uni; i++){ int flag = 1; for(j = 0; j < n_sigle && flag; j++){ if(!strcmp(src[i].sigla, sigle[j])){ flag = 0; } } if(flag){ strncpy(sigle[n_sigle], src[i].sigla, 3); n_sigle++; } } // Trova l'università con il massimo numero di studenti per ogni sigla for(i = 0; i < n_sigle; i++){ max_studenti = 0; Uni max_uni; for(j = 0; j < n_uni; j++){ if(!strcmp(src[j].sigla, sigle[i])){ if(src[j].n_studenti > max_studenti){ max_uni = src[j]; max_studenti = src[j].n_studenti; } } } res[len] = max_uni; len++; } return len; // Numero di università nel risultato } void stampaUni(Uni uni){ printf("Nome: %s\n", uni.nome_lungo); printf("Nome corto: %s\n", uni.nome_corto); printf("Studenti: %d\n", uni.n_studenti); printf("Score: %.2f\n", uni.score); printf("Sigla: %s\n", uni.sigla); } void stampaAlleanza(Alleanza alle, int n_uni){ if(n_uni == 0){ printf("Alleanza vuota\n"); } else { printf("Alleanza\n"); for(int i = 0; i < n_uni; i++) stampaUni(alle[i]); } } ``` --- # Esercizio 06 - Popoli **Testo principale** 1. Definire e inizializzare una struttura popolazione_t contenente almeno cinque popoli nativi americani (es. Navajo, Apache, Sioux, Cherokee, Hopi), specificando per ciascuno: - il numero di abitanti, - il nome della lingua parlata, - e il relativo livello di vitalità linguistica. 2. Invocare la funzione analizzaPopoli e stampare: - il nome del popolo con più abitanti; - il nome del popolo con popolazione più vicina alla media. 3. Richiedere all’utente di inserire un livello di vitalità linguistica (ad esempio "Viva", "In pericolo", "Estinta"). 4. Invocare filtraPopoliLingua per eliminare i popoli la cui lingua non corrisponde al livello specificato. 5. Stampare a video i popoli rimasti dopo il filtraggio, indicando per ciascuno il nome, la lingua e il livello **Funzioni Richieste** - `analizzaPopoli`: Scrivere una funzione `analizzaPopoli` che prende in ingresso una popolazione, ed ulteriori variabili aggiuntive se necessarie, e riporta al chiamante: - Il nome del popolo con più abitanti tra quelli della popolazione - Il nome del popolo con il numero di abitanti più vicino alla media degli abitanti dei popoli della popolazione in esame. *Hint: per individuare il popolo più vicino alla popolazione media, confrontare la differenza assoluta tra il numero di abitanti di ciascun popolo e il valore medio.* - `filtraPopoliLingua`: Scrivere una funzione `filtraPopoliLingua` che prende in ingresso una popolazione ed eventuali parametri aggiuntivi ed elimina tutti i popoli la cui lingua non corrisponde al livello di vitalità indicato da vitalitaRichiesta. La funzione restituisce il numero di popoli rimasti dopo il filtraggio. ```c #include<stdio.h> #include<string.h> #include<math.h> #define N 20 #define DIM 10 typedef struct { char nome[N]; // Nome della lingua parlata char vitalita[N]; // Es. "Viva", "In pericolo", "Estinta" https://ich.unesco.org/doc/src/00120-EN.pdf } lingua_t; typedef struct{ char nome[N]; // nome della popolazione int pop; // numero di abitanti lingua_t lingua; // lingua parlata } popolo_t; typedef struct { popolo_t v[DIM]; // Vettore dei popoli int n; // Numero effettivo di popoli presenti } popolazione_t; void analizzaPopoli(popolazione_t p, char popMax[], char popVicinoMedia[]); int filtraPopoliLingua(popolazione_t *p, char vitalitaRichiesta[]); void analizzaPopoli(popolazione_t p, char popMax[], char popVicinoMedia[]) { int somma = 0; int i; // Calcolo della somma totale delle popolazioni for (i = 0; i < p.n; i++) { somma += p.v[i].pop; } float media = (float)somma / p.n; // Ricerca del massimo, algoritmo del supermercato! int max = p.v[0].pop; strcpy(popMax, p.v[0].nome); float diff_min = fabs(p.v[0].pop - media); strcpy(popVicinoMedia, p.v[0].nome); // Ricerca del massimo e del valore più vicino alla media for (i = 1; i < p.n; i++) { // aggiorno il massimo if (p.v[i].pop > max) { max = p.v[i].pop; strcpy(popMax, p.v[i].nome); } // aggiorno la media if (fabs(p.v[i].pop - media) < diff_min) { diff_min = fabs(p.v[i].pop - media); strcpy(popVicinoMedia, p.v[i].nome); } } } int filtraPopoliLingua(popolazione_t *p, char vitalitaRichiesta[]) { int i, j = 0; for (i = 0; i < p->n; i++) { if (strcmp(p->v[i].lingua.vitalita, vitalitaRichiesta) == 0) { p->v[j]= p->v[i]; j++; // posso fare così perché sono sicuro che j<=i; // p->v[j++] = p->v[i]; //se vuoi fare il fenomeno ma è meno chiaro } } p->n = j; return j; } int main() { popolazione_t p; // Navajo strcpy(p.v[0].nome, "Navajo"); p.v[0].pop = 350000; strcpy(p.v[0].lingua.nome, "Diné bizaad"); strcpy(p.v[0].lingua.vitalita, "Vulnerabile"); // Apache strcpy(p.v[1].nome, "Apache"); p.v[1].pop = 110000; strcpy(p.v[1].lingua.nome, "Ndee biyati'"); strcpy(p.v[1].lingua.vitalita, "In pericolo"); // Sioux strcpy(p.v[2].nome, "Sioux"); p.v[2].pop = 170000; strcpy(p.v[2].lingua.nome, "Lakota"); strcpy(p.v[2].lingua.vitalita, "In pericolo"); // Cherokee strcpy(p.v[3].nome, "Cherokee"); p.v[3].pop = 370000; strcpy(p.v[3].lingua.nome, "Tsalagi"); strcpy(p.v[3].lingua.vitalita, "In pericolo"); // Hopi strcpy(p.v[4].nome, "Hopi"); p.v[4].pop = 19000; strcpy(p.v[4].lingua.nome, "Hopi"); strcpy(p.v[4].lingua.vitalita, "Viva"); p.n = 5; char popMax[N]; char popVicinoMedia[N]; char vitalitaRichiesta[N]; // analisi demografica analizzaPopoli(p, popMax, popVicinoMedia); printf("Popolo con più abitanti: %s\n", popMax); printf("Popolo con popolazione più vicina alla media: %s\n\n", popVicinoMedia); // Inserimento vitalità printf("Inserisci livello di vitalità da mantenere (es. 'Viva', 'In pericolo', 'Estinta'): "); fgets(vitalitaRichiesta, N, stdin); // rimuovo a capo int k; for ( k = 0; vitalitaRichiesta[k] != '\0'; k++) { if (vitalitaRichiesta[k] == '\n') { vitalitaRichiesta[k] = '\0'; break; } } // Filtraggio filtraPopoliLingua(&p, vitalitaRichiesta); // Stampa printf("\nPopoli rimasti dopo il filtraggio (%s):\n", vitalitaRichiesta); if (p.n == 0) { printf("Nessun popolo corrisponde al criterio selezionato.\n"); } else { for (int i = 0; i < p.n; i++) { printf("- %s (lingua: %s, vitalità: %s)\n", p.v[i].nome, p.v[i].lingua.nome, p.v[i].lingua.vitalita); } } return 0; } // alternativa che non modifica la popolazione in ingresso ma usa una struttura di appoggio q int filtraPopoliLingua_bis(popolazione_t *p, popolazione_t *q, char vitalitaRichiesta[]); int filtraPopoliLingua_bis(popolazione_t *p, popolazione_t *q, char vitalitaRichiesta[]) { q->n = 0; // inizializza la nuova popolazione a vuota for (int i = 0; i < p->n; i++) { if (strcmp(p->v[i].lingua.vitalita, vitalitaRichiesta) == 0) { q->v[q->n] = p->v[i]; // copia l'intera struttura popolo_t q->n++; // aggiorna la dimensione effettiva } } return q->n; // numero di popoli copiati } ```