Concatenare Stringhe in Linguaggio C

Un'operazione comune che si presenta, spesso, quando si lavora con le stringhe è la concatenazione di due stringhe. Il linguaggio C non fornisce un operatore per concatenare due stringhe come fanno molti altri linguaggi.

Tuttavia, possiamo usare le funzioni strcat e strncat della libreria standard string.h per concatenare due stringhe in linguaggio C.

Esse accettano due puntatori a stringa e concatenano la seconda stringa alla fine della prima. Inoltre, restituiscono il puntatore alla prima stringa.

In questa lezione vedremo come utilizzare le funzioni strcat e strncat per concatenare due stringhe in linguaggio C. Inoltre, vedremo come implementare manualmente queste funzioni per capirne meglio il funzionamento e i problemi intrinseci.

Funzione strcat - Concatenazione di stringhe

In linguaggio C non possiamo usare l'operatore di somma +, come fanno molti altri linguaggi, per concatenare due stringhe.

Possiamo, invece, usare la funzione strcat della libreria standard string.h.

La funzione strcat accetta due puntatori a stringa e concatena la seconda stringa alla fine della prima. Inoltre, restituisce il puntatore alla prima stringa.

La sua firma è:

char *strcat(char *dest, const char *src);

Dove:

  • dest è il puntatore alla stringa di destinazione, cioè la stringa a cui vogliamo aggiungere la seconda stringa.
  • src è il puntatore alla stringa sorgente, cioè la stringa che vogliamo aggiungere alla stringa di destinazione.

Vediamo un esempio:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <stdio.h>
#include <string.h>

int main() {
    char s[128] = "Hello";
    char t[128] = "World";

    printf("Prima: %s\n", s);
    printf("Seconda: %s\n", t);

    strcat(s, t);

    printf("Dopo: %s\n", s);

    return 0;
}

In questo esempio, definiamo due array di caratteri s e t e li inizializziamo con le stringhe "Hello" e "World". Poi, concateniamo la stringa t alla stringa s usando la funzione strcat. Infine, stampiamo il risultato.

Il programma stampa:

Prima: Hello
Seconda: World
Dopo: HelloWorld

Come possiamo vedere, la stringa t è stata concatenata alla stringa s.

Il valore di ritorno della funzione strcat è spesso ignorato, poiché restituisce il puntatore alla stringa di destinazione, che è lo stesso puntatore passato come primo argomento. Tuttavia, possiamo usarlo per concatenare più stringhe in una sola riga di codice:

char s[128] = "Hello";
char t[128] = "World";
char u[128] = "!";
strcat(s, strcat(t, u));

In questo caso, la stringa u è concatenata alla stringa t; successivamente, il risultato di questa operazione, ossia t, è concatenato alla stringa s.

Il risultato finale è:

  • u conterrà "!";
  • t conterrà "World!";
  • s conterrà "HelloWorld!".
Definizione

Funzione strcat

La funzione strcat accetta due puntatori a stringa e concatena la seconda stringa alla fine della prima. Inoltre, restituisce il puntatore alla prima stringa.

Essa è definita nella libreria standard string.h:

#include <string.h>

La sua firma è:

char *strcat(char *dest, const char *src);
  • dest è il puntatore alla stringa di destinazione, cioè la stringa a cui vogliamo aggiungere la seconda stringa.
  • src è il puntatore alla stringa sorgente, cioè la stringa che vogliamo aggiungere alla stringa di destinazione.

Il valore di ritorno è il puntatore alla stringa di destinazione: dest.

Nota

La funzione strcat non è sicura

La funzione strcat non verifica se la stringa di destinazione ha abbastanza spazio per contenere se stessa e la stringa sorgente. Se la stringa di destinazione non ha abbastanza spazio, la funzione può sovrascrivere la memoria adiacente, causando comportamenti indefiniti.

Per evitare questo problema, possiamo usare la funzione strncat, che accetta un terzo argomento che specifica il numero massimo di caratteri da concatenare.

Funzione strncat - Concatenazione di stringhe con limite

Per evitare il problema di strcat, possiamo usare la funzione strncat della libreria standard string.h.

La funzione strncat accetta due puntatori a stringa e un limite superiore e concatena la seconda stringa alla fine della prima, fino al limite superiore. Inoltre, restituisce il puntatore alla prima stringa.

La sua firma è:

char *strncat(char *dest, const char *src, size_t n);

Dove:

  • dest è il puntatore alla stringa di destinazione, cioè la stringa a cui vogliamo aggiungere la seconda stringa.
  • src è il puntatore alla stringa sorgente, cioè la stringa che vogliamo aggiungere alla stringa di destinazione.
  • n è il numero massimo di caratteri da concatenare, escluso il terminatore \0.

Vediamo un esempio di utilizzo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>

#define MAX_SIZE 128

int main() {
    char s1[MAX_SIZE] = "Hello";
    char s2[MAX_SIZE] = "World";

    printf("Prima: %s\n", s1);
    printf("Seconda: %s\n", s2);

    strncat(s1, s2, MAX_SIZE - strlen(s1) - 1);

    printf("Dopo: %s\n", s1);

    return 0;
}

In questo esempio, definiamo due array di caratteri s1 e s2 e li inizializziamo con le stringhe "Hello" e "World".

Poi, concateniamo la stringa s2 alla stringa s1 usando la funzione strncat. Il terzo argomento passato alla funzione è il numero massimo di caratteri da concatenare, che è calcolato come la differenza tra la dimensione massima dell'array s1, MAX_SIZE, e la lunghezza attuale della stringa s1, ottenuto con la funzione strlen, meno 1 per il terminatore \0.

L'output del programma sarà:

Prima: Hello
Seconda: World
Dopo: HelloWorld
Consiglio

Calcolare il numero di caratteri da concatenare

Se dobbiamo concatenare due stringhe, s e t, e sappiamo che la stringa di destinazione, s, ha una dimensione massima di MAX_SIZE, possiamo calcolare il numero di caratteri da concatenare come:

MAX_SIZE - strlen(s) - 1

Questo perché alla stringa di destinazione possiamo aggiungere un numero di caratteri pari alla sua lunghezza massima, meno la sua lunghezza attuale, meno 1 per il terminatore \0.

Per cui, l'utilizzo tipico di strncat è:

strncat(s, t, MAX_SIZE - strlen(s) - 1);

Implementazione di strcat e strncat

Anche in questo caso, è utile, dal punto di vista didattico, implementare le funzioni strcat e strncat manualmente. In questo modo possiamo capirne meglio il funzionamento e i problemi intrinseci.

Partiamo dalla funzione strcat:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
char *mia_strcat(char *dest, const char *src) {
    char *p = dest;

    while (*p != '\0') {
        p++;
    }

    while (*src != '\0') {
        *p = *src;
        p++;
        src++;
    }

    *p = '\0';

    return dest;
}

Analizziamo il codice. La funzione utilizza un puntatore locale, p, con cui scorre la stringa di destinazione. In particolare, utilizza due cicli while:

  1. Il primo ciclo while, righe 4-6, scorre la stringa di destinazione fino a trovare il terminatore \0;
  2. Dopo questo ciclo while abbiamo che il puntatore p punta al terminatore \0 della stringa di destinazione. Questo terminatore andrà sostituito con il primo carattere della stringa sorgente, src. Per fare ciò, utilizziamo un secondo ciclo while, righe 8-12, che copia i caratteri della stringa sorgente nella stringa di destinazione.

Infine, la funzione pone il terminatore \0 alla fine della stringa di destinazione e restituisce il puntatore ad essa.

Il problema della strcat sta proprio nel fatto che i due cicli while non controllano se la stringa di destinazione ha abbastanza spazio per contenere se stessa e la stringa sorgente. Non solo, ma non controllano nemmeno se i due puntatori alle stringhe passati come argomenti puntano a stringhe valide.

La funzione strncat risolve il primo problema. Vediamone una possibile implementazione che chiameremo mia_strncat:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
char *mia_strncat(char *dest, const char *src, size_t n) {
    char *p = dest;

    while (*p != '\0') {
        p++;
    }

    while (*src != '\0' && n > 0) {
        *p = *src;
        p++;
        src++;
        n--;
    }

    *p = '\0';

    return dest;
}

La funzione mia_strncat è simile alla mia_strcat, ma ha un terzo argomento, n, che rappresenta il numero massimo di caratteri da concatenare. La differenza principale rispetto alla strcat sta nel secondo ciclo while, righe 8-13, che controlla anche il numero di caratteri da concatenare.

Infatti, la condizione *src != '\0' && n > 0 controlla se il carattere corrente della stringa sorgente è diverso dal terminatore \0 e se il numero di caratteri da concatenare è maggiore di 0. Inoltre, all'interno del ciclo while, decrementiamo il contatore n ad ogni iterazione.

In questo modo, la funzione mia_strncat non concatenerà più di n caratteri, evitando così di sovrascrivere la memoria adiacente.

In Sintesi

In linguaggio C, possiamo concatenare due stringhe usando la funzione strcat della libreria standard string.h. Questa funzione accetta due puntatori a stringa e concatena la seconda stringa alla fine della prima. Tuttavia, la funzione strcat non verifica se la stringa di destinazione ha abbastanza spazio per contenere se stessa e la stringa sorgente, causando comportamenti indefiniti.

Per evitare questo problema, possiamo usare la funzione strncat, che accetta un terzo argomento che specifica il numero massimo di caratteri da concatenare.

Entrambe le funzioni restituiscono il puntatore alla stringa di destinazione.

Inoltre, abbiamo visto come implementare manualmente le funzioni strcat e strncat, per capirne meglio il funzionamento e i problemi intrinseci.

Nella prossima lezione vedremo come confrontare stringhe in linguaggio C.