Stringhe dichiarazione e input/output assegnamento e sottostringhe concatenazione confronto array di puntatori a stringhe input/output, analisi e conversione di caratteri conversione da stringa a numero e viceversa 1
Stringhe Una stringa è una sequenza di caratteri. Esempi: printf( Sum = %d, s); #define ERR_PREFIX ***** Error - #define INSUFF_DATA Insufficient data 2
Dichiarazione e inizializzazione char str_var[30]; la variabile str_var può contenere una stringa contenente un numero di caratteri compreso tra 0 e 29 char str[20] = Initial value ; I n i t i a l v a l u e \0 [0] [4] [9] [14] [19] 3
Carattere nullo Il carattere \0, chiamato carattere nullo, indica la fine della stringa. A causa della presenza del carattere nullo, le stringhe memorizzabili in un array di caratteri hanno come lunghezza massima la dimensione dell array meno 1. Le funzioni C per la manipolazione di stringhe ignorano il contenuto degli elementi che seguono il carattere nullo. 4
Array di stringhe Poichè una stringa è un array di caratteri, un array di stringhe è un array bidimensionale di caratteri, in cui ogni riga è una stringa. Es:. #define NUM_PEOPLE 30 #define NAME_LEN 25 char names[num_people][name_len]; char month[12][10] = { January, February, March, April, May, June, July, August, September, October, November, December }; 5
Input / Output printf( Topic: %s\n, str_var); stampa i caratteri contenuti in str_var che precedono il carattere nullo. printf( ***%8s***\n, Short ); stampa la stringa Short all interno di un campo di 8 caratteri, giustificata a destra. se la dimensione del campo è troppo piccola per contenere la stringa, il campo viene esteso della quantità minima necessaria per poter contenere la stringa. 6
Input / Output printf( %-10s\n, String ); stampa la stringa String all interno di un campo di 10 caratteri, giustificata a sinistra. char name[name_len]; scanf( %s, name); prende in input una stringa; poichè il passaggio di parametri di tipo array avviene passando l indirizzo del primo elemento dell array, la variabile name non deve essere preceduta da & 7
scanf( %s, name); [0] N a d i a \0 [4] [9] [14] dati inseriti > Nadia spazi ignorati causa l inserimento di \0 La scanf ignora spazi, return e tab iniziali; inserisce quindi i caratteri in celle consecutive; quando trova uno spazio (o return o tab) aggiunge il carattere nullo e termina la scansione dell input. 8
char name[name_len]; int age; Input - esempio scanf( %s%d, name, &age); > Nadia25 Se non separo i dati in input con spazi, la scanf non è in grado di separare i dati e inserisce la sequenza di caratteri Nadia25 nella stringa name: name N a d i a 2 5 \0 age?? 9
Input - esempio char names[num_people][name_len]; int ages[num_people]; for (i = 0; i < NUM_PEOPLE; i++) { scanf( %s%d, names[i], &ages[i]); printf( %-35s %3d\n, names[i], ages[i]); } riempie gli array contenenti nomi ed età di un insieme di persone ed effettua l eco dei dati inseriti. 10
Assegnamento Un nome di array senza indici rappresenta l indirizzo del primo elemento dell array. Tale indirizzo è costante e non può essere cambiato con un assegnamento: char str[15]; str = Test string ; /* errore! */ viene segnalato un errore in fase di compilazione 11
Assegnamento La libreria string.h fornisce funzioni per operare sulle stringhe. strcpy(str, Test string ); copia la stringa fornita come secondo argomento nel primo argomento. str T e s t s t r i n g \0 12
Assegnamento La prima stringa deve avere dimensione sufficiente a contenere la seconda stringa più il carattere nullo strcpy(str, A long test string ); in questo caso i caratteri finali i, n, g e \0 vengono memorizzati in locazioni riservate ad altre variabili. str A l o n g t e s t s t r 13
Assegnamento La funzione strncpy permette di specificare il numero di caratteri da copiare: strncpy(str, Test, 15); str T e s t \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 Se la stringa sorgente è più corta del numero di caratteri specificato, i restanti caratteri vengono posti a nullo. 14
Assegnamento Per assegnare il massimo prefisso della stringa sorgente alla stringa destinazione si utilizzano le seguenti istruzioni: strncpy(dest, source, dest_len - 1); dest[dest_len - 1] = \0 ; 15
Prototipo di strcpy e strncpy char *strcpy(char *dest, char *source); char *strncpy(char *dest, char *source, size_t n); Il valore di ritorno è la stringa contenuta in dest. Il chiamante può ottenere il risultato in due modi: può utilizzare il primo argomento può utilizzare il valore di ritorno 16
Sottostringhe - prefissi Le funzioni strcpy e strncpy possono essere utilizzate per estrarre frammenti (sottostringhe) di una stringa. Es.: estrarre giorno, mese ed anno dalla stringa 27/09/1999 I primi n caratteri di una stringa possono essere estratti mediante le seguenti istruzioni: strncpy(result, source, n); result[n] = \0 ; 17
Sottostringhe centrali Un nome di array senza indici rappresenta l indirizzo del primo elemento dell array. Per estrarre una sottostringa centrale che inizia alla posizione k (e di lunghezza n) forniamo a strncpy l indirizzo dell elemento di indice k: strncpy(result, &source[k], n); result[n] = \0 ; 18
Sottostringhe - suffissi Per estrarre la parte finale di una stringa, a partire dalla posizione k, utilizzo la seguente istruzione: strcpy(result, &source[k]); La funzione strcpy copia tutti i caratteri finchè non trova (e copia) il carattere nullo. 19
Sottostringhe - esempio Estrazione di giorno, mese ed anno dalla data: char date[11] = 15/01/2000 ; char day[3], month[3], year[5]; strncpy(day, date, 2); day[2] = \0 ; strncpy(month, &date[3], 2); month[2] = \0 ; strcpy(year, &date[6]); 20
Lunghezza e stringa vuota La lunghezza di una stringa è il numero di caratteri che precedono il carattere nullo. La funzione strlen restituisce la lunghezza della stringa. char str[20] = hello ; printf( %d\n, strlen(str)); La stringa vuota è una stringa di lunghezza 0; il primo carattere della stringa è il carattere nullo: char empty_str[30] = ; 21
Concatenazione Le funzioni strcat e strncat modificano il primo argomento aggiungendo tutta o parte della stringa fornita come secondo argomento. Le due funzioni assumono che il primo argomento abbia dimensione sufficiente a contenere i caratteri che vengono aggiunti. 22
Concatenazione #define STRSIZ 15 char f1[strsiz] = John, f2[strsiz] = Jacqueline, last[strsiz] = Kennedy ; strcat(f1, last); strcat(f2, last); f1 J o h n K e n n e d y \0 f2 J a c q u e l i n e K e n n i caratteri e, d, y vengono posti all inizio di last. 23
Concatenazione - carattere nullo La funzione strcat aggiunge un intera stringa, comprensiva del carattere nullo. La funzione strncat aggiunge il carattere nullo solo c è un carattere nullo tra gli n caratteri copiati. 24
Siano s1 ed s2 due stringhe di lunghezza STRSIZ: char s1[strsiz], s2[strsiz]; Se possibile viene effettuata la concatenazione di s1 ed s2; se lo spazio non è sufficiente, viene aggiunto il massimo prefisso di s2 che non causa overflow: if (strlen(s1) + strlen(s2) < STRSIZ) { strcat(s1, s2); } else { strncat(s1, s2, STRSIZ - strlen(s1) - 1); s1[strsiz -1] = \0 ; } 25
Punti critici nella manipolazione di stringhe la dimensione del parametro di output è sufficiente a contenere la stringa che stiamo creando? la stringa che stiamo creando termina con \0? 26
Differenza tra caratteri e stringhe Il carattere b non è un argomento valido per una funzione che richiede una stringa (es.: strcat, strcpy,...) b carattere b b \0 stringa b 27
Input di una linea di testo La funzione scanf utilizza gli spazi come delimitatori della fine di una stringa. La funzione gets permette di prendere in input un intera linea di testo (fino al carattere return): char line[80]; printf( > ); gets(line, 80); > Short line. S h o r t l i n e. \0 28
Confronto di stringhe str1 < str2 se str1 e str2 sono stringhe, la condizione è vera se la locazione contenente il primo elemento di str1 precede la locazione contenente il primo elemento di str2. La funzione di libreria strcmp effettua il confronto di 2 stringhe: strcmp(str1, str2) ritorna un valore negativo se str1 è minore di str2 0 se str1 è uguale ad str2 un valore positivo se str1 è maggiore di str2 29
Ordinamento di stringhe 1. se i primi n caratteri di str1 ed str2 sono uguali e i caratteri in posizione n sono diversi, allora str1 è minore di str2 se str1[n] < str2[n] es.: thrill è minore di throw 2. se str1 è più corta di str2 e tutti i caratteri di str1 sono uguali ai corrispondenti caratteri di str2, allora str1 è minore di str2 es.: joy è minore di joyous 30
Il confronto tra stringhe è utile per ordinare un elenco di stringhe (es. con il selection sort): Confronto (nella funzione get_min_range) tra numeri if (list[i] < list[first])... tra stringhe if (strcmp(list[i], list[first]) < 0)... 31
Scambio di elementi tra numeri temp = list[index_of_min]; list[index_of_min] = list[fill]; list[fill] = temp; tra stringhe strcpy(temp, list[index_of_min]); strcpy(list[index_of_min], list[fill]); strcpy(list[fill], temp); 32
Input di stringhe controllato da sentinella scanf( %s, word); while (strcmp(word, SENT)!= 0) { /* process word */ } scanf( %s, word); 33
Array di puntatori Lo scambio di stringhe è un operazione costosa perchè richiede 3 operazioni di copiatura di stringhe. In questo caso è conveniente utilizzare un array ausiliario di puntatori a stringhe ed effettuare scambi di puntatori. In aggiunta a char list[numelem][strsiz]; si dichiara l array di puntatori char *alphap[numelem]; 34
alphap list t u l i p \0 m a r i g o r o s e \0 p e t u n i d a i s y \0 l i l y \0 l a d \0 \0 Visualizzazione della lista ordinata: for (i = 0; i < NUMELEM; i++) printf( %s\n, alphap[i]); L array ausiliario di puntatori è utile per mantenere due diversi ordinamenti in una lista (es.: ordine di registrazione e ordine alfabetico) 35
Input/output di caratteri L input di un carattere può essere effettuato nei seguenti modi: scanf( %c, ch); ch = getchar(); L output di un carattere può essere effettuato nei seguenti modi: printf( %c, a ); putchar( a ); 36
Analisi di caratteri La libreria ctype.h contiene le seguenti funzioni di analisi e conversione di caratteri: isalpha isdigit islower isupper ispunct isspace vera se l argomento è una lettera vera se l argomento è una cifra vera se l argomento è una lettera minuscola vera se l argomento è una lettera maiuscola vera se l argomento è un segno di punteggiatura vera se l argomento è uno spazio, un return o un tab 37
Conversione di caratteri tolower converte la lettera maiuscola fornita come argomento nella corrispondente lettera minuscola e ritorna quest ultima; se l argomento non è una lettera maiuscola, ritorna l argomento invariato toupper analogo da minuscola a maiuscola if (islower(ch)) printf( Capital %c = %c\n, ch, toupper(ch)); 38
Conversione da numero a stringa La funzione sprintf opera come la printf, ma anzichè visualizzare l output, lo inserisce nella stringa specificata: int day = 30, month = 1, year = 1999; char s[100]; sprintf(s, %d/%d/%d, day, month, year); s 3 0 / 1 / 1 9 9 9 \0 39
Conversione da stringa a numero La funzione sscanf opera come la scanf, ma prende l input dalla stringa specificata come primo argomento: int num; double val; char word[10]; sscanf( 5 1.23 hello, %d%lf%s, &num, &val, word); num 5 val 1.23 word h e l l o \0 40
/* returns the uppercase version of string s */ char * toupper_str(char *s, int len) { char temp[100]; int i; for (i = 0; i < len; i++) temp[i] = toupper(s[i]); } return(temp); Errore: ritorno un indirizzo di un area di memoria che è stata deallocata al ritorno dalla funzione. Le funzioni che creano una nuova stringa devono avere un parametro in cui ritornare la stringa creata. 41
int n; char ch, word[10]; Esempio scanf( %c%d%s, &ch, n, &word); Errore: word è un puntatore al primo carattere di una stringa, quindi non occorre &; n è una variabile quindi deve essere preceduta da &; versione corretta: scanf( %c%d%s, &ch, &n, word); 42
Esempio char first[8] = long, last[8] = beach ; strcat(first, last); Errore di overflow: first non ha dimensioni sufficienti a contenere la stringa long beach : first l o n g b e a I restanti caratteri, c, h e \0, vengono posti nelle locazioni di last. 43
Esempio char source[10] = hello, dest[10]; strncpy(dest, source, 4); Errore: la dimensione di word non è sufficiente a contenere il carattere nullo; ho dimenticato di aggiungere il carattere nullo al termine di dest. source h e l l o \0 dest h e l l 44
Esempio char second[10] = tulip, first[10] = lily ; if (first < second) printf( ok\n ); Errore: l operatore < non effettua il confronto tra stringhe ma tra gli indirizzi di memoria dei primi elementi delle stringhe; versione corretta: if (strcmp(first, second) < 0) printf( ok\n ); 45
Esempio char s1[10], s2[10], temp[10]; /* swap s1 and s2 */ temp = s1; s1 = s2; s2 = temp; Errore: l assegnamento di stringhe va effettuato mediante strcpy. Versione corretta: strcpy(temp, s1); strcpy(s1, s2); strcpy(s2, temp); 46