Array e stringhe in C
In questa pagina 5
Array
Un array è una sequenza di N elementi dello stesso tipo in celle di memoria contigue. La dimensione è fissata alla dichiarazione.
#define N 5
int v[N]; /* valori indeterminati */
int w[5] = {3, 1, 4, 1, 5};
int z[100] = {0}; /* tutti a zero */
int u[] = {2, 7, 1}; /* dimensione dedotta: 3 */
for (int i = 0; i < N; i++) {
v[i] = i * i;
}- Indici da
0aN - 1;v[i]si trova all'indirizzov + i * sizeof(int), per questo l'accesso è . - Nessun controllo degli indici:
v[N]ov[-1]leggono/scrivono memoria altrui (comportamento indefinito: valori casuali, crash, variabili vicine modificate). - Non si può assegnare un array a un altro (
w = v;è un errore) né confrontarli con==: si copia elemento per elemento. sizeof(w) / sizeof(w[0])dà il numero di elementi, ma solo dove l'array è dichiarato, non dentro una funzione che lo riceve.
Rispetto alle Liste in Pythonlist come sequenza mutabile (array dinamico); indici, slicing e assegnamento a fette; metodi e loro costo; aliasing, copia superficiale e profonda; list comprehension; liste annidate e matrici.Liste in Python →: niente append, niente lunghezza memorizzata, niente tipi misti. Per una dimensione decisa a run-time serve l'allocazione dinamica (Gestione della memoria in CSegmenti di memoria di un processo (codice, dati statici, stack, heap); durata delle variabili; allocazione dinamica con malloc, calloc, realloc e free; errori classici: memory leak, dangling pointer, double free, buffer overflow; strumenti di controllo.Gestione della memoria in C →).
Array e funzioni
Il nome di un array, in quasi tutte le espressioni, vale l'indirizzo del primo elemento (vedi Puntatori in CUn puntatore contiene un indirizzo di memoria; operatori & e *, NULL, puntatori come parametri per modificare variabili del chiamante, aritmetica dei puntatori, legame tra array e puntatori, const, puntatori a puntatori.Puntatori in C →). Passandolo a una funzione si passa quell'indirizzo:
int somma(const int v[], int n) { /* equivalente a: const int *v */
int s = 0;
for (int i = 0; i < n; i++)
s += v[i];
return s;
}
void azzera(int v[], int n) { /* modifica l'array del chiamante */
for (int i = 0; i < n; i++)
v[i] = 0;
}
/* chiamate: somma(w, 5); azzera(w, 5); */- La lunghezza va sempre passata come parametro.
constdichiara che la funzione non modificherà gli elementi.
Matrici
int m[3][4]; /* 3 righe, 4 colonne, memorizzate riga per riga */
m[1][2] = 7;
void stampa(int m[][4], int righe) { /* tutte le dimensioni tranne la prima vanno indicate */
for (int i = 0; i < righe; i++) {
for (int j = 0; j < 4; j++)
printf("%3d", m[i][j]);
printf("\n");
}
}Stringhe
Una stringa C è un array di char che termina con il carattere nullo '\0' (valore 0). La lunghezza non è memorizzata: si conta fino a '\0'.
char s[] = "ciao"; /* 5 byte: 'c' 'i' 'a' 'o' '\0' */
char t[20] = "ciao"; /* 20 byte, i restanti a zero */
char c = 'a'; /* carattere: apici singoli */
/* "a" è una stringa di 2 byte: 'a' e '\0' */Una stringa di n caratteri richiede un array di almeno n + 1 char.
string.h
| Funzione | Effetto |
|---|---|
strlen(s) |
numero di caratteri prima di '\0' () |
strcpy(dst, src) |
copia src in dst (dst deve essere abbastanza grande) |
strncpy(dst, src, n) |
copia al più n caratteri (può non aggiungere '\0') |
strcat(dst, src) |
accoda src a dst |
strcmp(a, b) |
< 0, 0, > 0 se a precede, è uguale, segue b (ordine dei codici) |
strchr(s, c), strstr(s, sub) |
puntatore alla prima occorrenza, o NULL |
char nome[32];
strcpy(nome, "Ada");
if (strcmp(nome, "Ada") == 0) { /* uguali */ }
/* lunghezza scritta a mano */
int lunghezza(const char s[]) {
int n = 0;
while (s[n] != '\0')
n++;
return n;
}<ctype.h>: isdigit(c), isalpha(c), isspace(c), toupper(c), tolower(c).
Lettura di stringhe da tastiera e da file: Input e output in Cprintf con larghezza e precisione, scanf con indirizzi e valore di ritorno, lettura di righe con fgets, file con FILE*, fopen, fclose, fprintf, fscanf, controllo degli errori e della fine del file.Input e output in C →.
Errori tipici
s1 == s2per confrontare stringhe: confronta gli indirizzi. Usarestrcmp.s = "testo";per assegnare a un array dichar: errore; usarestrcpyo inizializzare nella dichiarazione.- Dimenticare lo spazio per
'\0'o non aggiungerlo costruendo una stringa a mano: le funzioni continuano a leggere oltre la fine. - Uscire dai limiti dell'array (
for (i = 0; i <= N; i++)). - Usare
sizeof(v)dentro una funzione per avere la lunghezza: dà la dimensione di un puntatore.