Upload
ngomien
View
220
Download
1
Embed Size (px)
Citation preview
Corso di Fondamenti di InformaticaIngegneria delle Comunicazioni – BCORIngegneria Elettronica – BELR
Introduzione al C
Unità 8 – Stringhe
D. Bloisi, S. Peluso, A. Pennisi, S. Salza
Pagina 22016/2017Unità 8 - Stringhe
Sommario – Unità 8
• Array di caratteri: stringa
• Inizializzazione di stringhe
• Lettura e scrittura di stringhe
• Operazioni sulle stringhe
• Funzioni per la manipolazione delle stringhe
Pagina 32016/2017Unità 8 - Stringhe
Array di caratteri
• Un caso particolare di array è quello costituito da caratteri.
• Le sequenze di caratteri servono per gestire testi.
• In C si usa il termine stringa per indicare gli array dicaratteri.
• La libreria <string.h> offre alcune funzioni speciali per gli array di caratteri.
Pagina 42016/2017Unità 8 - Stringhe
Rappresentazione di stringhe in C
• Nel linguaggio C una stringa è rappresentata mediante un array di caratteri terminante con il carattere speciale '\0' (codice ASCII = 0), che, quindi, funge da terminatore di stringa.
• In questo modo è possibile conoscere la lunghezza di una stringa contando il numero di caratteri che precedono il carattere '\0'.
Pagina 52016/2017Unità 8 - Stringhe
Esempio 1#include <stdio.h>
s[N];
int main() {const int N chars[0] = 'H';
= 25;
s[1]='e'; s[2]='l';s[4]='o';s[3]='l';
s[5]='\0'; // terminatore stringaprintf("%s\n", s); return 0;
}Nota: si utilizza il formato%s nella printf per le stringhe
Questo programma stampaHello
Pagina 62016/2017Unità 8 - Stringhe
Esempio 2#include <stdio.h>
int main()const
{int N = 25;
char s[N]; int i;for(i = 0; i < N; i++)
s[i] = 'a';s[0] = 'H'; s[1]='e'; s[2]='l';s[3]='l';// mancato
s[4]='o';inserimento
// del terminatore stringa printf("%s\n", s);return 0;
}
Questo programma stampaHelloaaaaaaaaaaaaaaaaaaaa
Pagina 72016/2017Unità 8 - Stringhe
Esempio 3#include <stdio.h>
int main()const
{int N = 25;
char s[N]; int i;for(i = 0; i < N; i++)
s[i] = 'a';s[0] = 'H'; s[1]='e'; s[2]='l';s[3]='l';s[5]='\0';
s[4]='o';// terminatore stringa
printf("%s\n", s);return 0;
}
Questo programma stampaHello
Pagina 82016/2017Unità 8 - Stringhe
Stringhe costanti
• Stringa costante: serie di caratteri tra doppi apiciEs: "HELLO WORLD"
• Stringa: array di caratteri che termina sempre con il carattere nullo, cioè la sequenza di escape \0
• Per memorizzare una stringa si usa un array di caratteri:
Char str[] = "some text"• Array di 9+1=10 elementi
Pagina 92016/2017Unità 8 - Stringhe
Stringhe e caratteri
• Le stringhe sono diverse dalle costanti carattere• "a" stringa: è un array di 2 elementi:
char array[2]; 'a' e '\0'
• 'a'costante : è un solo carattere:
char ch = 'a';
• In memoria:"a"occupa due byte ('a' e '\0')'a'occupa un solo byte
Pagina 102016/2017Unità 8 - Stringhe
Inizializzazione tramite costante 1/3
"some text"; str);
#include <stdio.h>
int main() {char str[10] =printf("%s\n",return 0;
}
Pagina 112016/2017Unità 8 - Stringhe
Inizializzazione tramite costante 2/3
Pagina 122016/2017Unità 8 - Stringhe
Inizializzazione tramite costante 3/3
• L’array che rappresenta la stringa ha dimensione (almeno) maggiore di 1 rispetto alla stringa
• Aggiunto automaticamente il terminatore \0
• Se si specifica la lunghezza della stringa il numero di caratteri deve corrisponderechar str[3] = "ecco"; tagliati gli ultimi due caratteri
char str[3] = "e"; elementi mancanti messi a 0
Pagina 132016/2017Unità 8 - Stringhe
Esempio
#include <stdio.h>
int main() {char str[10] = text";printf("%s\n",
"some str);
di str = %d\n“,printf("dimensione sizeof(str));
char s[] = {'g', 'u', 'a', 'r', 'd', 'a'};printf("%s\n", s);
s = %d\n", sizeof(s));printf("dimensione di return 0;
}
Pagina 142016/2017Unità 8 - Stringhe
Possibile output
some textdimensioneguardaxxxdimensione
di str = 10
di s = 6
Manca il carattere di terminazione '\0' dopo l’ultima 'a' di “guarda”
Pagina 152016/2017Unità 8 - Stringhe
Esempio modificato
#include <stdio.h>
int main() {char str[10] = text";printf("%s\n",
"some str);
printf("dimensione di str = %d\n“, sizeof(str));
char s[] = {'g','u','a','r','d','a','\0'}; printf("%s\n", s);printf("dimensione di s = %d\n", sizeof(s)); return 0;
}
carattere speciale '\0'
Pagina 162016/2017Unità 8 - Stringhe
Output di esempio modificato
some textdimensione di str = 10guardadimensione di s = 7
Pagina 172016/2017Unità 8 - Stringhe
Stringhe e array
• Una stringa di caratteri è un array a tutti gli effetti
• Accesso ai singoli elementi tramite nome e indice
char str[5] = "ecco";
char[3] contiene il carattere 'o'
• Viene trattata dal compilatore come un puntatore (nome di array)
• Il nome della stringa è l’indirizzo del byte che contiene il primo elemento della stringa
Pagina 182016/2017Unità 8 - Stringhe
Lettura e scrittura di stringhe 1/3
Si usano le funzioni scanf e printf con la specifica di formato %s
char str[4];scanf("%s", str);printf("%s", str);
N.B. Non si mette l’operatore indirizzo &, perché il nome della tringa str è già un puntatore che punta al primo elemento dell’array
Pagina 192016/2017Unità 8 - Stringhe
Lettura e scrittura di stringhe 2/3
#include <stdio.h>#define N 20
int main() {char ar[N] = "Oggi piove. ”;char str[N];printf("Digita una stringa:");scanf("%s", str);printf("Prima stringa: %s\n", ar};printf("Seconda stringa: %s\n", str};return 0;
}
Pagina 202016/2017Unità 8 - Stringhe
Lettura e scrittura di stringhe 3/3
• scanf• L’argomento deve essere un puntatore a un array di
dimensioni sufficienti per contenere la linea di input• Termine di immissione: carattere invio• Alla fine della stringa viene automaticamente
aggiunto il carattere \0• printf
• L’argomento deve essere un puntatore a un array di caratteri terminato dal carattere nullo (\0)
• I caratteri sono stampati fino al terminatore
Pagina 212016/2017Unità 8 - Stringhe
Stringhe e puntatori 1/2
#include <stdio.h>
int main() {char *p = "abc";printf("%s %s %s", p, p+1, p+2);return 0;
}
Pagina 222016/2017Unità 8 - Stringhe
Stringhe e puntatori 2/2
• La stringa sarà composta da quattro elementi, compreso il terminatore \0
• Alla variabile p viene assegnato l’indirizzo del primo elemento dell’array di caratteri "abc"
• La stampa di un puntatore a char provoca la stampa di tutti caratteri dell’array fino al terminatore \0
• printf(.. p): stampa tutta la stringa cioè abc• printf(.. P+1): stampa il secondo elemento cioè b• printf(.. P+2): stampa il terzo elemento cioè c
Pagina 232016/2017Unità 8 - Stringhe
Dimensione delle stringhe in C 1/4
Per le stringhe rappresentate come array di caratteri, bisogna distinguere tra
Ø dimensione dell’array (staticamente determinata alla sua creazione) rimane fissa
Ø lunghezza della stringa (può invece variare a tempo di esecuzione)
N.B. La dimensione della stringa (più il terminatore \0) dovrà essere sempre non superiore a quella dell’array
Pagina 242016/2017Unità 8 - Stringhe
Dimensione delle stringhe in C 2/4
ØDimensione dell’array 256
ØLunghezza della stringa 5
const int N = 256;char s[n];s[0]='H'; s[1]='e'; s[2]='l';s[3]='l'; s[4]='o'; s[5]=\0; // terminatore di stringa
Pagina 252016/2017Unità 8 - Stringhe
Dimensione delle stringhe in C 3/4
ATTENZIONE
• La lunghezza (dimensione) della stringa deve essere sempre minore o uguale della dimensione dell’array meno uno (perché bisogna considerare sempre il carattere terminatore della stringa).
• In caso contrario, si ha un accesso fuori dalla zona di memoria allocata alla stringa con conseguente possibilità di errori.
Pagina 262016/2017Unità 8 - Stringhe
Dimensione delle stringhe in C 3/4
Calcolo della lunghezza della stringa
• Il calcolo della lunghezza di una stringa, cioè il conteggio dei caratteri che precedono il terminatore di stringa, si effettua tramite la funzione strlen (v. dopo).
• Tale funzione è però inefficiente (perché richiede un ciclo di scansione di tutta la stringa); quindi, a volte, si preferisce usare un argomento esplicito che contiene la lunghezza della stringa.
Pagina 272016/2017Unità 8 - Stringhe
Dimensione delle stringhe in C 4/4
Calcolo della lunghezza della stringa
• Il calcolo della lunghezza di una stringa, cioè il conteggio dei caratteri che precedono il terminatore di stringa, si effettua tramite la funzione strlen (v. dopo).
• Tale funzione è però inefficiente (perché richiede un ciclo di scansione di tutta la stringa); quindi, a volte, si preferisce usare un argomento esplicito che contiene la lunghezza della stringa.
Pagina 282016/2017Unità 8 - Stringhe
Funzione strlen
size_t strlen( const char *str );
• Serve a determinare la lunghezza di una stringa• Restituisce la lunghezza della stringa str passata
come paramentro• È una funzione definita in <string.h>N.B. Il tipo size_t è di fatto unsigned long int e
viene usato per contenere il valore assoluto della differenza tra due indirizzi
size_t
Pagina 292016/2017Unità 8 - Stringhe
Esmpio strlen
#include#include
<stdio.h><string.h>
int main() {char str[100] = "test string";printf("%d\n", printf("%d\n",
sizeof(str));strlen(str));
return 0;} Questo programma stampa
10011
Pagina 302016/2017Unità 8 - Stringhe
Esempio: conteggio di occorrenze 1/3
Scrivere una funzione che, presi come parametri una stringa (sotto forma di array dicaratteri s[]) e uno specifico carattere c, restituisca il numero di occorrenze di cnella stringa.
Pagina 312016/2017Unità 8 - Stringhe
Esempio: conteggio di occorrenze 2/3
int contaChar (const char s[],int N,char c) {int conta = 0;int pos = 0; while (pos < N) {
if (s[pos] == c)conta++; pos++;
}return conta;
}
Pagina 322016/2017Unità 8 - Stringhe
Esempio: conteggio di occorrenze 3/3
int contaChar(const char *s, char c) {
pos = 0;int conta = 0; intint N = strlen(s);while (pos < N) {
if (s[pos] == c) conta++; pos++;
}return conta;
}
Usando la funzione strlen
Pagina 332016/2017Unità 8 - Stringhe
Main di prova
int main() {
char s[256];
char c;
printf("digitare una parola, poi premere INVIO\n");
scanf("%s", s);
//pulisco il buffer in ingresso while(c != '\n' && c!= EOF){getchar();}
printf("digita il carattere da cercare, poi premiINVIO\n");
scanf("%c", &c);
int i = contaChar(s, c);
printf("il carattere %c si trova %d volte in %s\n",c,I,s);
return 0;
}
Pagina 342016/2017Unità 8 - Stringhe
Esempio: codifica di una stringa 1/3
• Scrivere una funzione che, presi come parametri una stringa (sotto forma di array di caratteri) ed un interod , restituisca la stringa opportunamente codificata.
• La codifica è ottenuta sostituendo ciascun caratterecon il carattere che ha codice pari al codice del carattere da sostituire incrementato di d.
• Esempio• "ciao" con d=3 diventerà "fldr"
Pagina 352016/2017Unità 8 - Stringhe
Esempio: codifica di una stringa 2/3
void codifica(const char *str,char *strRis,int d){ char c;int ci;int N = strlen(str); int i;for (i = 0; i <
strRis[i]N; i++)= d + str[i];// terminatore di stringastrRis[N]='\0';
return;}
Pagina 362016/2017Unità 8 - Stringhe
Esempio: codifica di una stringa 3/3
Nota 1: il primo dei due parametri di tipo array di caratteri ha il ruolodi input, ed è quindi dichiarato const, mentre il secondo ha il ruolo di output e non può essere dichiarato const in quanto verrà modificato.
Nota 2: nell’istruzione strRis[i] = d + str[i]; c’è una conversione implicita ad intero per poter effettuare la somma e poiuna conversione di nuovo a carattere per memorizzare il risultato.
Nota 3: in questa funzione si assume che sia stata già allocata memoria per la stringa di output strRis di dimensione almeno pari a quella di str. Inoltre, è necessario aggiungere il carattere '\0' per terminare la stringa di output.
Pagina 372016/2017Unità 8 - Stringhe
Esempio: sequenza più lunga 1/2
• Scrivere una funzione che:• riceva una stringa come parametro• restituisca la lunghezza della più lunga sequenza
di 0 contenuta nella stringa data• Se ad esempio la stringa passata come parametro è
"001000111100", allora la più lunga sequenza di soli '0' è quella sottolineata, che ha lunghezza 3.
Pagina 382016/2017Unità 8 - Stringhe
Esempio: sequenza più lunga 1/2
• Scrivere una funzione che:
• riceva una stringa come parametro
• restituisca la lunghezza della più lunga sequenza di 0 contenuta nella stringa data
• Se ad esempio la stringa passata come parametro è "001000111100", allora la più lunga sequenza di soli '0' è quella sottolineata, che ha lunghezza 3.
Pagina 392016/2017Unità 8 - Stringhe
Esempio: sequenza più lunga 2/2
int sottosequenza(const char *s) {char bit; // l’elemento corrente della sequenza
0della sequenza di della massima lungh
int i, cont = 0; // lunghezza attuale int maxlung = 0; // valore temporaneo
stringaint N = strlen(s); // lunghezza della for (i =0; i < N; i++) {
bit = s[i];if (bit =='0'){ // e’ stato letto un altro '0' cont++; // aggiorna la lungh.della sequenza correnteif (cont > maxlung) maxlung=cont;
}else // e’ stato letto un ‘1’cont = 0; // azzera la lungh. seq. corr.
} return maxlung;}
Pagina 402016/2017Unità 8 - Stringhe
Header string.h
string.h è un header file che contiene una serie di definizioni di funzioni per la manipolazione di stringheAd esempio in string.h è definita la funzione
size_t strlen( const char *str );
che restituisce la lunghezza della stringa passataparametro str.
Pagina 412016/2017Unità 8 - Stringhe
Comparazione di stringhe in C
La funzione strcmp permette di confrontare due stringhe
int strcmp(const char *str1,const *str2);
Effettua un confronto lessicografico tra due stringhe restituendo un valore
< 0 se str1 precede str2,
= 0 se str1 è uguale a str2,
> 0 se str1 segue str2
Pagina 422016/2017Unità 8 - Stringhe
Confronto lessicografico
• Una stringa s precede una stringa t inordine lessicografico se:§ s è un prefisso di t, oppure§ se c e d sono il primo carattere rispettivamente dis e t in cui s e t differiscono, allora c precede dnell’ordinamento dei caratteri.
Nota: per i caratteri che sono lettere alfabetiche, l’ordinamento è quello alfabetico. Le cifre precedono le lettere e le lettere maiuscole precedono quelle minuscole.
Pagina 432016/2017Unità 8 - Stringhe
Esempi
• auto precede automatico
• Automatico precede auto
• albero precede alto
• H2O precede HOTEL
N.B. Il codice ASCII di A è inferiore a quello di a
Pagina 442016/2017Unità 8 - Stringhe
Esercizio: verifica dell’ordine
Si scriva un programma che utilizzi la funzione strcmp per verificare l’ordinelessicografico mostrato negli esempi precedenti.
Pagina 452016/2017Unità 8 - Stringhe
Schema di soluzione#include#include#include
<stdio.h><string.h><stdlib.h>
"auto"; "automatico";
int main() {char a[20] =char b[20] =if(strcmp(a,
printf("%sb) < 0) {
precede %s\n", a, b);
b) == 0) {uguale %s\n", a, b);
segue %s\n", a, b);
}else if(strcmp(a,
printf("%s}else {
printf("%s}return EXIT_SUCCESS;
}
Pagina 462016/2017Unità 8 - Stringhe
Copia di stringhe in C
char *strcpy(char *dest, const char *src);
Copia la stringa src in dest e restituisce dest; dest viene quindi modificata.
char *strncpy(char *dest,const char *src,size_t n);
Copia i primi n caratteri di src in dest e restituisce dest; dest viene quindi modificata.
Pagina 472016/2017Unità 8 - Stringhe
Esempio d’uso di strcpy#include#include#include
<stdio.h><string.h><stdlib.h>
{str1[] = "esempio";
int main()charcharchar
str2[40];str3[40];
str1); "copia riuscita");
strcpy(str2, strcpy(str3, printf("str1: %s\nstr2: %s\nstr3: %s\n",
returnstr1, str2, str3);
EXIT_SUCCESS;}
Pagina 482016/2017Unità 8 - Stringhe
Nota su strcpy
• La funzione strcpy copia la stringa src nella stringa dest, incluso il carattere terminatore e la restituisce.
• Il contenuto precedente di dest viene perduto.
• Il controllo che lo spazio puntato da dest sia sufficiente rimane a carico del programmatore.
Pagina 492016/2017Unità 8 - Stringhe
Esempio d’uso di strncpy#include#include#include
<stdio.h><string.h><stdlib.h>
int main() {str1[] = "esempio";char
charchar
str2[40];str3[40];
strcpy(str2, str1);strncpy(str3, "copia riuscita", 8);printf("str1: %s\nstr2: %s\nstr3: %s\n",
returnstr1, str2, str3);
EXIT_SUCCESS;}
Pagina 502016/2017Unità 8 - Stringhe
Esecuzione
str1:str2:str3:
esempio esempio copia ri[d♣Ç
Perché si può ottenere questo risultato?
Pagina 512016/2017Unità 8 - Stringhe
Concatenazione di stringhe in C
char *strcat(char *str1, const char *str2);
Concatena str2 alla fine di str1 e restituiscestr1; str1 viene quindi modificata.
char *strncat(char *str1, const char *str2, size_t n);
Concatena i primi n caratteri di str2 alla fine di str1 e restituisce str1; str1 viene quindi modificata.
Pagina 522016/2017Unità 8 - Stringhe
Esempio d’uso di strcat#include#include#include
<stdio.h><string.h><stdlib.h>
int main() {char str[80];
"queste ");"stringhe ");"sono ");
strcpy(str,strcat(str,strcat(str,strcat(str, "concatenate.");printf("%s\n", str);return EXIT_SUCCESS;
}
Pagina 532016/2017Unità 8 - Stringhe
Ricerca di occorrenze di stringhe
char *strstr(const char *str1, const char *str2);
• Riceve come parametri due stringhe str1 e str2
• Restituisce il puntatore alla prima occorrenza della stringa str2 in str1, oppure NULL se str2 non compare come sotto-stringa di str1
• Le stringhe str1 e str2 non vengono modificate
Pagina 542016/2017Unità 8 - Stringhe
Esempio d’uso di strstr#include#include#include
<stdio.h><string.h><stdlib.h>
int main() {char str[] = "Tutti a casa, subito!";char*pch =
pch;strstr(str, "casa");
if(pch != NULL)strncpy(pch, "mare", 4);
printf("%s\n", str); return EXIT_SUCCESS;
}
Pagina 552016/2017Unità 8 - Stringhe
Leggere stringhe da stream
char* fgets(char *s, int n, FILE *stream);
• fgets legge al più il numero di caratteri n menouno dallo stream specificato e li memorizza nella stringa s
• La lettura termina quando si hanno un carattere di nuova linea, un EOF o un errore.
• Se qualche carattere è stato letto e non c’è errore allora il carattere \0 è inserito alla fine di s.
Esempio d’uso di fgets
#include <stdio.h>int main() {
char buffer[60];char* pointer;int i;pointer = fgets(buffer, 60, stdin);if (pointer!= NULL) printf("%s\n",
pointer);return 0;
}
STREAM STANDARD DI INPUT
N.B. È meglio di scanf perché possiamo evitare di eccesere la taglia del buffer passato in input
2016/2017Unità 8 - Stringhe Pagina 56
Pagina 572016/2017Unità 8 - Stringhe
Esercizio
Si scriva un programma che:• legga da tastiera una stringa di lunghezza
arbitraria terminante con \n• stampi in output la stringa che ha letto• per limitare lo spreco di memoria si può
utilizzare solo un buffer di taglia massima 5 byte per memorizzare i caratteri in input.
Pagina 582016/2017Unità 8 - Stringhe
Parametri in input ad un programma
La funzione main può essere dichiarata anche con un prototipo a due argomenti:
int main(int argc, char **argv)
Gli argomenti della funzione main indicano• un array di stringhe rappresentate mediante array di caratteri
argv • il numero di elementi dell’array argc.
Il primo argomento, cioè argv[0], corrisponde al nome delfile eseguibile.
Pagina 592016/2017Unità 8 - Stringhe
Esempio: stampa argomenti
#include <stdio.h>
int main(int argc, char **argv) { int k;for (k = 0; k < argc; k++)
printf("%s ", argv[k]);printf("\n");
}
Pagina 602016/2017Unità 8 - Stringhe
Esecuzione
>gcc stampaargomenti.c -ostampaargomenti
>./stampaargomenti stampaargomenti
>./stampaargomenti arg1 arg2 ciaostampaargomenti arg1 arg2 ciao