Caratteri e stringhe
Caratteri
¨ Dato che un computer può memorizzare esclusivamente sequenze di bit, per memorizzare un carattere (e quindi testi) è necessario stabilire una convenzione che associa a un carattere una determinata sequenza di bit,
rappresentata ad esempio con un numero intero
¨ Lo standard principale si chiama codice ASCII (American Standard Code for Information Interchange), pronunciato
“aski” (/ˈæski/)
¨ Il codice ASCII standard stabilisce la corrispondenza tra 128 caratteri e un numero da 0 a 127 (7 bit)
2
Caratteri
Codice ASCII Caratteri
0-31 Caratteri di controllo
32 spazio
33-47 Altri caratteri (!, ", #, $, %, ', (, ), *, +, -, /, ., ,)
48-57 Cifre da 0 a 9
58-64 Altri caratteri (:, ;, <, =, >, ?, @) 65-90 Lettere maiuscole (A-Z)
91-96 Altri caratteri ([, \, ], ^, _, `) 97-122 Lettere minuscole (a-z) 123-127 Altri caratteri ({, |, }, ~)
Caratteri
¨ In C per indicare un carattere si usano gli apici singoli
¨ Es.:
¤ 'A' è il carattere A maiuscolo (a cui corrisponde il numero 65 nel codice ASCII)
¤ '0' è il carattere della cifra zero (a cui corrisponde il numero 48 nel codice ASCII)
¤ 0, senza apici, invece, è il numero zero, diverso dal carattere '0'
Caratteri
¨ Il tipo char è utile per memorizzare un carattere
¨ Dato che per memorizzare un carattere il C memorizza il suo codice ASCII, una variabile di tipo char può essere usata sia come numero intero che come carattere
¨ Es.:
¤ char c = 'A'; e char c = 65; sono equivalenti
¤ Dato char d ='3', posso ottenere il suo valore con d-'0', che il C eseguirà come 51-48, cioè 3
Stringhe
¨ In C non esiste il tipo stringa
¨ Una stringa di caratteri in C è un array di caratteri di una certa dimensione terminato dal carattere '\0'
¨ Un array di N caratteri può dunque ospitare stringhe lunghe al più N-1 caratteri perché una cella è destinata al simbolo '\0'
m a t t o n e \0 0 1 2 3 4 5 6 7 char s[8];
4
Stringhe
¨ Un array di N caratteri può essere usato per memorizzare anche stringhe più corte di N-1
¨ Le celle contrassegnate da ? indicano celle il cui contenuto è indefinito, cioè corrispondono a ciò che “casualmente” si trova in quelle celle di memoria
c i a o \0
0 1 2 3 4 5 6 7
char s[8]; ? ? ?
Manipolazione di stringhe
Manipolazione di stringhe
¨ Il C fornisce alcune funzioni per la manipolazione delle stringhe i cui prototipi sono nell’header string.h. Tra queste funzioni:
¨ size_t strlen(char *str);
¨ strlen sta per string length e restituisce il numero di caratteri di cui è composta una stringa (size_t è un tipo intero senza segno; a seconda dell’architettura e del compilatore, è un unsigned int o un unsigned long)
¨ Es.:
#include <string.h>
int main(void) { int l;
char s[] = "pippo";
l = strlen(s); // l vale 5 return 0;
}
Manipolazione di stringhe
¨ char* strcpy(char* dst, char* src);
¨ strcpy sta per string copy e effettua una copia tra stringhe. Il primo parametro è la stringa di destinazione e il secondo è la stringa sorgente. Il valore di ritorno di strcpy si usa raramente (è un puntatore allo \0 finale di dst)
¨ Es.:
#include <string.h>
int main(void) { char s[10];
strcpy(s, "pippo");
return 0;
}
¨ N.B.: in C non si può assegnare una stringa (ad es.
s = "stringa_costante") tranne quando si dichiara e inizializza una stringa (ad es. char s[] = "stringa_costante";)
6
Manipolazione di stringhe
¨ int strcmp(char *s1, char *s2);
¨ strcmp sta per string compare e confronta due stringhe.
Restituisce 0 se le stringhe sono uguali, un numero diverso da 0 se sono diverse (negativo se s1 precede s2 lessicograficamente, cioè considerando l’ordinamento ASCII, positivo se s1 segue s2)
¨ Es.:
#include <string.h>
int main(void) { int cmp;
char str1[] = "Pippo", str2[] = "pippo";
cmp = strcmp(str1, str2); //cmp è un numero negativo perché 'P'<'p'
return 0;
}
I/O di caratteri e stringhe
I/O di caratteri
¨ Output di un carattere char c = 'A';
printf("%c", c);
¨ Input di un carattere char c;
scanf("%c", &c);
¨ In questo caso la scanf interpreta come carattere anche i white space iniziali eventualmente rimasti nel buffer. Per scartare i white space, bisogna scrivere
scanf(" %c", &c); (con lo spazio prima di %)
I/O di stringhe
¨ Output di una stringa
char stringa[] = "Ciao";
printf("%s", stringa);
8
I/O di stringhe
¨ Input di una stringa
char stringa[8];
scanf("%s", stringa);
¨ N.B.: In questo caso la variabile non è preceduta da & (i motivi saranno chiari in seguito)
¨ Nell’input di stringhe, la scanf scarta automaticamente i white space iniziali e continua a leggere fino a quando incontra un white space (quindi non si può usare la scanf in questa forma per leggere una stringa composta da più di una parola)
¨ Attenzione: cosa succede se l’utente inserisce una stringa con 10 caratteri?
I/O di stringhe
¨ Il C di norma non effettua controlli. Continua a scrivere in memoria anche oltre la fine dell’array: si ha un buffer overflow
¨ In questo modo scanf potrebbe sovrascrivere altre strutture dati oppure scrivere in una zona di memoria in cui il programma non ha il permesso di scrivere (il runtime può dare l’errore di
segmentation fault).
p r o g r
0 1 2 3 4 5 6 7
char stringa[8]; a m m a \0
I/O di stringhe
¨ Per prevenire questi errori bisogna limitare il numero di caratteri letti in input:
scanf("%7s", stringa);
¨ In questo modo scanf interrompe la lettura dopo al massimo 7 caratteri (l’array ha capienza 8 ma dobbiamo lasciare un carattere per lo '\0' finale).
Eventuali caratteri non letti rimangono nel buffer
I/O di stringhe
¨ Per l’input di stringhe, la funzione scanf ha due limitazioni:
¤ Termina la lettura al primo whitespace
¤ Non è agevole limitare il numero di caratteri in input usando il valore di una variabile o una costante simbolica
¨ Per questi motivi può essere utile usare, invece, la funzione fgets, che legge righe di testo e accetta come parametro anche la dimensione del vettore di caratteri
10
I/O di stringhe
¨ Per utilizzare fgets occorre include stdio.h char* fgets(char *str, int size, FILE
*stream);
¨ str è l’array di char in cui memorizzare la stringa (che può contenere anche spazi)
¨ size è la dimensione dell’array (quindi la lettura
termina al massimo dopo size-1 caratteri letti in modo da lasciare un elemento nell’array per lo '\0' finale)
¨ stream nel caso di input da tastiera è sempre impostato come stdin (vedremo più in là la lettura da file)
¨ In caso di errore restituisce NULL
I/O di stringhe
¨ Nota: a differenza di scanf, fgets conserva al termine della stringa il carattere newline ('\n') (ad eccezione del caso in cui l’utente inserisca una stringa più lunga di size-1)
¨ Quindi per leggere una stringa con fgets si può scrivere così:
char str[SIZE];
if (fgets(str, SIZE, stdin) == NULL) { //trattamento dell’errore
}
if (strlen(str) > 0 && str[strlen(str)-1] == '\n') str[strlen(str)-1] = '\0';
Matrici e vettori di stringhe
Matrici
¨ Le matrici sono array bidimensionali
¨ Definizione:
tipo nome[numero_righe][numero_colonne];
¨ L’indice per le righe va da 0 a numero_righe-1, quello delle colonne da 0 a numero_colonne-1
¨ Es.:
int matr[3][6];
definisce una matrice matr di 3 righe (con indice da 0 a 2) e 6 colonne (con indice da 0 a 5)
matr[2][3] è una variabile di tipo int
12
Matrici
¨ Una matrice viene interpretata dal C come un vettore di vettori
¨ Quindi int matr[3][6]; definisce un vettore di 3 elementi ognuno dei quali è un vettore di 6 interi
¨ Vengono memorizzati per righe
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
matr[0] matr[1] matr[2]
matr[0][4] matr[2][3]
Vettori di stringhe
¨ Un vettore di stringhe, quindi, corrisponde a una matrice di caratteri
¨ Esempio:
char elenco[10][100];
definisce un vettore di 10 stringhe lunghe ognuna al massimo 99 caratteri
¨ Ogni riga della matrice si può usare come una stringa.
Ad es.
strcpy(elenco[2], "latte");
scanf("%99s", elenco[9]);