Salta al contenuto
Note per Studenti Array e stringhe in C

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.

c
#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 0 a N - 1; v[i] si trova all'indirizzo v + i * sizeof(int), per questo l'accesso è O(1)O(1).
  • Nessun controllo degli indici: v[N] o v[-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:

c
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.
  • const dichiara che la funzione non modificherà gli elementi.

Matrici

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

c
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' (O(n)O(n))
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
c
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 == s2 per confrontare stringhe: confronta gli indirizzi. Usare strcmp.
  • s = "testo"; per assegnare a un array di char: errore; usare strcpy o 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.

Teoria collegata