Sei sulla pagina 1di 58

Corso di Fondamenti di Informatica

Ingegneria delle Comunicazioni – BCOR


Ingegneria Elettronica – BELR

Introduzione al C

Unità 8 – Stringhe

D. Bloisi, A. Pennisi, S. Peluso, S. Salza


Sommario – Unità 8

•  Array di caratteri: stringhe


•  Inizializzazione di stringhe
•  Lettura e scrittura di stringhe
•  Operazioni sulle stringhe
•  Funzioni per la manipolazione delle stringhe

Stringhe - Unità 8 2013/2014 Pagina 2


Array di caratteri
Un caso particolare di array è quello
costituito da caratteri.
Infatti, le sequenze di caratteri servono per
gestire testi.

In C si usa il termine stringa per indicare gli


array di caratteri.

La libreria <string.h> offre alcune funzioni


speciali per gli array di caratteri.

Stringhe - Unità 8 2013/2014 Pagina 3


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'.

Stringhe - Unità 8 2013/2014 Pagina 4


Esempio 1

#include <stdio.h> Questo programma stampa


Hello
int main() {
const int N = 25;
char s[N];
s[0] = 'H'; s[1]='e'; s[2]='l';
s[3]='l'; s[4]='o';
s[5]='\0'; // terminatore stringa
printf("%s\n", s);
return 0; Nota: si utilizza il formato
} %s nella printf per le
stringhe
Stringhe - Unità 8 2013/2014 Pagina 5
Esempio 2
#include <stdio.h>

int main() { Questo programma stampa


const int N = 25;
Helloaaaaaaaaaaaaaaaaaaaa
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[4]='o';
// mancato inserimento
// del terminatore stringa
printf("%s\n", s);
return 0;
}
Stringhe - Unità 8 2013/2014 Pagina 6
Esempio 3
#include <stdio.h>

int main() {
const int N = 25;
Questo programma stampa
char s[N]; Hello
int i;
for(i = 0; i < N; i++)
s[i] = 'a';
s[0] = 'H'; s[1]='e'; s[2]='l';
s[3]='l'; s[4]='o';
s[5]='\0'; // terminatore stringa
printf("%s\n", s);
return 0;
}

Stringhe - Unità 8 2013/2014 Pagina 7


Stringhe costanti

Stringhe - Unità 8 2013/2014 Pagina 8


Stringhe e caratteri

Stringhe - Unità 8 2013/2014 Pagina 9


Inizializzazione tramite stringa
costante (1/3)
#include <stdio.h>

int main() {
char str[10] = "some text";
printf("%s\n", str);
return 0;
}

Stringhe - Unità 8 2013/2014 Pagina 10


Inizializzazione tramite stringa
costante (2/3)

Stringhe - Unità 8 2013/2014 Pagina 11


Inizializzazione tramite stringa
costante (3/3)

warning: excess elements in


array initializer

Stringhe - Unità 8 2013/2014 Pagina 12


Esempio
#include <stdio.h>

int main() {
char str[10] = "some text";
printf("%s\n", str);
printf("dimensione di str = %d\n“,
sizeof(str));
char s[] = {'g', 'u', 'a', 'r', 'd', 'a'};
printf("%s\n", s);
printf("dimensione di s = %d\n", sizeof(s));
return 0;
}

Stringhe - Unità 8 2013/2014 Pagina 13


Possibile output
some text
dimensione di str = 10
guardasome text
dimensione di s = 6

Manca il carattere di
terminazione '\0'
dopo l’ultima 'a' di
“guarda”

Stringhe - Unità 8 2013/2014 Pagina 14


Modifica esempio
#include <stdio.h>
carattere
speciale '\0'
int main() {
char str[10] = "some text";
printf("%s\n", 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;
}

Stringhe - Unità 8 2013/2014 Pagina 15


Output
some text
dimensione di str = 10
guarda
dimensione di s = 7

Stringhe - Unità 8 2013/2014 Pagina 16


Stringhe e array

Stringhe - Unità 8 2013/2014 Pagina 17


Lettura e scrittura di stringhe (1/3)

Si usano le funzioni scanf e printf con lo specificatore di


formato %s:
char str[4];!
scanf(“%s”, str);!
printf(“%s”, str);!
Manca & dato che str è
l’indirizzo al primo
elemento dell’array

Stringhe - Unità 8 2013/2014 Pagina 18


Lettura e scrittura di stringhe (2/3)

Stringhe - Unità 8 2013/2014 Pagina 19


Lettura e scrittura di stringhe (3/3)

Stringhe - Unità 8 2013/2014 Pagina 20


Stringhe e puntatori

Stringhe - Unità 8 2013/2014 Pagina 21


Dimensione delle stringhe in C (1/4)

Per le stringhe rappresentate come array di


caratteri, bisogna distinguere tra

Ø  la dimensione dell’array (staticamente


determinato alla sua creazione)

Ø  la lunghezza della stringa, che può invece


variare a tempo di esecuzione.

Stringhe - Unità 8 2013/2014 Pagina 22


Dimensione delle stringhe in C (2/4)

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 stringa
Ø  La dimensione dell’array è 256

Ø  La dimensione della stringa è 5

Stringhe - Unità 8 2013/2014 Pagina 23


Dimensione delle stringhe in C (3/4)

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.

Stringhe - Unità 8 2013/2014 Pagina 24


Dimensione delle stringhe in C (4/4)
Il calcolo della lunghezza di una stringa, cioè il
conteggio dei caratteri che precedono il
terminatore di stringa, si effettua tramite la
funzione strlen (vedi 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.

Stringhe - Unità 8 2013/2014 Pagina 25


Funzione strlen!

size_t strlen( const char *str );

restituisce la lunghezza del parametro str.

E’ una funzione definita in <string.h>

Stringhe - Unità 8 2013/2014 Pagina 26


Esempio strlen!
#include <stdio.h>
#include <string.h>

int main() {
char str[100] = "test string";
printf("%d\n", sizeof(str));
printf("%d\n", strlen(str));
return 0;
} Questo programma stampa
100
11
Stringhe - Unità 8 2013/2014 Pagina 27
Possibile implementazione di strlen!

size_t strlen(const char *str) {


const char* s = str;
for( ; *s; ++s);
return(s – str);
}

Stringhe - Unità 8 2013/2014 Pagina 28


Esempio: contare le occorrenze di una
lettera in una stringa (1/2)

Scrivere una funzione che, presi come


parametri una stringa (sotto forma di array di
caratteri) ed un carattere c, restituisca il
numero di occorrenze di c nella stringa.

Stringhe - Unità 8 2013/2014 Pagina 29


Esempio: contare le occorrenze di una
lettera in una stringa (2/2)
int contaLettera (const char s[], int N, char c) {
int numlettera = 0;
int pos = 0;
while (pos < N) {
if (s[pos] == c)
numlettera++;
pos++;
}
return numlettera;
}

Stringhe - Unità 8 2013/2014 Pagina 30


Versione con strlen!

int contaLettera (const char *s, char c) {


int numlettera = 0;
int pos = 0;
int N = strlen(s);
while (pos < N) {
if (s[pos] == c)
numlettera++;
pos++;
}
return numlettera;
}

Stringhe - Unità 8 2013/2014 Pagina 31


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) {
c = getchar();
}
printf("digitare un carattere da cercare, poi premere
INVIO\n");
scanf("%c", &c);
int i = contaLettera(s, c);
printf("il carattere %c si trova %d volte in %s\n",
c, i, s);
return 0;
}

Stringhe - Unità 8 2013/2014 Pagina 32


Esempio: codifica di una stringa (1/2)
Scrivere una funzione che, presi come parametri una
stringa (sotto forma di array di caratteri) ed un intero d,
restituisca la stringa opportunamente codificata.

La codifica è ottenuta sostituendo ciascun carattere con


il carattere che ha codice pari al codice del carattere da
sostituire incrementato di d.

Esempio
"ciao" con d=3 diventerà "fldr"

Stringhe - Unità 8 2013/2014 Pagina 33


Esempio: codifica di una stringa (2/2)

void codifica(const char *str, char *strRis, int d) {


char c;
int ci;
int N = strlen(str);
int i;
for (i = 0; i < N; i++)
strRis[i] = d + str[i];
strRis[N]=’\0’; // terminatore di stringa
return;
}

Stringhe - Unità 8 2013/2014 Pagina 34


Note
Nota 1: il primo dei due parametri di tipo array di caratteri ha il ruolo di
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 poi una
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.

Stringhe - Unità 8 2013/2014 Pagina 35


Esempio: lunghezza della più lunga
sottosequenza (1/2)
Se la stringa passata come parametro è
"001000111100", allora la più lunga
sottosequenza di soli '0' è quella sottolineata,
che ha lunghezza 3.

Stringhe - Unità 8 2013/2014 Pagina 36


Esempio: lunghezza della più lunga
sottosequenza (1/2)
int sottosequenza(const char * s) {
char bit; // l’elemento corrente della sequenza
int i, cont = 0; // lunghezza attuale della sequenza di zeri
int maxlung = 0; // valore temporaneo della massima
lunghezza
int N = strlen(s); // lunghezza della stringa
for (i = 0; i < N; i++) {
bit = s[i];
if (bit == '0') { // e’ stato letto un altro '0'
cont++; // aggiorna la lunghezza della sequenza
// corrente
if (cont > maxlung) // se necessario, aggiorna
maxlung = cont;// il massimo temporaneo
} else // e’ stato letto un '1'
cont = 0; // azzera la lunghezza della sequenza
//corrente
} return maxlung;
}
Stringhe - Unità 8 2013/2014 Pagina 37
Header string.h!

string.h è l’header file che contiene le


definizioni di funzioni che permettono la
manipolazione delle stringhe.

Ad esempio, è definita in string.h


size_t strlen( const char *str );
che restituisce la lunghezza del parametro str.

Stringhe - Unità 8 2013/2014 Pagina 38


Comparazione di stringhe in C
int strcmp(const char *str1, const char
*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.

Stringhe - Unità 8 2013/2014 Pagina 39


Confronto lessicografico
Una stringa s precede una stringa t in ordine
lessicografico se
• s è un prefisso di t, oppure
• se c e d sono il primo carattere rispettivamente di s e t in
cui s e t differiscono, allora c precede d nell’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.

Stringhe - Unità 8 2013/2014 Pagina 40


Esempi
• auto precede automatico
• Automatico precede auto
• albero precede alto
• H2O precede HOTEL

Stringhe - Unità 8 2013/2014 Pagina 41


Esercizio
Si scriva un programma che utilizzi la
funzione strcmp per verificare l’ordine
lessicografico mostrato negli esempi
precedenti.

Stringhe - Unità 8 2013/2014 Pagina 42


Soluzione (da completare)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char a[20] = "auto";
char b[20] = "automatico";
if(strcmp(a, b) < 0) {
printf("%s precede %s\n", a, b);
}
else if(strcmp(a, b) == 0) {
printf("%s uguale %s\n", a, b);
}
else {
printf("%s segue %s\n", a, b);
}
return EXIT_SUCCESS;
}

Stringhe - Unità 8 2013/2014 Pagina 43


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.

Stringhe - Unità 8 2013/2014 Pagina 44


Esempio d’uso di strcpy!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char str1[] = "esempio";
char str2[40];
char str3[40];
strcpy(str2, str1);
strcpy(str3, "copia riuscita");
printf("str1: %s\nstr2: %s\nstr3: %s\n",
str1, str2, str3);
return EXIT_SUCCESS;
}
Stringhe - Unità 8 2013/2014 Pagina 45
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.

Stringhe - Unità 8 2013/2014 Pagina 46


Esempio d’uso di strncpy!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char str1[] = "esempio";
char str2[40];
char str3[40];
strcpy(str2, str1);
strncpy(str3, "copia riuscita", 8);
printf("str1: %s\nstr2: %s\nstr3: %s\n",
str1, str2, str3);
return EXIT_SUCCESS;
} Stringhe - Unità 8 2013/2014 Pagina 47
Esecuzione
str1: esempio
str2: esempio
str3: copia ri[d♣Ç

Perché si può ottenere


questo risultato?

Stringhe - Unità 8 2013/2014 Pagina 48


Concatenazione di stringhe in C
char *strcat(char *str1, const char
*str2);
Concatena str2 alla fine di str1 e restituisce
str1; 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.
Stringhe - Unità 8 2013/2014 Pagina 49
Esempio d’uso di strcat!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char str[80];
strcpy(str, "queste ");
strcat(str, "stringhe ");
strcat(str, "sono ");
strcat(str, "concatenate.");
printf("%s\n", str);
return EXIT_SUCCESS;
}
Stringhe - Unità 8 2013/2014 Pagina 50
Occorrenze di stringhe in C
char *strstr(const char *str1, const char *str2);

Restituisce il puntatore alla prima occorrenza


della stringa str2 in str1, oppure NULL
se str2 non compare come sotto-stringa di str1.

Stringhe - Unità 8 2013/2014 Pagina 51


Esempio d’uso di strstr!
#include <stdio.h>
#include <string.h>
#include <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;
}
Stringhe - Unità 8 2013/2014 Pagina 52
Leggere stringhe da stream

char*
fgets(char *s, int n, FILE *stream);

fgets legge al più il numero di caratteri n meno uno


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.

Stringhe - Unità 8 2013/2014 Pagina 53


Esempio d’uso di fgets!
#include<stdio.h> stdin indica il
int main(){ puntatore allo stream
char buffer[60]; di input standard.
char * pointer;
int i;
pointer = fgets(buffer, 60, stdin);
if(pointer!=NULL)
printf("%s\n”,pointer);

return 0;
}
Meglio di scanf: possiamo evitare di eccedere
la taglia del buffer passato in input
Stringhe - Unità 8 2013/2014 Pagina 54
Esercizio

Si scriva un programma che legga da tastiera


una stringa di lunghezza arbitraria terminante
con ‘\n’ e si stampi in output la stringa. Si
noti che per limitare lo spreco di memoria si può
utilizzare solo un buffer di taglia massima 5 byte
per memorizzare i caratteri in input.

Stringhe - Unità 8 2013/2014 Pagina 55


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

1. un array di stringhe rappresentate mediante array di caratteri argv

2. il numero di elementi dell’array argc.

Il primo argomento, cioè argv[0], corrisponde al nome del file


eseguibile.

Stringhe - Unità 8 2013/2014 Pagina 56


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");
}

Stringhe - Unità 8 2013/2014 Pagina 57


Esecuzione
>gcc stampaargomenti.c -o
stampaargomenti

>./stampaargomenti
stampaargomenti

>./stampaargomenti arg1 arg2 ciao


stampaargomenti arg1 arg2 ciao

Stringhe - Unità 8 2012/2013 Pagina 58