slides
Transcript
slides
Università degli studi di Camerino Scuola di scienze e tecnologia - Sezione Informatica Programmazione C Massimo Callisto De Donato [email protected] www.cs.unicam.it/massimo.callisto LEZIONE 5 – ARRAY & STRINGHE A.A. 2011/12 Array • Un array (vettore) rappresenta una collezione di dati dello stesso tipo identificati da indici progressivi che identificano la posizione. • Gli array sono 0-index ovvero da 0 .. N – 1. E.s: per N=6 implica un intervallo di indici in [0 .. 5] • Se si esce fuori dal limite il comportamento non è prevedibile. • Sintassi: tipo nome_variabile[DIMENSIONE_MAX]; • Esempio: int a[6]; Esempi • Inizializzazione tramite dati immessi dall’utente int i; for (i = 0; i < 6; i++){ printf(„„Inserisci un intero: "); scanf(„„%d", &a[i]); } • Ricerca del massimo int max = a[0]; for (i = 1; i < 6; i++) if (a[i] > max) max = a[i]; printf(„„Valore massimo: %d\n", max); • Calcolo della media dei valori int somma = 0; float media; for (i = 0; i < 6; i++) somma = somma + a[i]; media = somma / 6; • Possiamo anche inizializzare l’array nella definizione: int somma[] = {11,22,34,14,35,566}; Esempio: n concorrenti • N concorrenti. • Ogni concorrente sostiene 2 prove. • Il punteggio corrisponde alla media aritmetica dei risultati delle due prove. • Creare una tabella che mostri: – Risultato 1° prova – Risultato 2° prova – Punteggio finale Esempio: n concorrenti #include <stdio.h> #define MAX CONC 100 // MAX CONCORRENTI main() { /* 3 vettori: 1 e 2 prova e risultati */ float prova1[MAX CONC], prova2[MAX CONC], totali[MAX CONC]; int i, n; /* Inserimento numero concorrenti */ do { printf(„„Inserire numero concorrenti: "); scanf(„„%d", &n); } while ((n < 1) k (n > MAX CONC)) /* Inserimento punteggi */ for (i=0; i < n; i++){ printf(„„\nConcorrente %d\n", i+1); printf(„„Risultato prima prova: "); scanf(„„%f", &prova1[i]); printf(„„Risultato seconda prova: "); scanf(„„%f", &prova2[i]); } /* calcolo media dei punteggi */ for (i=0; i < n; i++) totale[i]=(prova1[i] + prova2[i]) /2 ); /* classifica */ for (i=0; i < n; i++) { printf(„„%f\t‟‟, prova1[i]); printf(„„%f\t‟‟, prova2[i]); printf(„„%f\n‟‟, totale[i]); } } // main Se volessimo stampare l’indice(i) del vincitore(i) con relativo punteggio? Esempio: array + switch #include <stdio.h> main(){ char espress[30]; int pg,pq,pt, c; printf("\nEspressione algebrica "); gets(espress); pg=pq=pt=0; for(c=0; c<30 && espress[c]!='\0';c++) { switch(espress[c]) { case '{„: case '}': pg++; break; case '[': case ']': pq++; break; case '(':; case ')': pt++; break; }; }; printf("\nG = %d\nQ = %d\nT = %d",pg, pg, pt); } Esempio: somma incrociata • Dati due vettori a e b di lunghezza N. • Calcolare la somma incrociata degli elementi in un vettore c. • Per somma incrociata intendiamo che gli elementi di c sono: (a[0] + b[N-1], a[1] + b[N-2], ..., a[N-1] + b[0]) Esempio: somma incrociata /* Somma incrociata (a[0] + b[N-1], a[1] + b[N-2], ..., a[N-1] + b[0]) */ #define N 6 main () { int a[N], b[N], c[N]; int i, j; for (i=0; i < N; ++i){ // Per a printf("Inserisci l'elemento numero %d: ", i+1); scanf("%d", &a[i]); } for (i=0; i < N; ++i){ // Per b printf("Inserisci l'elemento numero %d: ", i+1); scanf("%d", &b[i]); } for (i = 0; i < N; ++i) c[i] = a[i] + b[N - 1 -i]; printf(“Vettore c = "); for (i = 0; i < N; ++i) printf("%d\t", c[i]); } Array bidimensionali: matrici • Array bidimensionale (matrice): righe e colonne. • Sintassi: tipo nome array[DIMENSIONE RIGHE][DIMENSIONE COLONNE]; E.s.: int matrice[4][3]; • Un elemento si identifica con il doppio indice compresi in [0 .. r - 1] e [0 .. c - 1] (righe – colonne). • Esempi su array bidimensionali: Array multi-dimensionali • Possiamo avere dimensioni arbitrarie: tipo nome_array[DIM 1][DIM 2] ... [DIM N]; • Esempio: memorizzare i ricavi ottenuti dalla vendita di 10 prodotti in 5 punti vendita nei dodici mesi dell’anno. int marketing[10][5][12] • Ricavi ottenuti dalla vendita del terzo prodotto nel quarto punto vendita nel mese di ottobre: marketing[2][3][10] Esempio: inizializzazione #include <stdio.h> main(){ int mat[4][3]; int i,j; printf(„„\n\nCaricamento della matrice\n\n"); for(i = 0; i < 4; i++) for(j = 0; j < 3; j++){ printf(„„El. di riga %d e colonna %d: ", i+1, j+1); scanf(„„%d", &mat[i][j]); } printf(„„\n\nVisualizzazione matrice\n\n"); for(i = 0; i < 4; i++){ printf(„„\n‟‟); for(j = 0; j < 3; j++) printf(„„%d\t", mat[i][j]); } } Esempio: prodotto matrici • Date due matrici mat_1[N][P] e mat_2[P][M], calcolare la matrice prodotto pmat[N][M]. • Ogni elemento pmat[i][j] (con i = 1..N e j = 1..M) è definito da: Esempio: prodotto matrici /* prodotto di matrici */ #include <stdio.h> main () { int N = P = 2, M = 3 int mat1[N][P], mat2[P][M]; int pmat[N][M]; int i, j, k, somma; printf("Matrice A (%d x %d) \n\n", N, P); for (i=0; i < N; i++) for (j=0; j < P; j++){ printf(“Riga %d e colona %d: ", i, j); scanf("%d", &mat1[i][j]); } printf("Matrice B (%d x %d) \n\n", P, M); for (i=0; i < P; i++) for (j=0; j < M; j++){ printf(“Riga %d e colona %d: ", i, j); scanf("%d", &mat2[i][j]); } //Calcolo del prodotto for (i=0; i < N; i++) for (j=0; j < M; j++){ somma = 0; for (k=0; k < P; k++){ somma = somma + (mat1[i][k] * mat2[k][j]); } pmat[i][j] = somma; } //Visualizzazione prodotto // (A e B analogo) printf("\n\nMatrice prodotto\n\n"); for (i=0; i < N; i++){ printf("\n"); for (j=0; j < M; j++) printf("%d ", pmat[i][j]); } } // chiuso main Altri esercizi 1. Data una matrice mat_1[N][P] calcolare la matrice trasposta mat_2[P][M]. 2. Controllare se una matrice A è a diagonale dominante in senso debole per righe: gli elementi diagonali di A sono ≥ in valore assoluto della somma di tutti i restanti elementi della stessa riga (in valore assoluto). 3. Considerare la variante a senso stretto ovvero controllando l’uguaglianza > . Le stringhe • Si lavora spesso su gruppi di caratteri che nell’insieme sono chiamati stringa. • In C non c'è un tipo specifico per le stringhe. Esse sono array di caratteri char terminati con il carattere speciale “\0”: char str[5]; char str[] = “ciao”; • La dimensione in memoria degli array nei due casi è uguale.. Perché? • Il carattere nullo ‘\0’ serve al compilatore per capire dove finisce la stringa. str C I A O \0 Le stringhe • Modi equivalenti di dichiarare una stringa: char str[] = “ciao”; char str[] = {„c‟, „i‟, „a‟, „o‟, „\0‟} • Vale anche questo ma non si dovrebbe fare: char str[] = {„c‟, „i‟, „a‟, „o‟}; • Chiaro ora che „A‟ è diverso da “A”! Le stringhe • La quantità di memoria occupato dell’array che contiene la stringa viene fissata all’inizio ed è non modificabile. char str[] = “ciao”; char str[] = {„c‟, „i‟, „a‟, „o‟, „\0‟} char str[5]; str[0] = „c‟; str[1] = „i‟; str[2] = „a‟; str[3] = „o‟; str[4] = „\0‟; Esempio si riempimento #include <stdio.h> main() { char c1[100]; char c2[] = {'p','i','p', 'p', 'o', '\0'}; c1[0] c1[1] c1[2] c1[3] c1[4] c1[5] c1[6] = = = = = = = 'c'; 'a'; 's'; 'a'; 'm'; 'i'; 'a'; printf("Lunghezza di 'c1': %d, di 'c2': %d\n", strlen(c1), strlen(c2)); c1[0] = 'c'; c1[1] = 'a'; c1[2] = 's'; printf("Lunghezza di 'c1': %d, di 'c2': %d\n", strlen(c1), strlen(c2)); c1[0] c1[1] c1[2] c1[3] = = = = 'c'; 'a'; 's'; '\0'; printf("Lunghezza di 'c1': %d, di 'c2': %d\n", strlen(c1), strlen(c2)); return 0; } Le stringhe • Le stringhe non sono un tipo di dato primitivo. Non sono supportate le operazioni dirette come: Copia? Concatenazione? Comparazione? • Soluzione: – ce le facciamo a mano – usiamo le funzioni di libreria (se esistono) • Esercizio: come facciamo a contare gli spazi contenuti in una stringa? I caratteri ‘\n’? Stringhe: copia e concatenazione #include <stdio.h> #define LEN 100 main () { int i, j; char c, s1[LEN], s2[LEN]; do{ printf(“Cosa vuoi fare? [0-copia,1-concatena]”) c=getchar(); }while(c!= „0‟ or „1‟); /* immissione stringhe */ printf("Inserisci le due stringhe separate da uno spazio\n"); scanf("%s %s", s1, s2); switch(c){ case „0‟: for (i=0; (s1[i]=s2[i]) != '\0'; i++); break; case „1‟: for (i=0; s1[i]!='\0'; i++); for (j=0; (s1[i]=s2[j])!='\0'; j++, i++); break; } printf(“S1: %s\nS2: %s", s1, s2); } // C‟è qualche problema potenziale su LEN? Stringhe: comparazione #include <stdio.h> #define LEN 100 main () { int i, flag; char s1[LEN], s2[LEN]; /* immissione stringhe */ printf("Inserisci le due stringhe separate da spazio\n"); scanf("%s %s", s1, s2); i=0;flag = 0; while ((s1[i] !='\0') && (s2[i] != '\0')){ if(s1[i] != s2[i]){ flag = (s1[i] < s2[i]) ? -1: 1; break; } i++; } if (flag == -1) printf("%s e' minore di %s\n", s1, s2); else if (flag == 1) printf("%s e' maggiore di %s\n", s1, s2); /* se flag=0, allora o entrambe le stringhe sono arrivate a '\0', oppure qualcuna è arrivata prima dell'altra. */ else if (!flag){ if ( (s1[i] == '\0') && (s2[i] == '\0') ) printf("Le due stringhe %s e %s sono uguali\n", s1, s2); else if (s1[i] == '\0') printf("%s e' minore di %s\n", s1, s2); else printf("%s e' maggiore di %s\n", s1, s2); } } // Il controllo è case-sensitive… Per farne uno non case-sensitive? Le stringhe palindrome • Facciamo un programma che controlla se due stringhe sono “palindrome”. se, messa al contrario, si legge come l’originale. Stringhe: palindrome #include<stdio.h> #define LEN 100 main () { char stringa[LEN]; int i, j; int len, palindroma = 1; printf("Inserisci una frase: "); scanf("%s", stringa); for(i=0; stringa[i] != '\0'; i++){} len = i; i--; j = 0; while(palindroma && (j < (len/2))){ if (stringa[i] != stringa[j]) palindroma = 0; j++; i--; } if (palindroma) printf("palindroma\n"); else printf("non palindroma\n"); } Stringhe e tabella ASCII • Tutti gli esempi visti sono case-sensitive. • Possiamo usare la tabella ASCII per creare programmi non-case-sensitive. • Osservazione: tutte le lettere alfabetiche MAIUSCOLE sono comprese tra 65 (‘A’) e 90(‘Z’), distanziate dal valore 32 dalla rispettiva versione minuscola (‘a’..’z’). • Anche i numeri hanno un intervallo specifico… Stringhe e tabella ASCII Stringhe: esercizi • Come possiamo cambiare il programma per le stringhe palindrome affinché “Anna” sia uguale ad “aNnA”? • Come si può fare per convertire una stringa in maiuscola? • Fare un programma “calcolatrice” che usi solo getchar() e realizzi le 4 operazioni fondamentali. Stringhe: esercizi • string.h: contiene delle funzioni standard che consentono di manipolare le stringhe. Alcune sono molto simili a quelle viste finora. • Funzioni principali di string.h strcpy(str1, str2) copia str2 in str1 strlen(str1) ritorna la lunghezza di str1 strncpy(str1, str2, n) copia i primi n caratteri di str2 in str1 strcat(str1, str2) concatena str2 a str1 strcmp(str1, str2) confronta str1 con str2, restituisce zero se le due stringhe sono uguali, un valore negativo se str1 è minore di str2, un valore positivo altrimenti • Queste di seguito in stdlib.h atoi(str) e atof(str)convertono str in un intero e in un decimale rispettivamente • Guardate il resto su Open Group