# Esercitazione 5: Typedef e Matrici
# Dati Anagrafici
Si definisca un tipo di dato `DatiArchivio` contenente i seguenti dati relativi ad una persona:
* Età
* Altezza
* Peso
**Richieste**
1. Si scriva un programma in grado di memorizzare i dati relativi a 5 persone inseriti dall’utente
2. Si stampino tutti i dati anagrafici inseriti
3. Si stampino i dati anagrafici relativi a persone con al più 20 anni
4. Si stampi l’altezza media di tutti dati inseriti
5. Si stampi l’altezza media dei soli dati inseriti relativi a persone con almeno 30 anni
```c
#include <stdio.h>
#define N 5
int main(int argc, char* argv[]) {
// Tipo
typedef struct {
int eta;
int altezza;
int peso;
} DatiArchivio;
// Variabili
DatiArchivio persone[N];
int i, n_30_anni;
float a_media;
// Acquisizione dati
for(i=0; i<N; i++){
printf("Persona %d\n", i+1);
do {
printf("Inserisci età: ");
scanf("%d", &persone[i].eta);
} while(persone[i].eta < 0);
do {
printf("Inserisci altezza: ");
scanf("%d", &persone[i].altezza);
} while(persone[i].altezza < 0);
do {
printf("Inserisci peso: ");
scanf("%d", &persone[i].peso);
} while(persone[i].peso < 0);
}
// Stampa di tutti i dati
printf("\nTUTTI\n");
for(i=0; i<N; i++) printf("Persona %d: età = %d - altezza = %d - peso = %d\n", i+1, persone[i].eta, persone[i].altezza, persone[i].peso);
// Stampa di dati con età <= 20
printf("\nPERSONE CON ETA <= 20\n");
for(i=0; i<N; i++){
if(persone[i].eta <= 20) printf("Persona %d: età = %d - altezza = %d - peso = %d\n", i+1, persone[i].eta, persone[i].altezza, persone[i].peso);
}
// Altezza media di tutti
printf("\nALTEZZA MEDIA di TUTTI\n");
a_media = 0;
for(i=0; i<N; i++) a_media += persone[i].altezza;
a_media /= N;
printf("Altezza media: %.2f\n", a_media);
// Altezza media di persone con anni >= 30
printf("\nALTEZZA MEDIA di PERSONE CON ETA >= 30\n");
a_media = 0;
n_30_anni = 0;
for(i=0; i<N; i++){
if(persone[i].eta >= 30){
a_media += persone[i].altezza;
n_30_anni++;
}
}
a_media /= n_30_anni;
printf("Altezza media di persone con almeno 30 anni: %.2f\n", a_media);
return 0;
}
```
---
# Confronto Articoli
Si definisca un tipo di dato `Articolo` composto dai seguenti campi:
* Titolo (stringa con spazi)
* Numero di Citazioni (int)
* Numero di Autori (int)
* Cognome Autore Principale (stringa no spazi)
**Richieste**
1. Si scriva un programma in grado di memorizzare i dati relativi a 5 articoli, da dati inseriti dall’utente
1. Si stampi il cognome dell’autore principale dell’articolo con il titolo più lungo tra quelli inseriti
1. Si inizializzi staticamente (i.e., direttamente nel codice) una variabile articolo con i seguenti valori nei rispettivi campi:
* Titolo: “An Amazing Research”
* N. Citazoni: 1000
* N. Autori: 5
* Cognome Autore Principale: “Montenegro”
1. Per ogni articolo inserito dall’utente, stampare i dati dei soli articoli con un numero di citazioni maggiori o uguali a quelle dell’articolo inizializzato staticamente
1. Si modifichi la struttura in modo tale che si salvi anche la lista dei cognomi degli autori (senza ripetere l’autore principale)
1. Si stampi il numero di autori medio degli articoli inseriti dall’utente con autore principale
1. Si stampi il numero di autori medio degli articoli inseriti dall’utente aventi almeno un autore in comune con l’articolo inizializzato staticamente
```c
#include <stdio.h>
#include <string.h>
#define N 5
#define LEN 100
int main(int argc, char* argv[]) {
// Tipo
typedef char stringa[LEN];
typedef struct {
stringa titolo;
int n_cit;
int n_autori;
stringa autore;
stringa altri_autori[LEN];
} Articolo;
// Variabili
Articolo articoli[N], articolo_statico;
int i, idx_titolo_lungo, max_len, j, n_aut_medio_N;
float n_aut_medio;
// Acquisizione dati
for (i=0; i<N; i++) {
printf("Dati articolo %d\n", i+1);
printf("Titolo: ");
gets(articoli[i].titolo);
do {
printf("Citazioni: ");
scanf("%d", &articoli[i].n_cit);
} while(articoli[i].n_cit < 0);
do {
printf("Numero di Autori: ");
scanf("%d", &articoli[i].n_autori);
} while(articoli[i].n_autori < 0);
printf("Cognome Autore Principale: ");
scanf("%s", articoli[i].autore);
fflush(stdin); // serve per evitare che la prossima gets legga quello che rimane nel buffer
// !! non sappiamo come si comporta l'utente !!
for(j=0; j<articoli[i].n_autori-1; j++){
do {
printf("Cognome Co-Autore %d: ", j+1);
scanf("%s", articoli[i].altri_autori[j]);
fflush(stdin);
} while(!strcmp(articoli[i].autore, articoli[i].altri_autori[j]));
}
}
// Stampo titolo più lungo
max_len = 0;
idx_titolo_lungo = 0;
for(i=0; i<N; i++){
if(strlen(articoli[i].titolo) > max_len){
idx_titolo_lungo = i;
max_len = strlen(articoli[i].titolo);
}
}
printf("\n'%s' ha il titolo più lungo\n", articoli[idx_titolo_lungo].titolo);
// Inizializzo l'articolo statico
strcpy(articolo_statico.titolo, "An Amazing Research");
articolo_statico.n_cit = 1000;
articolo_statico.n_autori = 1;
strcpy(articolo_statico.autore, "Montenegro");
// Stampo Dati di articoli con più citazioni dell'articolo statico
printf("\nARTICOLI CON PIU CIT DELL'ARTICOLO STATICO\n");
for(i=0; i<N; i++){
if(articoli[i].n_cit > articolo_statico.n_cit){
printf("Titolo: %s\nCitazioni: %d\nN. Autori: %d\nAutore: %s\n", articoli[i].titolo, articoli[i].n_cit, articoli[i].n_autori, articoli[i].autore);
for(j=0; j<articoli[i].n_autori-1; j++){
printf("Co-Autore %d: %s\n", j+1, articoli[i].altri_autori[j]);
}
}
}
// Stampo il numero medio di autori
printf("\nN. AUTORI MEDIO\n");
n_aut_medio = 0;
n_aut_medio_N = 0;
for(i=0; i<N; i++){
n_aut_medio += articoli[i].n_autori;
}
n_aut_medio /= N;
printf("%.2f\n", n_aut_medio);
// Stampo il numero medio di autori di articoli in cui ha partecipato Montenegro
printf("\nN. AUTORI MEDIO DI ARTICOLI IN CUI HA PARTECIPATO MONTENEGRO\n");
n_aut_medio = 0;
n_aut_medio_N = 0;
for(i=0; i<N; i++){
if(!strcmp(articolo_statico.autore, articoli[i].autore)){
n_aut_medio += articoli[i].n_autori;
n_aut_medio_N++;
}
else{
for(j=0; j<articoli[i].n_autori-1; j++){
if(!strcmp(articolo_statico.autore, articoli[i].altri_autori[j])){
n_aut_medio += articoli[i].n_autori;
n_aut_medio_N++;
}
}
}
}
n_aut_medio /= n_aut_medio_N;
printf("%.2f\n", n_aut_medio);
return 0;
}
```
---
# Confronto Studenti
Si definisca un tipo di dato `Studente` composto dai seguenti campi:
* Nome (stringa no spazi)
* Cognome (stringa no spazi)
* Età
* Sigla corso di iscrizione (stringa di 3 lettere a scelta tra “AUT”, “INF”, o “MAT”)
* Media voti
**Richieste**
1. Si scriva un programma in grado di memorizzare i dati relativi a 5 studenti inseriti dall’utente
1. Si stampi l’età media di tutti gli studenti
1. Si stampi l’età media di tutti gli studenti iscritti a “MAT”
1. Si stampi il nome e il cognome dello studente con la media più alta tra quelli iscritti a “INF”
1. Si modifichi la struttura in modo tale da aggiungere un campo `ultimitrevoti` che sia un array di dimensione 3 che salvi gli ultimi 3 voti registrati dallo studente. Si modifichi, se necessario, il codice scritto finora
1. Si stampino il nome ed il cognome di tutti gli studenti di “AUT” che abbiano come ultimi 3 voti registrati tutti voti maggiori o uguali di 29
```c
#include <stdio.h>
#include <string.h>
#define N 5
#define LEN 100
int main(int argc, char* argv[]) {
// Tipo
typedef char stringa[LEN];
typedef struct {
stringa nome;
stringa cognome;
int eta;
char corso[4];
float media;
float ultimi_voti[3];
} Studente;
// Variabili
Studente studenti[N];
int i, eta_media_N, idx_max_media, j, flag;
float eta_media, max_media;
// Acquisizione
for(i=0; i<N; i++){
printf("Studente %d\n", i+1);
printf("Nome: ");
scanf("%s", studenti[i].nome);
fflush(stdin);
printf("Cognome: ");
scanf("%s", studenti[i].cognome);
fflush(stdin);
do {
printf("Età: ");
scanf("%d", &studenti[i].eta);
} while(studenti[i].eta < 0);
do {
printf("Corso (AUT - INF - MAT): ");
scanf("%s", studenti[i].corso);
fflush(stdin);
} while (strcmp(studenti[i].corso, "AUT") && strcmp(studenti[i].corso, "INF") && strcmp(studenti[i].corso, "MAT"));
do {
printf("Media: ");
scanf("%f", &studenti[i].media);
} while(studenti[i].media < 0 && studenti[i].media > 32);
for (j=0; j<3; j++) {
do {
printf("Voto %d: ", j+1);
scanf("%f", &studenti[i].ultimi_voti[j]);
} while(studenti[i].ultimi_voti[j] < 0 && studenti[i].ultimi_voti[j] > 32);
}
}
// Stampo età media di tutti
printf("\nETA MEDIA\n");
eta_media = 0;
for(i=0; i<N; i++){
eta_media += studenti[i].eta;
}
eta_media /= N;
printf("%.2f", eta_media);
// Stampo età media degli studenti MAT
printf("\nETA MEDIA MAT\n");
eta_media = 0;
eta_media_N = 0;
for(i=0; i<N; i++){
if(!strcmp(studenti[i].corso, "MAT")){
eta_media += studenti[i].eta;
eta_media_N++;
}
}
eta_media /= eta_media_N;
printf("%.2f", eta_media);
// Stampo nome e cognome dello studente INF con media più alta
printf("\nSTUDENTE INF CON MEDIA PIù ALTA\n");
max_media = 0;
idx_max_media = -1;
for(i=0; i<N; i++){
if(!strcmp(studenti[i].corso, "INF") && studenti[i].media > max_media){
max_media = studenti[i].media;
idx_max_media = i;
}
}
if(idx_max_media != -1) printf("%s - %s\n", studenti[idx_max_media].nome, studenti[idx_max_media].cognome);
else printf("No studenti INF");
// Stampo nome e cognome degli studenti AUT con ultimi voti tutti >= 29
printf("\nSTUDENTE AUT CON ULTIMI VOTI SOPRA AL 29\n");
for(i=0; i<N; i++){
if(!strcmp(studenti[i].corso, "AUT")){
flag = 0;
for(j=0; j<3 && flag != 1; j++){
if(studenti[i].ultimi_voti[j] < 29) flag = 1;
}
if(!flag) printf("%s - %s\n", studenti[i].nome, studenti[i].cognome);
}
}
return 0;
}
```
---
# Traccia e Trasposta
**Testo**
Si scriva un programma in grado di popolare una matrice quadrata di dimensione NxN. Durante l’inserimento, programma inserisce il valore assoluto del numero inserito dall’utente
Si stampi la traccia della matrice (i.e., la somma delle componenti sulla diagonale principale)
Si stampi la matrice trasposta
**Esempio**
$A = \left[\begin{matrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9
\end{matrix}\right]$
$Trace(A) = \sum_{i=0}^{N-1}A_{i,i} = 1 + 5 + 9 = 15$
$A^{\top} = \left[\begin{matrix}
1 & 4 & 7 \\
2 & 5 & 8 \\
3 & 6 & 9
\end{matrix}\right]$
## Versione Base
```c
#include <stdio.h>
#define N 3
int main(int argc, char* argv[]) {
// Variabili
int mat[N][N], mat_T[N][N], i, j, traccia;
// Popolamento matrice solo con valori assoluti
for(i=0; i<N; i++){
for(j=0; j<N; j++){
printf("Inserire elemento mat[%d][%d]: ", i, j);
scanf("%d", &mat[i][j]);
// prendo l'opposto se necessario
if(mat[i][j] < 0) mat[i][j] = -mat[i][j];
}
}
// Calcolo traccia
traccia = 0;
for(i=0; i<N; i++){
traccia += mat[i][i];
}
printf("Traccia: %d\n", traccia);
// Traspongo
for(i=0; i<N; i++){
for(j=0; j<N; j++){
mat_T[i][j] = mat[j][i];
}
}
// Stampo trasposta
for(i=0; i<N; i++){
for(j=0; j<N; j++){
printf("%d ", mat_T[i][j]);
}
printf("\n");
}
return 0;
}
```
## Versione Ottimizzata
```c
#include <stdio.h>
#define N 3
int main(int argc, char* argv[]) {
// Variabili
int mat[N][N], mat_T[N][N], i, j, traccia;
// Popolamento matrice solo con valori assoluti
traccia = 0;
for(i=0; i<N; i++){
for(j=0; j<N; j++){
printf("Inserire elemento mat[%d][%d]: ", i, j);
scanf("%d", &mat[i][j]);
// prendo l'opposto se necessario
if(mat[i][j] < 0) mat[i][j] = -mat[i][j];
// Calcolo traccia
if(i == j) traccia += mat[i][j];
// popolo trasposta
mat_T[j][i] = mat[i][j];
}
}
printf("Traccia: %d\n", traccia);
// Stampo trasposta
for(i=0; i<N; i++){
for(j=0; j<N; j++){
printf("%d ", mat_T[i][j]);
}
printf("\n");
}
return 0;
}
```
---
# Matrice Diagonalmente Dominante
Una matrice quadrata si dice diagonalmente dominante se, per ogni riga, la somma dei valori assoluti degli elementi della riga, escluso l’elemento delle riga sulla diagonale principale, è minore del valore assoluto dell’elemento sulla diagonale principale della riga.
Scrivere un programma che permetta di inserire i valori di una matrice NxN e che verifichi se sia dominante o meno.
**Esempio**
$\left[\begin{matrix}
10 & 1 & -2\\
-1 & 10 & 2\\
3 & 5 & 10
\end{matrix}\right]$ è dominante
$\left[\begin{matrix}
10 & 1 & -2\\
-15 & 10 & 2\\
3 & 25 & 10
\end{matrix}\right]$ NON è dominante
```c
// Librerie
#include <stdio.h>
// MACRO
#define N 3
int main(int argc, char* argv[]) {
// Variabili
int mat[N][N], i, j, somma, abs, flag = 0;
// Acquisizione Matrice
for(i=0; i<N; i++){
for(j=0; j<N; j++){
printf("Inserire l'elemento in riga %d e colonna %d: ", i+1, j+1);
scanf("%d", &mat[i][j]);
}
}
// Verifica che sia diagonalmente dominante
for(i=0; i<N; i++){
// sommo i valori assoluti degli elementi tranne che di mat[i][i]
somma = 0;
for (j=0; j<N; j++) {
if(i!=j){
abs = mat[i][j];
if(abs<0) abs = -abs;
somma += abs;
}
}
// prendo il valore assoluto di mat[i][i]
abs = mat[i][i];
if(abs < 0) abs = -abs;
// controllo se non è dominante
if(somma > abs){
flag = 1;
break;
}
}
// Stampa Matrice
if(flag) printf("Non dominante\n");
else printf("Dominante\n");
return 0;
}
```
---
# Prodotto di Kronecker
Il prodotto di Kronecker tra una matrice A (NxM) e B (PxQ) è una matrice (NxP)x(MxQ) definita come:
![Screenshot_2024-10-17_alle_16.46.28](https://hackmd.io/_uploads/rkwzeDGlkx.png)
Scrivere un programma che richieda l’inserimento di valori nelle matrici A e B, che calcoli il prodotto di Kronecker e lo stampi.
```c
// Librerie
#include <stdio.h>
// MACRO
#define N 3
#define M 3
#define P 3
#define Q 3
int main(int argc, char* argv[]) {
// Variabili
int a[N][M], b[P][Q], p[N*P][M*Q], i, j, k, t;
// Acquisizione Matrici
for(i=0; i<N; i++){
for(j=0; j<M; j++){
printf("Inserire l'elemento di A in riga %d e colonna %d: ", i+1, j+1);
scanf("%d", &a[i][j]);
}
}
for(i=0; i<P; i++){
for(j=0; j<Q; j++){
printf("Inserire l'elemento di B in riga %d e colonna %d: ", i+1, j+1);
scanf("%d", &b[i][j]);
}
}
// Prodotto di Kronecker
for(i=0; i<N; i++){
for(j=0; j<M; j++){
for(k=0; k<P; k++){
for(t=0; t<Q; t++){
p[i*P + k][j*Q + t] = a[i][j] * b[k][t];
}
}
}
}
// Stampo prodotto
for(i=0; i<N*P; i++){
for(j=0; j<M*Q; j++){
printf(" %d", p[i][j]);
}
printf("\n");
}
return 0;
}
```
---
# Numero di Claque
Una claque di una matrice NxM è una sottomatrice 2x2 tale che la somma degli elementi della sua diagonale principale sia uguale alla somma degli elementi della contro-diagonale.
Si scriva un programma che prenda in input una matrice e che stampi il numero di claque della matrice stessa.
![Screenshot_2024-10-17_alle_17.12.16](https://hackmd.io/_uploads/SJjQlwflyg.png)
```c
// Librerie
#include <stdio.h>
// MACRO
#define N 3
#define M 3
int main(int argc, char* argv[]) {
// Variabili
int a[N][M], i, j, somma1, somma2, n_claque = 0;
// Acquisizione Matrice
for(i=0; i<N; i++){
for(j=0; j<M; j++){
printf("Inserire l'elemento di A in riga %d e colonna %d: ", i+1, j+1);
scanf("%d", &a[i][j]);
}
}
// Conto Claque
for(i=0; i<N-1; i++){
for(j=0; j<M-1; j++){
somma1 = a[i][j] + a[i+1][j+1]; // somma diagonale
somma2 = a[i][j+1] + a[i+1][j]; // somma contro-diagonale
if(somma1 == somma2) n_claque++;
}
}
// Stampo prodotto
printf("La matrice inserita ha %d Claque.\n", n_claque);
return 0;
}
```
---
# Somma Massima Sottomatrici
Scrivere un programma che chiede all’utente di inserire una matrice di interi 20 × 30.
Per ogni possibile dimensione B di sottomatrice quadrata, stampa un singolo intero che denota la somma massima di
una sottomatrice di dimensione B x B.
```c
#include <stdio.h>
#define ROWS 20
#define COLS 30
int main(int argc, char* argv[]) {
int matrix[ROWS][COLS];
int B, i, j, k, l, max_sum, current_sum, to_init=1;
// Inserimento della matrice 20 x 30
printf("Inserisci la matrice 20 x 30 (600 numeri interi):\n");
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
scanf("%d", &matrix[i][j]);
}
}
// Ciclo per tutte le possibili dimensioni di sottomatrice B x B
for (B = 1; B <= 20; B++) {
max_sum = 0;
to_init = 1;
// Ciclo per trovare la sottomatrice con somma massima di dimensione B x B
for (i = 0; i <= ROWS - B; i++) {
for (j = 0; j <= COLS - B; j++) {
current_sum = 0;
// Calcola la somma della sottomatrice B x B con il vertice in (i, j)
for (k = 0; k < B; k++) {
for (l = 0; l < B; l++) {
current_sum += matrix[i + k][j + l];
}
}
// Aggiorna la somma massima
if (current_sum > max_sum || to_init) {
max_sum = current_sum;
to_init = 0;
}
}
}
// Stampa la somma massima per la dimensione B x B
printf("Somma massima per sottomatrice %d x %d: %d\n", B, B, max_sum);
}
return 0;
}
```
---
# Confronto Studenti con Matrici
Modificare l’esercizio sul confronto studenti in modo tale da salvare ogni studente in una matrice di 3 righe. La prima riga della matrice ospita gli studenti di “AUT”, la seconda quelli di “INF”, la terza quella di “MAT”. Eliminare pertanto il campo sigla corso di iscrizione dalla struttura principale. Si svolgano tutti i punti dell’esercizio in questo nuovo contesto
```c
#include <stdio.h>
#include <string.h>
#define N 5
#define LEN 100
int main(int argc, char* argv[]) {
// Tipo
typedef char stringa[LEN];
typedef struct {
stringa nome;
stringa cognome;
int eta;
float media;
float ultimi_voti[3];
} Studente;
// Variabili
Studente studenti[3][N];
int i, eta_media_N, idx_max_media, j, flag, n_aut=0, n_inf=0, n_mat=0, corso, idx;
float eta_media, max_media;
// Acquisizione
for(i=0; i<N; i++){
printf("Studente %d\n", i+1);
do {
printf("Che corso fa lo studente (0=AUT, 1=INF, 2=MAT)? ");
scanf("%d", &corso);
} while (corso < 0 || corso > 2);
switch (corso) {
case 0:
n_aut++;
idx = n_aut-1;
break;
case 1:
n_inf++;
idx = n_inf-1;
break;
case 2:
n_mat++;
idx = n_mat-1;
break;
default:
idx = -1;
break;
}
printf("Nome: ");
scanf("%s", studenti[corso][idx].nome);
fflush(stdin);
printf("Cognome: ");
scanf("%s", studenti[corso][idx].cognome);
fflush(stdin);
do {
printf("Età: ");
scanf("%d", &studenti[corso][idx].eta);
} while(studenti[corso][idx].eta < 0);
do {
printf("Media: ");
scanf("%f", &studenti[corso][idx].media);
} while(studenti[corso][idx].media < 0 && studenti[corso][idx].media > 32);
for (j=0; j<3; j++) {
do {
printf("Voto %d: ", j+1);
scanf("%f", &studenti[corso][idx].ultimi_voti[j]);
} while(studenti[corso][idx].ultimi_voti[j] < 0 && studenti[corso][idx].ultimi_voti[j] > 32);
}
}
// Stampo età media di tutti
printf("\nETA MEDIA\n");
eta_media = 0;
for(i=0; i<n_aut; i++){
eta_media += studenti[0][i].eta;
}
for(i=0; i<n_inf; i++){
eta_media += studenti[1][i].eta;
}
for(i=0; i<n_mat; i++){
eta_media += studenti[2][i].eta;
}
eta_media /= N;
printf("%.2f", eta_media);
// Stampo età media degli studenti MAT
printf("\nETA MEDIA MAT\n");
eta_media = 0;
eta_media_N = 0;
for(i=0; i<n_mat; i++){
eta_media += studenti[2][i].eta;
}
if(n_mat > 0){
eta_media /= n_mat;
printf("%.2f", eta_media);
}
else{
printf("NO STUDENTI MAT\n");
}
// Stampo nome e cognome dello studente INF con media più alta
printf("\nSTUDENTE INF CON MEDIA PIù ALTA\n");
max_media = 0;
idx_max_media = -1;
for(i=0; i<n_inf; i++){
if(studenti[1][i].media > max_media){
max_media = studenti[1][i].media;
idx_max_media = i;
}
}
if(n_inf > 0) printf("%s - %s\n", studenti[1][idx_max_media].nome, studenti[1][idx_max_media].cognome);
else printf("No studenti INF");
// Stampo nome e cognome degli studenti AUT con ultimi voti tutti >= 29
printf("\nSTUDENTE AUT CON ULTIMI VOTI SOPRA AL 29\n");
for(i=0; i<n_aut; i++){
flag = 0;
for(j=0; j<3 && flag != 1; j++){
if(studenti[0][i].ultimi_voti[j] < 29) flag = 1;
}
if(!flag) printf("%s - %s\n", studenti[0][i].nome, studenti[0][i].cognome);
}
return 0;
}
```