s STRINGHE DI CARATTERI a p e \0

Slides:



Advertisements
Presentazioni simili
I tipi Strutturati.
Advertisements

Corso di Fondamenti di Programmazione canale E-O
INFORMATICA Altre Istruzioni di I/O
Argomenti della lezione
Nel C non esiste un dato primario di tipo stringa; queste sono rappresentate con un array monodimensionale di caratteri (tipo char). Così per definire.
String c++.
Stringhe di caratteri In linguaggio C.
Introduzione al linguaggio C
Capitolo 10 Tecniche algoritmiche Algoritmi e Strutture Dati.
Caratteri e stringhe di caratteri
Funzioni definite dall’utente
Corso di Fondamenti di programmazione a.a.2009/2010
Esercizi di esonero (a.a. 2007/2008) Compito C, terzo esercizio Data una sequenza di caratteri s1 ed una stringa s2 diciamo che s1 è contenuta in s2 se.
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Stringhe e Puntatori Marco D. Santambrogio – Ver. aggiornata al 18 Marzo 2013.
Process synchronization
Allocazione dinamica della memoria
Corso di Informatica (Programmazione)
1 Corso di Informatica (Programmazione) Lezione 13 (21 novembre 2008) Programmazione in Java: stringhe e array.
Array Un array è una collezione in sequenza di variabili del medesimo tipo Riferimento con un nome comune Nome_studente1 Nome_studente2. Nome_studenteN.
Argomenti della lezione
Funzioni di Libreria per le stringhe DICHIARAZIONI CONTENUTE NEL FILE: char *strcpy( char *dest, const char *sorg ); Copia sorg in dest, incluso il carattere.
Esercizi su pile Scrivere una funzione che restituisca una nuova pila che contiene i valori di una pila in ingresso in ordine inverso. La pila originale.
Esempi di riuso del codice nei linguaggi di alto livello Lab Programmazione - turno /2006.
Esercizio: Copiare un file in un nuovo file mediante le funzioni read e write.
A.A. 2010/2011Ambienti di Programmazione per il Software di Base1 (Es. – 6) Ambienti di Programmazione per il Software di Base Le Stringhe in C Input.
Esercizi FUNZIONI Passaggio di parametri per valore, variabili e tipi locali e globali, prototipo.
Politecnico di Milano Esercizi Stringhe Ricerca binaria.
Politecnico di Milano Esercizi Preparazione alla prima prova intermedia.
Esercizi C su array e matrici
I File.
Le funzioni.
Java base III: Array e Stringhe
AN FI Array Array in Java. AN FI Array Dichiarazione di array in Java [ ]; //oppure u [] ; int a[]; int[] a; u La dimensione non è specificata.
PUNTATORI Un puntatore è una variabile destinata a contenere lindirizzo di unaltra variabile Vincolo di tipo: un puntatore a T può contenere solo lindirizzo.
FUNZIONI... Una funzione permette di dare un nome a una espressione rendendola parametrica float f(){ return * sin(0.75); } float f1(int x) { return.
TIPI DI DATO Un tipo di dato T è definito come: un dominio di valori, D un insieme di funzioni F 1,..,F n sul dominio D un insieme di predicati P 1,..,P.
Programmazione in Java Claudia Raibulet
Algoritmi e strutture dati
Il linguaggio C Le funzioni C Language Il passaggio dei parametri
void binario(int n); …………………
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array e stringhe Marco D. Santambrogio – Ver. aggiornata al 9 Agosto 2013.
Esercizi su File e Liste
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
28 ottobre Mergesort F. Bombi 28 ottobre 2003.
Ricerca sequenziale in un array di interi
Complessità di un algoritmo
Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni – BCOR Ingegneria Elettronica – BELR Introduzione al C Esercitazione 5 D. Bloisi, A.
GLI ARRAY MONODIMENSIONALI. Utilizzando le nostre attuali conoscenze, proviamo a risolvere il seguente problema: Calcolare la media dei voti conseguiti.
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Puntatori e Stringhe.
Vettori, indirizzi e puntatori Finora abbiamo usato gli indirizzi nel chiamare  la funzione scanf()  le altre funzioni per riferimento Tuttavia la vera.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Ottobre 2014.
Università di Torino – Facoltà di Scienze MFN Corso di Studi in Informatica Programmazione I - corso B a.a prof. Viviana Bono Blocco 7 – Array.
Ordinamento in tempo lineare Il limite inferiore Ω(n log n) vale per tutti gli algoritmi di ordinamento generali, ossia per algoritmi che non fanno alcuna.
CORSO DI PROGRAMMAZIONE II
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array e “stringhe” Marco D. Santambrogio – Ver. aggiornata al 8 Aprile 2015.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array e “stringhe” Marco D. Santambrogio – Ver. aggiornata al 26 Marzo 2014.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Operatori di incremento e decremento
Informatica 6 Tipi di dato. Nelle celle di memoria di un calcolatore ci sono solo “0” e “1”, fisicamente realizzati tramite due diversi livelli di tensione.
Sommario Oggetti immutabili e non Tipi Primitivi: String, Arrays.
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 8 Aprile 2015.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array e “stringhe” Marco D. Santambrogio – Ver. aggiornata al 14 Marzo 204.
Stringhe Una stringa è un vettore di char con un carattere costante \0 che indica la fine della stringa il terminatore rende differenti gli array di char.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array e “stringhe” Marco D. Santambrogio – Ver. aggiornata al 28 Ottobre 2014.
30/10/01Array 1  Un array e’ una struttura dati che contiene piu’ valori del medesimo tipo.  La lunghezza di un array e’ stabilita quando l’array viene.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array n-dimensionali e tipi di dati strutturati Marco D. Santambrogio – Ver. aggiornata.
comprensione e modifica di codice
Transcript della presentazione:

s STRINGHE DI CARATTERI a p e \0 Una stringa di caratteri in C è un array di ca- ratteri terminato dal carattere '\0' Un vettore di N caratteri può dunque ospitare stringhe lunghe al più N-1 caratteri, perché una cella è destinata al terminatore '\0'. a p e \0 s 1 2 3

s STRINGHE DI CARATTERI d i \0 Un array di N caratteri può ben essere usato per memorizzare stringhe più corte In questo caso, le celle oltre la k-esima (k essendo la lunghezza della stringa) sono concettualmente vuote: praticamente sono inutilizzate e contengono un valo- re casuale. d i \0 s 1 2 3

STRINGHE DI CARATTERI char s[4] = "ape" ; Una stringa di caratteri si può inizializzare, come ogni altro array, elencando le singole componenti: char s[4] = {'a', 'p', 'e', '\0'}; oppure anche, più brevemente, con la forma compatta seguente: char s[4] = "ape" ; Il carattere di terminazione ‘\0’ è automaticamente incluso in fondo. Attenzione alla lunghezza!

ESEMPIO Problema: Data una stringa di caratteri, calcolarne la lunghezza. Ipotesi: La stringa è “ben formata”, ossia correttamente terminata dal carattere ‘\0’. Specifica: scandire la stringa elemento per elemento, fino a trovare il terminatore ‘\0’ (che esiste certamente) il risultato è l’indice corrispondente al terminatore.

Non occorre dare una dimensione esplicita, data la presenza del terminatore. ESEMPIO int lunghStr( char s[] ) { int lung=0; for (lung=0; s[lung]!='\0'; lung++); return lung; }

Esempio: LUNGHEZZA DI UNA STRINGA Nel trasferimento di una stringa ad una procedura o funzione, non occorre un argomento intero che rappresenta la dimensione logica, data la presenza per ipotesi del terminatore Esempio: LUNGHEZZA DI UNA STRINGA int lunghStr( char s[] ) { int lung=0; for (lung=0; s[lung]!='\0'; lung++); return lung; }

ESEMPIO Problema: Data una stringa di caratteri, copiarla in un altro array di caratteri (di lunghezza non inferiore). Ipotesi: La stringa è “ben formata”, ossia correttamente terminata dal carattere ‘\0’. Specifica: scandire la stringa elemento per elemento, fino a trovare il terminatore ‘\0’ (che esiste certamente) nel fare ciò, copiare l’elemento nella posizione corrispondente dell’altro array.

void copiaStr( char s1[],char s2[] ) { //IPOTESI: //1) s1 e s2 hanno la stessa dimensione fisica //2) s1 è l’ingresso, s2 è l’uscita int i=0; for (i=0; s1[i]!='\0'; i++) s2[i] = s1[i]; s2[i] = '\0'; } Al termine, occorre garantire che anche la nuova stringa sia “ben formata”, inserendo esplicitamente il terminatore.

Problema Data una stringa, copiarla in un array di caratteri, con eventuale troncamento se la stringa è più lunga dell’array dato. Specifica: scandire la stringa elemento per elemento, o fino a trovare il terminatore ‘\0’ (che esiste certamente), o fino alla lunghezza dell’array di destinazione (-1) nel fare ciò, copiare l’elemento nella posizione corrispondente dell’altro array.

La condizione è i<N-1 perché deve rimanere uno spazio per ‘\0’ ESEMPIO Si prosegue solo se non si è incontrato il terminatore e inoltre c’è spazio nell’array destinazione Codifica: #define N 20 main() { char s[] = "Nel mezzo del cammin di"; char s2[N]; int i=0; for (i=0; s[i]!='\0' && i<N-1; i++) s2[i] = s[i]; s2[i] = '\0'; } La condizione è i<N-1 perché deve rimanere uno spazio per ‘\0’

ESEMPIO Problema: Date due stringhe di caratteri, decidere quale precede l’altra in ordine alfabetico. Rappresentazione dell’informazione: poiché vi possono essere tre risultati (s1<s2, s1==s2, s2<s1), un boolean non basta possiamo usare: due boolean (uguale e precede) tre boolean (uguale, s1precedes2, s2precedes1) un intero (negativo, zero, positivo) scegliamo la terza via.

ESEMPIO Problema: Date due stringhe di caratteri, decidere quale precede l’altra in ordine alfabetico. Specifica: scandire uno ad uno gli elementi di egual posizione delle due stringhe, o fino alla fine delle stringhe, o fino a che se ne trovano due diversi nel primo caso, le stringhe sono uguali nel secondo, sono diverse nel secondo caso, confrontare i due caratteri così trovati, e determinare qual è il minore la stringa a cui appartiene tale carattere precede l’altra

la costante stringa continua a capo ESEMPIO la costante stringa continua a capo Codifica: main() { char s1[] = "Sempre caro mi fu quell’\ ermo colle"; char s2[] = "Sempre odiai quell’orrido\ colle"; int i, stato; for (i=0; s1[i]!='\0' && s2[i]!='\0' && s1[i]==s2[i] ; i++); stato = s1[i]-s2[i]; } negativo  s1 precede s2 positivo  s2 precede s1 zero  s1 è uguale a s2

UNA RIFLESSIONE Nell’esempio della copiatura: Data una stringa di caratteri, copiarla in un altro array di caratteri (di lunghezza non inferiore). abbiamo deciso di copiare la stringa nell’ar- ray carattere per carattere. Avremmo potuto fare diversamente? Perché non copiarla “tutta in un colpo”?

IL CONTROESEMPIO s2 = s; Perché non fare così? main() { char s[] = "Nel mezzo del cammin di"; char s2[40]; s2 = s; } Perché non dovrebbe funzionare??? PERCHÉ GLI ARRAY NON POSSONO ESSERE MANIPOLATI “IN TOTO” !

ERRORE DI COMPILAZIONE: incompatible types in assignment !! IL CONTROESEMPIO Perché non fare così? main() { char s[] = "Nel mezzo del cammin di"; char s2[40]; s2 = s; } ERRORE DI COMPILAZIONE: incompatible types in assignment !!

ARRAY “VISTI DA VICINO” Concettualmente, un array è una collezione finita di N variabili dello stesso tipo, ognuna identificata da un indice compreso fra 0 e N-1 v 1 2 3 v[0] v[1] v[2] v[3] Praticamente, le cose non stanno proprio così.

ARRAY “VISTI DA VICINO” In C un array è in realtà un puntatore costante che punta a un’area di memoria pre-allocata, di dimensione prefissata. v 1 2 3  Pertanto, il nome dell’array è un sinonimo per il suo indirizzo iniziale: v  &v[0]  

CONSEGUENZA Il fatto che il nome dell’array indichi non l’array in sé, ma l’indirizzo iniziale dell’area di memoria ad esso associata ha una importante conseguenza: È impossibile denotare un array nella sua globalità, in qualunque contesto.

CONSEGUENZA Quindi, non è possibile: assegnare un array a un altro (s2 = s) che una funzione restituisca un array E soprattutto: passare un array come parametro a una funzione non significa affatto passare l’intero array !!

IL CONTROESEMPIO s2 = s; Ecco perché non si compilava! main() { char s[] = "Nel mezzo del cammin di"; char s2[40]; s2 = s; } Questo assegnamento viene interpretato come il tentativo di cambiare l’indirizzo iniziale della stringa s2, cosa eviden- temente impossibile !!!

ARRAY PASSATI COME PARAMETRI Poiché un array in C è un puntatore costante che punta a un’area di memoria pre-allocata, di dimensione prefissata, il nome dell’array: non rappresenta l’intero array è un alias per il suo indirizzo iniziale (v  &v[0]  ) v 1 2 3 

ARRAY PASSATI COME PARAMETRI Quindi, passando un array a una funzione: non si passa l’intero array !! si passa solo (per valore!) il suo indirizzo iniziale (v  &v[0]  ) v 1 2 3  w

ARRAY PASSATI COME PARAMETRI Conclusione: agli occhi dell’utente, l’effetto finale è che l’array passa per riferimento!! v 1 2 3  w

CONCLUSIONE A livello fisico: il C passa i parametri sempre e solo per valore nel caso di un array, si passa il suo indiriz-zo iniziale (v  &v[0]  ) perché tale è il significato del nome dell’array A livello concettuale: il C passa per valore tutto tranne gli array, che vengono trasferiti per riferimento.

ESEMPIO Problema: Data una stringa di caratteri, scrivere una funzione che ne calcoli la lunghezza. Codifica: int lunghezza(char s[]) { int lung=0; for (lung=0; s[lung]!='\0'; lung++); return lung; } La dimensione non serve, perché tanto viene passato solo l’indirizzo iniziale (non tutto l’array)

UN’ALTRA RIFLESSIONE Ma se quello che passa è solo l’indirizzo iniziale dell’array, che è un puntatore... ...allora tanto vale adottare direttamente la notazione a puntatori nella intestazione della funzione!! In effetti, l’una o l’altra notazione sono, a livel- lo di linguaggio, assolutamente equivalenti non cambia niente nel funzionamento si rende solo più evidente ciò che accade comunque

ESEMPIO Da così... int lunghezza(char s[]) { int lung=0; for (lung=0; s[lung]!='\0'; lung++); return lung; } … a così: int lunghezza(char *s) { Per il C è identico!!

UN’ULTIMA RIFLESSIONE Ma se le due notazioni char *s char s[] sono identiche agli occhi del compilatore, Cosa possiamo dire dei due operatori * e [] ? C’è qualche relazione?

OPERATORI DI DEREFERENCING L’operatore *, applicato a un puntatore, accede alla variabile da esso puntata L’operatore [], applicato a un nome di array e a un intero i, accede alla i-esima variabile dell’array Sono entrambi operatori di dereferencing *v  v[0]

ARITMETICA DEI PUNTATORI Oltre a *v  v[0], vale anche: *(v+1)  v[1] ... *(v+i)  v[i] Espressioni della forma p+i vanno sotto il nome di aritmetica dei puntatori, e denota-no l’indirizzo posto i celle dopo l’indirizzo denotato da p (celle, non bytes!)

ARITMETICA DEI PUNTATORI Più in generale: se p è un puntatore a T, e n è un intero positivo, l’espressione p+n denota un altro puntatore a T, che punta “n celle dopo” l’indirizzo puntato da p Se n è negativo, la cella denotata da p+n in realtà precede di n posizioni quella puntata da p.

ARITMETICA DEI PUNTATORI q = p+n (n>0) p  q +n*size size

ARITMETICA DEI PUNTATORI Analogamente, se q e p sono puntatori a T, l’espressione q-p denota un intero, che rappresenta il numero di celle comprese fra q e p se q precede p, l’intero denotato è negativo. NB: somme di puntatori, come p+q, sono illegali in quanto prive di significato.

CONCLUSIONE *(v+i)  v[i] Gli operatori * e []sono intercambiabili Ne basterebbe uno solo: il C li fornisce entrambi solo per nostra comodità in effetti, operare sui vettori scrivendo *(v+i) sarebbe poco pratico! Internamente, il compilatore C converte ogni espressione con [] nella corrispon-dente espressione con *

int findMax(int v[], int dim); ESEMPIO Problema: Scrivere una funzione che, dato un array di N interi, ne calcoli il massimo. Si tratta di riprendere l’esercizio già svolto, e impostare la soluzione come funzione anziché codificarla direttamente nel main. Dichiarazione della funzione: int findMax(int v[], int dim);

ESEMPIO main() { int max, v[] = {43,12,7,86}; max = findMax(v, 4); } Il cliente: main() { int max, v[] = {43,12,7,86}; max = findMax(v, 4); } Trasferire esplicitamente la dimensione dell’array è NECESSARIO, in quanto la funzione, ricevendo solo l’indirizzo iniziale, non avrebbe modo di sapere quanto è lungo l’array !

ESEMPIO int findMax(int v[], int dim) { int i, max; La funzione: int findMax(int v[], int dim) { int i, max; for (max=v[0], i=1; i<dim; i++) if (v[i]>max) max=v[i]; return max; }

ESEMPIO int findMax(const int v[], int dim) { int i, max; La funzione: int findMax(const int v[], int dim) { int i, max; for (max=v[0], i=1; i<dim; i++) if (v[i]>max) max=v[i]; return max; } Per evitare che la funzione modifichi l’array (visto che è passato per riferimento), si può imporre la qualifica const Se lo si tenta: cannot modify a const object

… e la si può anche mischiare con l’altra! ESEMPIO La funzione: int findMax(const int *v, int dim) { int i, max; for (max=v[0], i=1; i<dim; i++) if (v[i]>max) max=v[i]; return max; } Volendo si può usare anche la notazione a puntatore: tanto, per il linguaggio sono equivalenti!! … e la si può anche mischiare con l’altra!

ESEMPIO Problema: Data una stringa di caratteri, scrivere una funzione che ne calcoli la lunghezza. Codifica: int lunghezza(char s[]) { int lung=0; for (lung=0; s[lung]!='\0'; lung++); return lung; } Nel caso delle stringhe, la dimensione non serve perché può essere dedotta dalla posizione dello ‘\0’

Sfrutta l’aritmetica dei puntatori UNA VARIANTE Da così... int lunghezza(char *s) { int lung=0; for (lung=0; s[lung]!='\0'; lung++); return lung; } … a così: char *s0 = s; while (*s!='\0') s++; return s-s0; Sfrutta il fatto che s è una copia del- l’indirizzo iniziale della stringa, ergo si può modificare! Sfrutta l’aritmetica dei puntatori

UNA VARIANTE “DA HACKER” Uno hacker la compatterebbe prima così... int lunghezza(char *s) { char *s0 = s; while (*s) s++; return s-s0; } … e poi così: while (*s++); Il test “diverso da 0” è tautologico! Il post-incremento può essere inglobato.

ESEMPIO Problema: Scrivere una procedura che copi una stringa in un’altra. Codifica: void strcpy(char dest[], char source[]) { while (*source) { *dest = *(source++);} *dest = '\0'; }

LIBRERIA SULLE STRINGHE Il C fornisce una nutrita libreria di funzioni per operare sulle stringhe: #include < string.h > Include funzioni per: copiare una stringa in un’altra (strcpy) concatenare due stringhe (strcat) confrontare due stringhe (strcmp) cercare un carattere in una stringa (strchr) cercare una stringa in un’altra (strstr) ...

ARRAY MULTIDIMENSIONALI È anche possibile definire matrici e, più in generale, array a più dimensioni int matrice[N][M]; N indica il numero di righe numerate da 0 a N-1 M indica il numero di colonne numerate da 0 a M-1

ARRAY MULTIDIMENSIONALI Per selezionare la cella di indici i, j: x = matrice[i][j]; Attenzione: matrice[i,j] ha un altro significato!! l’espressione i,j denota un solo numero (j), non la coppia di indici necessaria! matrice[k] denota l’intera riga k non c’è modo di denotare un’intera colonna

ARRAY MULTIDIMENSIONALI Esempio (somma elementi di una matrice) main(){ float m[4][4] = { {1,2,3,4}, {5,6,7,8}, {4,3,2,1}, {9,8,7,6}}; float somma = 0; int i,j; for (i=0;i<4;i++) for (j=0;j<4;j++) somma += m[i][j]; }

ARRAY MULTIDIMENSIONALI E per passarli a una funzione? il C passa sempre solo l’indirizzo iniziale però, nella funzione occorre specificare tutte le dimensioni successive alla prima int f(int mm[4][4], int n, int m) { ... } int f(int *mm[4], int n, int m) {

ARRAY MULTIDIMENSIONALI Perché occorre specificare le dimensioni successive alla prima? perché un array multidimensionale è, di fatto, un array di array è visto come un array di N “cose”, ciascuna delle quali, in effetti, è un altro array per distinguere dove cominciano le diverse righe, bisogna sapere quanto sono grandi le singole colonne bisogna perciò sapere quante sono le colonne

STRUTTURE Una struttura è una collezione finita di varia- bili non necessariamente dello stesso tipo, ognuna identificata da un nome. struct persona nome stringa di 20 char età stipendio un intero un float

STRUTTURE Una struttura è una collezione finita di varia- bili non necessariamente dello stesso tipo, ognuna identificata da un nome. Definizione di una variabile di tipo struttura: struct [<etichetta>] { { <definizione-di-variabile> } } <nomeStruttura> ;

Definisce una variabile pers strutturata nel modo illustrato. STRUTTURE - ESEMPIO struct persona { char nome[20]; int eta; float stipendio; } pers ; Definisce una variabile pers strutturata nel modo illustrato. struct persona nome stringa di 20 char età stipendio un intero un float

ESEMPI struct punto { int x, y; } p1, p2 ; struct data { int giorno,mese,anno; } d ; p1 e p2 sono fatte ciascuna da due interi di nome x e y d è fatta da tre interi di nome giorno, mese e anno

Ogni campo si comporta e si usa come una normale variabile. STRUTTURE Una volta definita una variabile struttura, si accede ai singoli campi mediante la notazione puntata. Ad esempio: p1.x = 10; p1.y = 20; p2.x = -1; p2.y = 12; d.giorno = 25; d.mese = 12; d.anno = 1999; Ogni campo si comporta e si usa come una normale variabile.

UN ALTRO ESEMPIO main(){ struct frutto { char nome[20]; int peso; } f1; struct frutto f2 ; ... } Non occorre ripetere l’elenco dei campi perché è implicito nell’etichetta frutto, che è già comparsa sopra.

ESEMPIO main(){ struct frutto { char nome[20]; int peso; } f1 = {"mela", 70}; struct frutto f2 = {"arancio", 50}; int peso = f1.peso + f2.peso; } Non c’è alcuna ambiguità perché ogni variabile di nome peso è definita nel proprio environment.

UNA PRECISAZIONE A differenza di quanto accade con gli array, il nome della struttura rappresenta la strut- tura nel suo complesso. Quindi, è possibile: assegnare una struttura a un’altra (f2 = f1) che una funzione restituisca una struttura E soprattutto: passare una struttura come parametro a una funzione significa passare una copia

ASSEGNAMENTO FRA STRUTTURE main(){ struct frutto { char nome[20]; int peso; } f1 = {"mela", 70}; struct frutto f2 = {"arancio", 50}; f1 = f2; } Equivale a copiare f2.peso in f1.peso, e f2.nome in f1.nome.

STRUTTURE PASSATE COME PARAMETRI Il nome della struttura rappresenta, come è naturale, la struttura nel suo complesso niente scherzi come con agli array…!! quindi, non ci sono problemi nel passarle a come parametro a una funzione: avviene il classico passaggio per valore è perciò possibile anche restituire come risultato una struttura tutti i campi vengono copiati, uno per uno!

ESEMPIO struct frutto macedonia( struct frutto f1, struct frutto f2){ f.peso = f1.peso + f2.peso; strcpy(f.nome, "macedonia"); return f; } La funzione di libreria strcpy() copia la costante stringa “macedonia” in f.nome. Si crea una nuova struct frutto, la si inizializza e la si restituisce come risultato.

RIFLESSIONE Se una struttura, anche molto voluminosa, viene copiata elemento per elemento... .. perché non usare una struttura per incapsulare un array? In effetti: il C non rifiuta di manipolare gli array come un tutt’uno “per principio”: è solo la conseguenza del modo in cui si interpreta il loro nome quindi, “chiudendoli in una struttura” dovremmo riuscirci!

E INFATTI... s1 = s2; /* FUNZIONA!! */ main(){ struct string20 { char s[20]; } s1 = {"Paolino Paperino" }, s2 = {"Gastone Fortunato" }; s1 = s2; /* FUNZIONA!! */ }

STRUTTURE CHE RACCHIUDONO ARRAY Usando una struttura per “racchiudere” un array, si fornisce all’array esattamente quello che gli mancava: un modo per denotare “il tutto” ossia un “contenitore” dotato di nome, che consenta di riferirsi all’array nella sua globalità.

ARGOMENTI DALLA LINEA DI COMANDO Come si è detto più volte, il main è una funzione come le altre: ha un nome convenzionale, fissato è la funzione invocata per far partire il programma. Ma… CHI LA INVOCA? Visto che è una funzione, HA DEI PARAMETRI?

ARGOMENTI DALLA LINEA DI COMANDO Il main è una funzione invocata dal sistema operativo cui è passato un array di stringhe che corrispondono agli argomenti scritti dall’utente sulla linea di comando Esempio di invocazione da linea di comando: C:> prog pippo 12 paperino 23 IV° argomento nome del programma I° argomento II° argomento III° argomento

ARGOMENTI DALLA LINEA DI COMANDO Perciò, main ha due parametri: un intero che rappresenta la lunghezza dell’array int argc (argument counter) l’array di stringhe vero e proprio (ovvia-mente, si passa il suo indirizzo iniziale) char* argv[] (argument vector) Ogni elemento dell’array è un puntatore a carattere, che punta a uno degli argomenti della linea di comando.

ARGOMENTI DALLA LINEA DI COMANDO Quindi, l’interfaccia completa del main è la seguente: int main(int argc, char* argv[]) Se non servono, argc e argv possono essere omessi, nel qual caso il main assume la forma semplificata già nota: int main() Valore di ritorno: può essere usato per restituire al Sistema Operativo un codice numerico di errore. Convenzione: 0 = OK, ogni altro valore = un tipo di errore

ARGOMENTI DALLA LINEA DI COMANDO argv[0] è il nome del programma stesso da argv[1] ad argv[argc-1] vi sono gli argomenti passati, nell’ordine argv[argc] è per convenzione NULL argv argv[0] "prog" "pippo" "12" "paperino" "23" (NULL) argv[1] argv[2] argv[3] argv[4] argc 5

ARGOMENTI DALLA LINEA DI COMANDO argv[0] è il nome del programma stesso da argv[1] ad argv[argc-1] vi sono gli argomenti passati, nell’ordine argv[argc] è per convenzione NULL Attenzione: sono aree del sistema operativo  disponibili solo in lettura argv argv[0] "prog" "pippo" "12" "paperino" "23" (NULL) argv[1] argv[2] argv[3] argv[4] argc 5

ARGOMENTI DALLA LINEA DI COMANDO Problema: Come passare argomenti dalla linea di comando… quando non c’è una linea di comando, come negli ambienti di sviluppo integrati (DJGPP / Turbo C) ? C:> prog pippo 12 paperino 23 Esiste un’apposita opzione da menù.

ARGOMENTI DALLA LINEA DI COMANDO In Turbo C: Options / Environment / Debugger

ARGOMENTI DALLA LINEA DI COMANDO In RHide: Run / Arguments...

ESEMPIO 1 Problema: Scrivere un programma che analizzi gli argomenti passati dalla linea di comando, e restituisca il numero di lettere minuscole. Specifica: Per ogni argomento da 1 ad argc-1, occorre: recuperare l’argomento (una stringa) contare le minuscole presenti in tale stringa sommare questo valore alla variabile che rappresenta il numero totale di minuscole. Alla fine si restituisce il valore di tale variabile.

ESEMPIO 1 int contaMinuscole(char s[]); Codifica int contaMinuscole(char s[]); int main(int argc, char* argv[]) { int sum=0, i; for(i=1; i<argc; i++) sum += contaMinuscole(argv[i]); return sum; }

ESEMPIO 1 #include <ctype.h> /* islower() */ Codifica #include <ctype.h> /* islower() */ int contaMinuscole(char *s){ int n=0; while (*s) if (islower(*s++)) n++; return n; }

ESEMPIO 2 Problema: Scrivere un programma che, dati un carattere e una stringa sulla linea di comando, conti quante volte il carattere compare nella stringa (sia in versione maiuscola che minuscola), e restituisca questo valore come risultato del main. Specifica: occorre in primis recuperare gli argomenti poi, si scandisce la stringa carattere per carattere e si contano le occorrenza del carattere dato (facendo attenzione alle maiuscole e minuscole) Alla fine si restituisce il risultato di tale conteggio.

ESEMPIO 2 #include <ctype.h> int main(int argc, char* argv[]) { Codifica #include <ctype.h> int main(int argc, char* argv[]) { int cont=0; char ch = toupper(argv[1][0]); char *s = argv[2]; while (*s) if (toupper(*s++)==ch) cont++; return cont; }