Upload
elena-casagrande
View
213
Download
0
Embed Size (px)
Citation preview
LdL - LP1 - lez 11 - ver 6 - aa 05-06 1
Linguaggi di programmazione IStringhe (II)
Prof. Luigi Di Lascio
Lezione 11
LdL - LP1 - lez 11 - ver 6 - aa 05-06 2
Gli argomenti di questa lezione (12°)
• Richiami• La funzione sizeof• Allocazioni dinamica della memoria: malloc,
free• Input, Output di Stringhe, di Testo• Funzioni per il trattamento di stringhe nella
librerie standard• Stringhe e Puntatori• Stringhe come array di puntatori
LdL - LP1 - lez 11 - ver 6 - aa 05-06 3
Richiami: Il tipo char (I)
Il dominio D del tipo char è dato da:• le lettere dell’alfabeto (maiuscole, minuscole)• segni di punteggiatura• cifre decimali: ‘0’, ‘1’, … ‘9’• altri simboli: quelli della tabella dei codici
ASCII • il dominio D associato al tipo char è ordinato,
l’ordine è dato dal codice ASCII: 0 … 255• il C rappresenta i dati di tipo char come degli
interi: ogni carattere è rappresentato dal suo codice ASCII
LdL - LP1 - lez 11 - ver 6 - aa 05-06 4
• Dichiarazioni di variabili di tipo char: char nome_variabile
• Costanti di tipo char: ogni valore di tipo char viene specficato tra singoli apici: ‘a’, ‘b’, ‘2’, ....
• Dimensione della Rappresentazione: sizeof(char) (vedi dopo)
• Operatori relazionali: ==, !=, <=, =>, >, <• Relazione d’ordine x<=y sse
ASCII(x)<=ASCII(y)• Operatori aritmetici e logici: quelli visti per il
tipo int
Richiami: Il tipo char (II)
LdL - LP1 - lez 11 - ver 6 - aa 05-06 5
‘C’ < ‘a’ VERO, perché 67<97‘1’+’A’=ASCII(‘1’)+ASCII(‘A’)=carattere(49+65) =
CARATTERE(114) = ‘r’!’A’ FALSO, ‘A’ && ‘a’ VERO
Richiami: Il tipo char (III)
#include <stdio.h>
int main() {
int x;
x='A'+'B';
printf("%d\n",x);
printf("%c\n",x);
return 0;}
131
â
Premere un tasto per continuare . . .
LdL - LP1 - lez 11 - ver 6 - aa 05-06 6
Richiami: Stringhe e PuntatoriDichiarazioni equivalenti di stringhe:• char *corso = “LP1”;• char *corso; /* attenzione: occorre inizializzarlo */ • char corso[] = “LP1”;• char corso[4]; /* attenzione: occorre inizializzarlo */;• char corso[4] = {‘L’, ‘P’, ‘1’, ‘\0’};• char corso[] = {‘L’, ‘P’, ‘1’, ‘\0’};
Quando usate un puntatore per definire una stringa, l’imprevedibilità della lunghezza della stringa impone di allocare dinamicamente spazio in memoria per la gestione della stringa.
LdL - LP1 - lez 11 - ver 6 - aa 05-06 7
sizeof(espressione) oppure sizeof(tipo) L’operatore sizeof restituisce la memoria necessaria per espressione o per tipo.
Dimensione della memoria utilizzata per rappresentare espressioni o dati: sizeof()
Esempi:char a[10]; int i; char c; double d;i = sizeof(a[10]);printf("L'array %s ha dimensione = %d\n", a, i);i = sizeof(int);printf("Gli interi hanno dimensione %d", i);c = sizeof(char);printf(“I caratteri hanno dimensione %c", c);d = sizeof(double);printf(“Un dato di tipo double hanno dimensione %lf", d);
LdL - LP1 - lez 11 - ver 6 - aa 05-06 8
sizeof() : implementazione
#include <stdio.h>
int main(void) {
printf(“char:%3d byte\n”, sizeof(char));
printf(“int:%3d bytes\n”, sizeof(int));
printf(“long:%3d bytes\n”, sizeof(long));
printf(“float:%3d bytes\n”, sizeof(float));
printf(“double:%3d bytes\n”, sizeof(double));
printf(“long double:%3d bytes\n”, sizeof(long double));
return (0);}
char: 1 byte
int: 2 bytes
long: 4 bytes
float: 4 bytes
double: 8 bytes
long double: 10 bytes
LdL - LP1 - lez 11 - ver 6 - aa 05-06 9
Allocazione dinamica di spazio in memoria
La funzione malloc() in <stdlib.h> è utilizzata a tal fine. Vediamo come.
Allocazione di memoria per una stringa di 100 caratteri
Dichiarazione char * str;
str = (char *) malloc(100*sizeof(char));
Allocazione di memoria per un array di 50 interi
Dichiarazione int *elementi;
elementi = (int *) malloc(50*sizeof(int));
(tipo *) malloc(n*sizeof(tipo))alloca un blocco di memoria per n dati di tipo tipo
LdL - LP1 - lez 11 - ver 6 - aa 05-06 10
Allocazione dinamica di spazio in memoriaLa funzione malloc() in <stdlib.h> è utilizzata a tal
fine. Vediamo come.
Allocazione di memoria per una stringa di 100 caratteri
Dichiarazione char * str;
str = (char *) malloc(n_var*sizeof(char));
Allocazione di memoria per un array di 50 interi
Dichiarazione int *elementi;
elementi = (int *) malloc(n_var*sizeof(int));
(tipo *) malloc(n_var*sizeof(tipo))alloca un blocco di memoria per n dati di tipo tipo
LdL - LP1 - lez 11 - ver 6 - aa 05-06 11
Allocazione dinamica di spazio in memoria: malloc
if((str=(char *) malloc(100*sizeof(char))) == NULL) { printf(“memoria insufficiente”);exit(-1);}
#include <stdio.h>
#include <stdlib.h>
char i, *pPtr, *p;
int main() {
/* riserva un blocco per stringa di 34 caratteri*/
pPtr=(char*)malloc(35*sizeof(char));
if(pPtr==NULL) {
{puts(“no memoria”); exit(-1);}
Ma bisogna assicurarsi che la memoria richiesta sia disponibile ogni volta che si usa malloc(). Come si fa?
p=pPtr; /* salviamo l’indirizzo iniziale */
for(i=65;i<91;++i)
*p++=i; /* {*p=i; p++;}*/
*p = ‘\0’;
puts(pPtr);
return 0;}
Out del programma: ABC……………XYZ
LdL - LP1 - lez 11 - ver 6 - aa 05-06 12
Allocazione dinamica di spazio in memoria: free
#include <stdio.h>
#include <stdlib.h>
char i, *pPtr, *p;
int main() {
pPtr=(char*)malloc(35*sizeof(char));
if(pPtr==NULL) {puts(“no memoria”); exit(-1)};
……
pPtr=free(pPtr);
…..
return 0;}
Come si rende di nuovo libero un blocco di memoria allocato dinamicamente con malloc() ? Con free() in <stdlib.h>.
free(pPtr); /* rilascia il blocco di memoria al quale punta pPTR */
LdL - LP1 - lez 11 - ver 6 - aa 05-06 13
Visualizzazione di stringhe e caratteri
Input di stringhe, caratteri e testo su più righe
LdL - LP1 - lez 11 - ver 6 - aa 05-06 14
Visualizzazione di stringhe e caratteri
#include <stdio.h>
int main() {
char *parola =“oggi”;
puts(parola);
return 0;
}
La funzione puts()
LdL - LP1 - lez 11 - ver 6 - aa 05-06 15
Visualizzazione di stringhe e caratteri
#include <stdio.h>int main() { char *parola =“oggi”; printf(“%s”, parola); return 0;}
La funzione printf()
LdL - LP1 - lez 11 - ver 6 - aa 05-06 16
Visualizzazione di stringhe e caratteri
#include <stdio.h>
int main() {
char *parola =“oggi”;
while(*parola!=‘\0’) {
printf(“%c”, *parola);
++parola; }
return 0;}
Carattere per Carattere
LdL - LP1 - lez 11 - ver 6 - aa 05-06 17
Input di stringhe dalla tastiera
gets() riceve una stringa dalla tastiera, leggendo tutti i caratteri digitati fino a quando non viene premuto INVIO, in tal caso scarta tale carattere e aggiunge il carattere di terminazione ‘\’0
La funzione gets() /1
#include <stdio.h>int main() { char input[81]; puts(“Inserire un testo e premere INVIO: “); gets(Input); printf(“\n%s”, Input); return 0;}
LdL - LP1 - lez 11 - ver 6 - aa 05-06 18
Input di più righe di testo dalla tastiera
#include <stdlib.h>#include <stdio.h>int main(){ char input[81],*pPtr; puts("Inserire la riga premere INVIO. "); puts("Per terminare non digitare nulla e premere INVIO\n"); while(*(pPtr=gets(input))!= NULL) printf("DIGITATO: %s\n",input); /* printf("\nDIGITATO: %s\n",input);*/ return 0;}
La funzione gets() /2a
gets() restituisce un valore che rappresenta un puntatore al tipo char con l’indirizzo al quale è stata memorizzata la stringa
char *gets(char *str)
LdL - LP1 - lez 11 - ver 6 - aa 05-06 19
Input di più righe di testo dalla tastiera
Inserire la riga premere INVIOPer terminare non digitare nulla e premere INVIO
oggiDIGITATO: oggisonoDIGITATO: sonoandatoDIGITATO: andatoal mareDIGITATO: al mare
DIGITATO:Premere un tasto per continuare . . .
La funzione gets() /2b
LdL - LP1 - lez 11 - ver 6 - aa 05-06 20
Input di stringhe dalla tastiera
#include <stdio.h>int main() { char *parola =“oggi”; scanf(“%s”, parola); return 0;}
La funzione scanf()
AAA! scanf() non vede gli spazi vuoti!
LdL - LP1 - lez 11 - ver 6 - aa 05-06 21
Funzioni per il trattamento di stringhe
nella libreria <string.h>
LdL - LP1 - lez 11 - ver 6 - aa 05-06 22
size_int strlen(const char *s)
#include <stdio.h>#include <string.h>int main(void){ char *s1="abc"; char *s2="four"; char *s3="cinque"; printf("Lunghezza di %s = %d\n",s1, strlen(s1)); printf("Lunghezza di %s = %d\n",s2, strlen(s2)); printf("Lunghezza di %s = %d\n",s3, strlen(s3)); return(0);}
Funzioni per il trattamento di stringhe nella libreria <string.h> /1
LdL - LP1 - lez 11 - ver 6 - aa 05-06 23
Funzioni per il trattamento di stringhe nella libreria <string.h> /2
char *strcpy(char *s1, const char *s2)
copia la stringa s2 nell’array s1 e ritorna s1
char *strncpy(char *s1, const char *s2, size_t n)
copia al più n caratteri di s2 nell’array s1 e ritorna s1
char *strcat(char *s1, const char *s2)
attacca la stringa s2 all’array s1, quindi ritorna s1.
char *strncat (char *s1, const char *s2, size_t n)
attacca al più n caratteri della stringa s2 all’array s1, quindi ritorna s1
LdL - LP1 - lez 11 - ver 6 - aa 05-06 24
Funzioni per il trattamento di stringhe /2 : esempio/a
#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){ char x[]="Ciao"; char y[10], z[3];
strcpy(y,x); printf("stringa in x = %s, stringa in y = %s\n",x,y);
strncpy(z,x,2); z[2]='\0'; printf("stringa in z = %s\n",z);
return 0;}
LdL - LP1 - lez 11 - ver 6 - aa 05-06 25
Funzioni per il trattamento di stringhe /2 : esempio/a
stringa in x = Ciao
stringa in y = Ciao
stringa in z = Ci
Premere un tasto per continuare . . .
LdL - LP1 - lez 11 - ver 6 - aa 05-06 26
Funzioni per il trattamento di stringhe /2 : esempio /b
#include <string.h>#include <stdio.h>#include <stdlib.h>int main(){ char s1[20]="Happy "; char s2[]= "New Year "; char s3[]= " "; printf("s1 = %s\ns2 = %s\n", s1, s2); strcat(s1,s2); printf("s1+s2=%s\n",s1); strncat(s3,s1,6); printf("s3+s1(3 car) =%s\n", s3); strcat(s3,s1); printf("s3+s1=%s\n", s3); return 0;}
LdL - LP1 - lez 11 - ver 6 - aa 05-06 27
Funzioni per il trattamento di stringhe /2 : esempio /b
s1 = Happy
s2 = New Year
s1+s2=Happy New Year
s3+s1(3 car) = Hap
s3+s1= HapHappy New Year
Premere un tasto per continuare . . .
LdL - LP1 - lez 11 - ver 6 - aa 05-06 28
int strcmp( const char *s1, const char *s2)
confronta le stringhe s1 ed s2; se s1<s2 dà un numero negativo, se s1==s2 dà zero, se s1>s2 dà un numero positivo (ordine lessicografico)
int strncmp( const char *s1, const char *s2, size_t n)
confronta i primi n caratteri di s1 con i primi n caratteri di s2; il valore restituito segue le regole date sopra
Funzioni per il trattamento di stringhe nella libreria <string.h> /3
LdL - LP1 - lez 11 - ver 6 - aa 05-06 29
Array di Puntatori: array di stringhe
Inizializzazione, Scansione per Stringhe
Immissione di un testo su più righe fissate
Passaggio di un array di puntatori ad una funzione
LdL - LP1 - lez 11 - ver 6 - aa 05-06 30
Array di Puntatori: array di stringhe
#include <stdio.h>
int main() {
char *parole[3] = {“oggi”,”domani”,”mai”};
int i;
for(i=0;i<3;++i)
printf(“%s”, parole[i]);
return 0;
}
Inizializzazione, Scansione per Stringhe
LdL - LP1 - lez 11 - ver 6 - aa 05-06 31
Array di Puntatori: array di stringheImmissione di un testo su più righe fissate
#include <string.h>#include <stdio.h>#include <stdlib.h>#define NUM_RIGHE 3int main() { char *parole[NUM_RIGHE], stringa[80+1]; int i; for(i=0;i<NUM_RIGHE;++i) { gets(stringa); parole[i]=(char *)malloc((strlen(stringa)+1)*
sizeof(char)); if(parole[i]==NULL) exit(EXIT_FAILURE); strcpy(parole[i], stringa); } for(i=0;i<NUM_RIGHE;++i) printf("%d: %s\n",i,parole[i]);return 0;}
exit(EXIT_SUCCESS)terminazione con successoexit(EXIT_FAILURE)terminazione con
fallimento
oggi sono
andato al
mare
0: oggi sono
1: andato al
2: mare
Premere un tasto per continuare . . .
LdL - LP1 - lez 11 - ver 6 - aa 05-06 32
Array di Puntatori: array di stringhe
#include <stdio.h>
void visualizza(char *[], int);
int main() {
char *parole[3] = {“oggi”,”domani”,”mai”};
visualizza(parole, 3);
return 0;
}
Passaggio di un array di puntatori ad una funzione
void visualizza(char *pPtr[], int n)
{
int i; for(i=0;i<n;++i) printf(“%s\n”, pPtr [i]);return ;}
oggi domani mai Premere un tasto per continuare . . .
LdL - LP1 - lez 11 - ver 6 - aa 05-06 33
Array di Puntatori: ultimo esempio /1La dichiarazione char *semi[4]={“cuori”, “picche”, “quadri”,
“fiori”} ha il seguente significato:• semi[4] indica un array di 4 elementi• char * indica che ogni elemento dell’array sarà del tipo
“puntatore a char”, quindi …• ognuno degli elementi sarà immagazzinato in memoria come
una stringa di caratteri terminata da ‘\0’. • Per accedere a questi elementi, basta sapere che: • semi[0] punta a (contiene l’indirizzo della locazione di
memoria con) ‘c’ (di cuori), semi[1] a ‘p’ (di picche), semi[2] a ‘q’ di (di quadri), semi[3] a ‘f’ (di fiori).
• ++semi[0]: permette di avanzare lungo “cuori”• ++semi[1]: permette di avanzare lungo “picche”• ++semi[2]: permette di avanzare lungo “quadri”• ++semi[3]: permette di avanzare lungo “fiori”
LdL - LP1 - lez 11 - ver 6 - aa 05-06 34
Array di Puntatori: ultimo esempio /2
Input, Scansione per Carattere
per giovedi’
Progettare e implementare un programma che accetti a tempo di esecuzione l’array seguente {“cuori”, “picche”, “quadri”, “fiori”}, quindi visualizzi l’array carattere per carattere, segnalando la fine di ogni stringa
Progettare e implementare un programma che accetti a tempo di esecuzione l’array seguente {“cuori”, “picche”, “quadri”, “fiori”}, quindi visualizzi l’array carattere per carattere, segnalando la fine di ogni stringa, mediante un’opportuna funzione
LdL - LP1 - lez 11 - ver 6 - aa 05-06 35
Array di Puntatori: ultimo esempio /3
Provate, allenatevi, riprovate, riallenatevi
Linguaggi di Programmazione 1Appello, 26 novembre 2004, ore 14, aule C31 (matr. 6), C38
(matr. 7)prof. Luigi Di Lascio
3) Progetta ed implementa in C una funzione, i cui parametri di
input sono un array di n parole della lingua italiana e due caratteri dell’alfabeto della lingua italiana, che calcoli la frequenza dei due caratteri nell’array (p. 15)
LdL - LP1 - lez 11 - ver 6 - aa 05-06 36
Array di Puntatori: aiutoProvate, allenatevi, riprovate, riallenatevi
#include <stdio.h>int main() { char *semi[4]={"cuori", "picche", "quadri", "fiori"}; printf("%c\n",*semi[0]); /*c*/ printf("%c\n",*(semi[0]+2)); /*o*/ printf("%c\n",*semi[1]); /*p*/ printf("%c\n",*(semi[1]+1)); /*i*/ printf("%c\n",*semi[2]); /*q*/ printf("%c\n",*(semi[2]+3)); /*d*/ printf("%c\n",*semi[3]); /*f*/ printf("%c\n",*(semi[3]+1)); /*i*/ return 0;}