Lezione 8: Stringhe ed array multidimensionali Vittorio Scarano Corso di Laurea in Informatica Università degli Studi di Salerno Struttura della lezione AVVISO: la lezione di laboratorio di 28/5 non si tiene Stringhe Array multidimensionali 2 1
Stringhe In C non esiste il tipo string ma le stringhe vengono trattate come array di caratteri: Una stringa è un array di caratteri terminato dal carattere ASCII 0 ( \0 ) Quindi, come per gli array, è cura del programmatore curare che la dimensione della stringa (incluso ASCII 0) non superi lo spazio allocato per l array 3 Costanti stringhe Sequenze di caratteri delimitate da doppi apici. Es. abc La costante carattere a è diversa da a la costante carattere occupa 1 byte mentre la stringa a occupa 2 bytes: uno per la a e uno per \0 Una costante stringa è trattata come un puntatore a caratteri: char *p = abcdef ;... printf ( %s %s, p, p+1); p a b c d e f \0 4 2
Array e puntatori Dichiarazione di costante stringa: char *p = abcdef ;... Dichiarazione di array di caratteri: p a b c d e f \0 char s[]= a, b, c, d, e, f, \0 ;... s a b c d e f \0 5 Una funzione conta_parole() #include <ctype.h> int conta_parole(char *s) int cnt=0; while (*s!= \0 ) while ( isspace (*s) ) ++s; if (*s!= \0 ) ++ cnt; while (! isspace (*s) && *s!= \0 ) ++s; /* end if */ /* end while */ return (cnt); Funzione che: accetta una stringa come parametro restituisce il numero di parole contenute usa una funzione (macro) isspace(c) in ctype.h Comportamento: salta i blank iniziali al primo carattere non blank conta la parola, fino al prossimo spazio o fino alla fine parola 6 3
Un esercizio: una funzione balbuziente() Una funzione che prende in input una stringa e la sua lunghezza e la restituisce con ogni carattere ripetuto tre volte. Esempio: la funzione balbuziente( abcd, 4) restituisce la stringa aaabbbcccddd Considerazioni: la funzione deve restituire una stringa: la stringa va allocata (dinamicamente) e ne deve essere restituito il puntatore. 7 La funzione balbuziente() char *balbuziente(char *s, int lung) char *res, *p; res = (char *) malloc (lung*3 +1); p = res; while (*s!= \0 ) *p++ = *s; *p++ = *s; *p++ = *s++; *p = \0 ; return (res); I parametri Due puntatori: uno per il risultato uno per inserire i nuovi caratteri presi da *s Comportamento: allocazione memoria ed inizializzazione di p triplicazione del carattere puntato da s inserimento ASCII 0 per fine stringa 8 4
Funzioni di libreria per la gestione di stringhe Per le operazioni più comuni tra stringhe esiste una libreria di funzioni Necessario includere la interfaccia alla libreria string.h Funzioni per: copiare una stringa concatenare una stringa misurare la lunghezza di una stringa etc. etc. 9 Alcune funzioni per le stringhe char *strcat ( char *s1, const char*s2) concatena s2 a s1 e restituisce s1. Lo spazio in s1 deve essere sufficiente a contenere la stringa concatenata int strcmp (const char *s1, const char *s2) confronta le stringhe e restituisce un intero = 0 se sono uguali, < 0 se s1 precede s2, > 0 se s1 segue s2 char *strcpy (char *s1, const char *s2) copia s2 in s1 e restituisce s1 (dopo la copia). Lo spazio in s1 deve essere sufficiente int strlen(const char *s1) restituisce la lunghezza di s1 10 5
Alcune implementazioni: strlen() e strcpy() unsigned strlen (char *s) register int n; for (n = 0; *s!= \0 ; ++s) n++; return n; unsigned anotherstrlen(char *s) register int n=0; while (*s++) n++; return n; char *strcpy (char *s1, const char *s2) while (*s1++ = *s2++) ; return s1; strlen (char *s) variabile register anotherstrlen (char *s) operatore postfisso di incremento del puntatore s ASCII 0 vale 0! (=FALSE) strcpy (char *s1, char *s2) assegnazione, incremento e test contemporaneo 11 Alcune implementazioni: strcat() char *strcat (char *s1, const char *s2) register char *p = s1; while (*p) ++p; while (*p++ = *s2++) ; return s1; char *wrongstrcat (char *s1, const char *s2) register char *p = s1; while (*p++) ; while (*p++ = *s2++) ; strcat (char *s1, const char *s2) sposta il puntatore locale p a fine stringa s1 copia da quella posizione tutti i caratteri (compreso il \0 finale) di s2 Perchè wrongstrcat non funziona? 12 6
Array multidimensionali In C si possono dichiarare array a più dimensioni: int a[2][6]; char f[3][5][7]; Per ognuna delle dimensioni viene allocato spazio in memoria: il totale della memoria allocata è il prodotto delle dimensioni Si può immaginare la allocazione di array bidimensionali come righe e colonne 13 Array bidimensionali a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] Un array int a[3][4] Può essere considerato come diviso in righe (primo indice) colonne (secondo indice) La memorizzazione avviene per righe 14 7
Memorizzazione per righe L array int a[3][4] memorizzato per righe L indirizzo di a[i][j]: ci si sposta di i righe ci si sposta di j posizioni Quindi, a[i][j] viene memorizzato in: posizione 4*i + j a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015............ 15 Elementi di array bidimensionali a[i] a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] int a[3][4] Come accedere a[i][j] *(a[i] +j ) (*(a+i)) [ j ] *( (*(a+i)) + j) *(&a[0][0]+4*i+j) 16 8
Passaggio di parametri di array multidimensionali main() int f [3][3];... /*input dell array f */ printf ( %d\n, sum (f)) int sum (int a [ ] [3]) int i,j, result = 0; for (i=0 ; i< 3; ++i) for (j = 0; j < 3; j++) result + = a[i] [j]; return result; Si specificano tutte le lunghezze eccetto la prima In questo modo il compilatore determina la mappa di memorizzazione 17 Inizializzazione Diverse possibilità ma sempre per righe: int a [2][3] = 1, 2, 3, 4, 5, 6; int a[2][3] = 1,2,3, 4, 5, 6 ; int a[][3] = 1,2,3, 4,5,6; 18 9
Array di puntatori Utili in diversi contesti numerici Utili per la trattazione di stringhe se char *a rappresenta un puntatore a carattere, allora char *a[10] rappresenta 10 puntatori a carattere e, quindi, char *a[10] può essere visto come un array di stringhe 19 Una funzione ordina_parole() #define N 1000 #define MAX 50 void ordina_parole (char *[ ], int); void swap (char **, char **); main() char *w[n];... for (i=0;i < N; i++)... w[i] = calloc (MAX, sizeof(char)); scanf ( %s, w[i]); /*end for*/ ordina_parole (w, N); /* output */ Prototipi: ordina_parole swap Input (banale): allocazione spazio per ogni stringa input attraverso scanf; Chiamata di ordina_parole 20 10
Una funzione ordina_parole() void ordina_parole(char *w[ ], int n) int i,j; for (i=0; i < n-1; i++) for (j=i+1; j< n; ++j) if (strcmp (w[i], w[ j ]) > 0) swap (&w[i], &w[ j ]); void swap (char ** p, char **q) char *tmp; tmp = *p; *p =*q; *q = tmp; ordina_parole confronta ogni parola se necessario le scambia Funzione swap() accetta indirizzi di puntatori a carattere effettua lo scambio 21 Come funziona lo swap void ordina_parole(char *w[ ], int n) int i,j; for (i=0; i < n; i++) for (j=i+1; j< n; ++j) if (strcmp (w[i], w[ j ]) > 0) swap (&w[i], &w[ j ]); void swap (char ** p, char **q) char *tmp; tmp = *p; *p =*q; *q = tmp; w[i] w[j] a c f \0 a f a g \0...... 22 11
Parametri di main() main() rappresenta una funzione (come le altre) tranne che: viene eseguita per prima riceve i parametri dalla linea di comando Per passare i parametri a main si specifica il numero di parametri i parametri (come un array di stringhe) 23 Passaggio di parametri a main int main(int argc, char *argv[ ]) int i; printf ( argc=%d\n, argc); for (i = 0; i < argc ; i++) printf ( %s, argv[i]); Vengono specificati argc numero argom argv array stringhe file eseguito è argv[0]: Se non si passa alcun parametro argc vale 1 e quindi stampa solo. Se si digita: a.out uno due tre il programma si comporta come echo ma stampa anche a.out 24 12
Esercizi Scrivere un insieme di funzioni su array dinamici di interi che effettuino: la ricerca del minimo, del massimo l input e l output la somma degli elementi l ordinamento per tutto o solo parte dell array. Si organizzi un programma a menù che effettui tutte queste operazioni a scelta dell utente 25 Esercizi Scrivere un programma che prende in input sulla linea di comando delle stringhe e le restituisce in ordine alfabetico Scrivere un programma che faccia giocare 2 giocatori a Tris un array 3x3 dove lo scopo del giocatore è quello di mettere il proprio simbolo su riga, colonna o diagonale 26 13