[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home] [volume] [parte]


Capitolo 602.   C: «string.h»

Il file string.h della libreria standard definisce il tipo size_t, la macro-variabile NULL (come dal file stddef.h, descritto nel capitolo 601) e una serie di funzioni per il trattamento delle stringhe o comunque di sequenze di caratteri.

602.1   Copia

Seguono i prototipi delle funzioni disponibili per la copia:

void *memcpy  (void *restrict dst, const void *restrict org, size_t n);
void *memmove (void *dst, const void *org, size_t n);
char *strcpy  (char *restrict dst, const char *restrict org);
char *strncpy (char *restrict dst, const char *restrict org, size_t n);

602.1.1   Funzione «memcpy()» (memory copy)

La funzione memcpy() copia n caratteri a partire dall'indirizzo indicato da org, per riprodurli a partire dall'indirizzo dst, alla condizione che i due insiemi non risultino sovrapposti. La funzione restituisce l'indirizzo dst.

#include <string.h>
void
*memcpy (void *restrict dst, const void *restrict org, size_t n)
{
    unsigned char *d = (unsigned char *) dst;
    unsigned char *o = (unsigned char *) org;
    size_t i;
    for (i = 0; n > 0 && i < n; i++)
      {
        d[i] = o[i];
      }
    return dst;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, dove la variabile y viene sovrascritta dal contenuto di x, ma questo attraverso la copia dei byte (si intende che gli interi siano da 32 bit).

#include <stdio.h>
#include <string.h>

int
main (void)
{
    int  x = 0x123456FF;
    int  y = 0xFFFFFFFF;
    printf ("prima: %x\n", y);
    memcpy (&y, &x, sizeof (int));
    printf ("dopo: %x\n", y);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

prima: ffffffff
dopo: 123456ff

602.1.2   Funzione «memmove()» (memory move)

La funzione memmove() opera in modo simile a memcpy(), con la differenza che le due aree di memoria coinvolte possono sovrapporsi. In pratica la copia avviene prima in un'area temporanea, quindi, dall'area temporanea viene ricopiata nella destinazione. La funzione restituisce l'indirizzo dst.

#include <string.h>
void
*memmove (void *dst, const void *org, size_t n)
{
    char temp[n];
    unsigned char *d = (unsigned char *) dst;
    unsigned char *o = (unsigned char *) org;
    size_t i;
    for (i = 0; i < n; i++)
      {
        temp[i] = o[i];
      }
    for (i = 0; n > 0 && i < n; i++)
      {
        d[i] = temp[i];
      }
    return dst;
}

Per osservare il comportamento della funzione si può riutilizzare lo stesso programma usato per memcpy(), con la modifica del nome della funzione chiamata. Il risultato atteso è lo stesso:

...
    printf ("prima: %x\n", y);
    memmove (&y, &x, sizeof (int));
    printf ("dopo: %x\n", y);
...

602.1.3   Funzione «strcpy()» (string copy)

La funzione strcpy() copia la stringa org nell'array a cui punta dst, includendo anche il carattere zero di conclusione delle stringhe, alla condizione che le due stringhe non si sovrappongano. La funzione restituisce dst.

#include <string.h>
char
*strcpy (char *restrict dst, const char *restrict org)
{
    size_t i;
    for (i = 0; org[i] != 0; i++)
      {
        dst[i] = org[i];
      }
    dst[i] = 0;
    return dst;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, dove l'array y viene sovrascritto dal contenuto di x.

#include <stdio.h>
#include <string.h>
int main (void)
{
    char x[] = "abcdefghijklmnopqrstuvwxyz";
    char y[50] = "ciao";
    printf ("prima: %s\n", y);
    strcpy (y, x);
    printf ("dopo: %s\n", y);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

prima: ciao
dopo: abcdefghijklmnopqrstuvwxyz

602.1.4   Funzione «strncpy()»

La funzione strncpy() funziona in modo analogo a quello di strcpy, con la differenza che la copia riguarda al massimo i primi n caratteri, includendo in questo anche il carattere nullo di terminazione delle stringhe. Se però la stringa org è più breve (in quanto si incontra il carattere di terminazione prima di n caratteri), i caratteri rimasti vengono copiati con un valore a zero nella destinazione. La funzione restituisce dst.

#include <string.h>
char
*strncpy (char *restrict dst, const char *restrict org, size_t n)
{
    size_t i;
    for (i = 0; n > 0 && i < n && org[i] != 0; i++)
      {
        dst[i] = org[i];
      }
    for ( ; n > 0 && i < n; i++)
      {
        dst[i] = 0;
      }
    return dst;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, dove l'array y viene sovrascritto dal contenuto di x.

#include <stdio.h>
#include <string.h>
int main (void)
{
    char x[] = "abcdefghijklmnopqrstuvwxyz";
    char y[50] = "ciaociaociaociaociaociaociaociao";
    printf ("prima: %s\n", y);
    strncpy (y, x, 10);
    printf ("durante: %s\n", y);
    strncpy (y, x, 27);
    printf ("dopo: %s\n", y);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

prima: ciaociaociaociaociaociaociaociao
durante: abcdefghijaociaociaociaociaociao
dopo: abcdefghijklmnopqrstuvwxyz

602.2   Concatenamento

Seguono i prototipi delle funzioni per il concatenamento:

char *strcat  (char *restrict dst, const char *restrict org);
char *strncat (char *restrict dst, const char *restrict org, size_t n);

602.2.1   Funzione «strcat()» (string cat)

La funzione strcat() copia la stringa org a partire dalla fine della stringa dst (sovrascrivendo il carattere nullo preesistente), alla condizione che le due stringhe non siano sovrapposte. La funzione restituisce dst.

#include <string.h>
char
*strcat (char *restrict dst, const char *restrict org)
{
    size_t i;
    size_t j;
    for (i = 0; dst[i] != 0; i++)
      {
        ; // Si limita a cercare il carattere nullo.
      }
    for (j = 0; org[j] != 0; i++, j++)
      {
        dst[i] = org[j];
      }
    dst[i] = 0;
    return dst;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, dove la stringa y viene estesa con il contenuto di x.

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char x[] = "abcdefghijklmnopqrstuvwxyz";
    char y[50] = "ciao";
    printf ("prima: %s\n", y);
    strcat (y, x);
    printf ("dopo: %s\n", y);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

prima: ciao
dopo: ciaoabcdefghijklmnopqrstuvwxyz

602.2.2   Funzione «strncat()»

La funzione strncat() si comporta in modo analogo a strcat(), con la differenza che copia al massimo n caratteri, ammesso che la stringa org ne contenga abbastanza. In ogni caso, la stringa dst viene completata con il carattere nullo di terminazione.

#include <string.h>
char
*strncat (char *restrict dst, const char *restrict org, size_t n)
{
    size_t i;
    size_t j;
    for (i = 0; n > 0 && dst[i] != 0; i++)
      {
        ; // Si limita a cercare il carattere nullo.
      }
    for (j = 0; n > 0 && j < n && org[j] != 0; i++, j++)
      {
        dst[i] = org[j];
      }
    dst[i] = 0;
    return dst;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, dove la stringa y viene estesa con il contenuto di x, in due fasi.

#include <stdio.h>
#include <string.h>
int main (void)
{
    char x[] = "abcdefghijklmnopqrstuvwxyz";
    char y[50] = "ciao";
    printf ("prima: %s\n", y);
    strncat (y, x, 10);
    printf ("durante: %s\n", y);
    strncat (y, x, 40);
    printf ("dopo: %s\n", y);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

prima: ciao
durante: ciaoabcdefghij
dopo: ciaoabcdefghijabcdefghijklmnopqrstuvwxyz

602.3   Comparazione

Le funzioni di comparazione memcmp(), strcmp() e strncmp() confrontano due sequenze di caratteri, determinando se la prima sia maggiore, minore o uguale rispetto alla seconda, scandendo i caratteri progressivamente e arrestando l'analisi appena si incontra una differenza. Pertanto, il carattere che differisce è quello che determina l'ordine tra le due sequenze.

int    memcmp  (const void *s1, const void *s2, size_t n);
int    strcmp  (const char *s1, const char *s2);
int    strcoll (const char *s1, const char *s2);
int    strncmp (const char *s1, const char *s2, size_t n);
size_t strxfrm (char *restrict dst, const char *restrict org, size_t n);

602.3.1   Funzione «memcmp()» (memory compare)

La funzione memcmp() confronta i primi n caratteri delle aree di memoria a cui puntano s1 e s2, restituendo: un valore pari a zero se le due sequenze si equivalgono; un valore maggiore di zero se la sequenza di s1 è maggiore di s2; un valore minore di zero se la sequenza di s1 è minore di s2.

#include <string.h>
int
memcmp (const void *s1, const void *s2, size_t n)
{
    unsigned char *a = (unsigned char *) s1;
    unsigned char *b = (unsigned char *) s2;
    size_t i;
    for (i = 0; n > 0 && i < n; i++)
      {
        if (a[i] > b[i])
          {
            return 1;
          }
        else if (a[i] < b[i])
          {
            return -1;
          }
      }
    return 0;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, dove le variabili x e y sono interi (che si presume siano a 32 bit) rappresentati in memoria invertendo l'ordine dei byte (little endian), pertanto il confronto avviene in modo inverso all'apparenza dei simboli.

#include <stdio.h>
#include <string.h>
int
main (void)
{
    unsigned int  x = 0x123456FF;
    unsigned int  y = 0xEEEEEEEE;
    int  r;
    r = memcmp (&x, &y, sizeof (int));
    printf ("memcmp: %x %d %x\n", x, r, y);
    r = memcmp (&x, &x, sizeof (int));
    printf ("memcmp: %x %d %x\n", x, r, x);
    r = memcmp (&y, &x, sizeof (int));
    printf ("memcmp: %x %d %x\n", y, r, x);
    return 0;
}

Avviando questo programma nelle condizioni descritte, si deve ottenere un risultato come quello seguente:

memcmp: 123456ff 1 eeeeeeee
memcmp: 123456ff 0 123456ff
memcmp: eeeeeeee -1 123456ff

602.3.2   Funzione «strcmp()» (string compare)

La funzione strcmp() confronta due stringhe restituendo: un valore pari a zero se sono uguali; un valore maggiore di zero se la stringa s1 è maggiore di s2; un valore minore di zero se la stringa s1 è minore di s2.

#include <string.h>
int
strcmp (const char *s1, const char *s2)
{
    unsigned char *a = (unsigned char *) s1;
    unsigned char *b = (unsigned char *) s2;
    size_t i;
    for (i = 0; ; i++)
      {
        if (a[i] > b[i])
          {
            return 1;
          }
        else if (a[i] < b[i])
          {
            return -1;
          }
        else if (a[i] == 0 && b[i] == 0)
          {
            return 0;
          }
      }
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char x[] = "ciao";
    char y[] = "ciao amore";
    int  r;
    r = strcmp (x, y);
    printf ("strcmp: %s %d %s\n", x, r, y);
    r = strcmp (x, x);
    printf ("strcmp: %s %d %s\n", x, r, x);
    r = strcmp (y, x);
    printf ("strcmp: %s %d %s\n", y, r, x);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

strcmp: ciao -1 ciao amore
strcmp: ciao 0 ciao
strcmp: ciao amore 1 ciao

602.3.3   Funzione «strcoll()» (string collate compare)

La funzione strcoll() è analoga a strcmp(), con la differenza che la comparazione avviene sulla base della configurazione locale (la categoria LC_COLLATE). Nel caso della configurazione locale C la funzione si comporta esattamente come strcmp().

602.3.4   Funzione «strncmp()»

La funzione strncmp() si comporta in modo analogo a strcmp(), con la differenza che la comparazione si arresta al massimo dopo n caratteri.

#include <string.h>
int
strncmp (const char *s1, const char *s2, size_t n)
{
    unsigned char *a = (unsigned char *) s1;
    unsigned char *b = (unsigned char *) s2;
    size_t i;
    for (i = 0; i < n ; i++)
      {
        if (a[i] > b[i])
          {
            return 1;
          }
        else if (a[i] < b[i])
          {
            return -1;
          }
        else if (a[i] == 0 && b[i] == 0)
          {
            return 0;
          }
      }
    return 0;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char x[] = "CIao";
    char y[] = "CIAO";
    int  r;
    r = strncmp (x, y, 4);
    printf ("strcmp: %d %s %d %s\n", 4, x, r, y);
    r = strncmp (x, y, 2);
    printf ("strcmp: %d %s %d %s\n", 2, x, r, x);
    r = strncmp (y, x, 4);
    printf ("strcmp: %d %s %d %s\n", 4, y, r, x);
    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

strncmp: 4 CIao 1 CIAO
strncmp: 2 CIao 0 CIao
strncmp: 4 CIAO -1 CIao

602.3.5   Funzione «strxfrm()» (string transform)

La funzione strxfrm() trasforma la stringa org sovrascrivendo la stringa dst in modo relativo alla configurazione locale. In pratica, la stringa trasformata che si ottiene può essere comparata con un'altra stringa trasformata nello stesso modo attraverso la funzione strcmp() ottenendo lo stesso esito che si avrebbe confrontando le stringhe originali con la funzione strcoll().

Nella stringa di destinazione vengono messi non più di n caratteri, incluso il carattere nullo di terminazione. Se n è pari a zero, dst può essere un puntatore nullo. Le due stringhe non devono sovrapporsi.

La funzione strxfrm() restituisce la quantità di caratteri necessari a contenere la stringa org trasformata, senza però contare il carattere nullo di terminazione. Se n è zero e dst corrisponde al puntatore nullo, restituisce il valore che sarebbe necessario per trasformare la stringa org in tutta la sua lunghezza.

L'esempio seguente di tale funzione è valido solo per la configurazione locale C:

#include <string.h>
size_t
strxfrm (char *restrict dst, const char *restrict org, size_t n)
{
    size_t i;
    if (n == 0 && dst == NULL)
      {
        return strlen (org);
      }
    else
      {
        for (i = 0; i < n ; i++)
          {
            dst[i] = org[i];
            if (org[i] == 0)
              {
                break;
              }
          }
        return i;
      }
}

602.4   Ricerca

Seguono i prototipi delle funzioni utili per la ricerca all'interno di sequenze di byte:

void  *memchr  (const void *s, int c, size_t n);
char  *strchr  (const char *s, int c);
char  *strrchr (const char *s, int c);
size_t strspn  (const char *s, const char *accept);
size_t strcspn (const char *s, const char *reject);
char  *strpbrk (const char *s, const char *accept);
char  *strstr  (const char *string, const char *substring);
char  *strtok  (char *restrict string, const char *restrict delim);

602.4.1   Funzione «memchr()» (memory character)

La funzione memchr() cerca un carattere a partire da una certa posizione in memoria, scandendo al massimo una quantità determinata di caratteri, restituendo il puntatore al carattere trovato. Se nell'ambito specificato non trova il carattere, restituisce il puntatore nullo.

#include <string.h>
void
*memchr (const void *s, int c, size_t n)
{
    unsigned char *a = (unsigned char *) s;
    unsigned char x  = (unsigned char) c;
    size_t i;
    for (i = 0; n > 0 && i < n; i++)
      {
        if (a[i] == x)
          {
            return (void *) (s + i);
          }
      }
    return NULL;
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente, in cui si scandisce il contenuto di una variabile di tipo int, intendendo che questa debba occupare uno spazio di 32 bit:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    int x = 0x13579BDF;
    void *p;
    p = memchr (&x, 0xDF, 4);
    printf ("contenuto della variabile: %x\n", x);
    printf ("indirizzo iniziale della variabile: 0x%x\n",
            (unsigned int) &x);
    printf ("indirizzo di 0x%x all'interno della variabile: 0x%x\n",
            0xDF,
            (unsigned int) p);
    return 0;
}

Avviando questo programma in un'architettura che inverte l'ordine dei byte (little endian) si deve ottenere un risultato simile a quello seguente:

contenuto della variabile: 13579bdf
indirizzo iniziale della variabile: 0xbff7f3bc
indirizzo di 0xdf all'interno della variabile: 0xbff7f3bc

602.4.2   Funzione «strchr()» (string character)

La funzione strchr() cerca un carattere all'interno di una stringa, restituendo il puntatore al carattere trovato, oppure il puntatore nullo se la ricerca fallisce. Nella scansione viene preso in considerazione anche il carattere nullo di terminazione della stringa.

#include <string.h>
char
*strchr (const char *s, int c)
{
    unsigned char *a = (unsigned char *) s;
    unsigned char x  = (unsigned char) c;
    size_t i;
    for (i = 0; ; i++)
      {
        if (a[i] == x)
          {
            return (char *) (s + i);
          }
        else if (a[i] == 0)
          {
            return NULL;
          }
      }
}

Per verificare sommariamente il comportamento della funzione si può realizzare un programma molto semplice come quello seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char *x = "ciao amore mio";
    char *p;

    p = strchr (x, 'a');
    printf ("La stringa \"%s\", collocata a partire ", x);
    printf ("dall'indirizzo %u, contiene il carattere '%c' ",
            (unsigned int) x,  'a');
    printf ("all'indirizzo %u.\n", (unsigned int) p);

    p = strchr (x, 0);
    printf ("La stringa \"%s\", collocata a partire ", x);
    printf ("dall'indirizzo %u, contiene il carattere 0x%x ",
            (unsigned int) x, 0);
    printf ("all'indirizzo %u.\n", (unsigned int) p);

    return 0;
}

Avviando questo programma si deve ottenere un risultato simile a quello seguente:

La stringa "ciao amore mio", collocata a partire dall'indirizzo \
  \134516936, contiene il carattere 'a' all'indirizzo 134516938. La stringa "ciao amore mio", collocata a partire dall'indirizzo \
  \134516936, contiene il carattere 0x0 all'indirizzo 134516950.

602.4.3   Funzione «strrchr()» (string character)

La funzione strrchr() cerca un carattere all'interno di una stringa, restituendo il puntatore all'ultimo carattere corrispondente trovato, oppure il puntatore nullo se la ricerca fallisce. Nella scansione viene preso in considerazione anche il carattere nullo di terminazione della stringa.

#include <string.h>
char
*strrchr (const char *s, int c)
{
    unsigned char *a = (unsigned char *) s;
    unsigned char x  = (unsigned char) c;
    size_t i;
    size_t last = 0;
    for (i = 0; a[i] != 0 ; i++)
      {
        if (a[i] == x)
          {
            last = i;
          }
      }
    if (last > 0)
      {
        return (char *) (s + last);
      }
    else
      {
        return NULL;
      }
}

Per verificare sommariamente il comportamento della funzione si può modificare leggermente l'esempio già apparso a proposito della funzione strchr():

...
    p = strrchr (x, 'a');
...
    p = strrchr (x, 0);
...

Avviando questo programma si deve ottenere un risultato simile a quello seguente:

La stringa "ciao amore mio", collocata a partire dall'indirizzo \
  \134514088, contiene il carattere 'a' all'indirizzo 134514093. La stringa "ciao amore mio", collocata a partire dall'indirizzo \
  \134514088, contiene il carattere 0x0 all'indirizzo 134514102.

602.4.4   Funzione «strspn()» (string span)

La funzione strspn() calcola la lunghezza massima iniziale della stringa s, composta esclusivamente da caratteri contenuti nella stringa accept, restituendo tale valore.

#include <string.h>
size_t
strspn (const char *s, const char *accept)
{
    size_t i;
    size_t j;
    int found;
    for (i = 0; s[i] != 0; i++)
      {
        for (j = 0, found = 0; accept[j] != 0; j++)
          {
            if (s[i] == accept[j])
              {
                found = 1;
                break;
              }
          }
        if (!found)
          {
            break;
          }
      }
    return i;
}

Per verificare sommariamente il comportamento della funzione si può utilizzare l'esempio seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char *x = "ciao amore mio";
    char *y = "abcdefghi";
    size_t n;

    n = strspn (x, y);
    printf ("La parte iniziale di \"%s\" ", x);
    printf ("che contiene i caratteri \"%s\" ", y);
    printf ("si compone di %d caratteri.\n", n);

    n = strspn (x, x);
    printf ("La parte iniziale di \"%s\" ", x);
    printf ("che contiene i caratteri \"%s\" ", x);
    printf ("si compone di %d caratteri.\n", n);

    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

La parte iniziale di "ciao amore mio" che contiene i caratteri \
  \"abcdefghi" si compone di 3 caratteri. La parte iniziale di "ciao amore mio" che contiene i caratteri \
  \"ciao amore mio" si compone di 14 caratteri.

602.4.5   Funzione «strcspn()»

La funzione strcspn() si comporta in modo analogo a strspn(), con la differenza che l'insieme di caratteri contenuto nella stringa reject non deve costituire l'insieme iniziale della stringa s che si va a contare. Pertanto, il valore restituito è la quantità di caratteri iniziali della stringa s che non si trovano anche nell'insieme reject.

#include <string.h>
size_t
strcspn (const char *s, const char *reject)
{
    size_t i;
    size_t j;
    int found;
    for (i = 0; s[i] != 0; i++)
      {
        for (j = 0, found = 0; reject[j] != 0 || found; j++)
          {
            if (s[i] == reject[j])
              {
                found = 1;
                break;
              }
          }
        if (found)
          {
            break;
          }
      }
    return i;
}

Per verificare sommariamente il comportamento della funzione si può utilizzare l'esempio seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char *x = "ciao amore mio";
    char *y = "mnopqrstuvwxyz";
    size_t n;

    n = strcspn (x, y);
    printf ("La parte iniziale di \"%s\" ", x);
    printf ("che non contiene i caratteri \"%s\" ", y);
    printf ("si compone di %d caratteri.\n", n);

    n = strcspn (x, x);
    printf ("La parte iniziale di \"%s\" ", x);
    printf ("che non contiene i caratteri \"%s\" ", x);
    printf ("si compone di %d caratteri.\n", n);

    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

La parte iniziale di "ciao amore mio" che non contiene i caratteri \
  \"mnopqrstuvwxyz" si compone di 3 caratteri. La parte iniziale di "ciao amore mio" che non contiene i caratteri \
  \"ciao amore mio" si compone di 0 caratteri.

602.4.6   Funzione «strpbrk()» (string point break)

La funzione strpbrk() scandisce la stringa s alla ricerca del primo carattere che risulti contenuto nella stringa accept, restituendo il puntatore al carattere trovato, oppure, in mancanza di alcuna corrispondenza, il puntatore nullo.

#include <string.h>
char
*strpbrk (const char *s, const char *accept)
{
    size_t i;
    size_t j;
    for (i = 0; s[i] != 0; i++)
      {
        for (j = 0; accept[j] != 0; j++)
          {
            if (s[i] == accept[j])
              {
                return (char *) (s + i);
              }
          }
      }
    return NULL;
}

Per verificare sommariamente il comportamento della funzione si può utilizzare l'esempio seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char *x = "ciao amore mio";
    char *y = "mnopqrstuvwxyz";
    char *p;

    p = strpbrk (x, y);
    printf ("La stringa \"%s\" che inizia all'indirizzo %u, ", x,
            (unsigned int) x);
    printf ("trova la prima corrispondenza con la stringa \"%s\" ", y);
    printf ("all'indirizzo %u.\n", (unsigned int) p);

    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

La stringa "ciao amore mio" che inizia all'indirizzo 134516840, \
  \trova la prima corrispondenza con la stringa "mnopqrstuvwxyz" \
  \all'indirizzo 134516843.

602.4.7   Funzione «strstr()»

La funzione strstr() cerca la stringa substring nella stringa string restituendo il puntatore alla prima corrispondenza trovata (nella stringa string). Se la corrispondenza non c'è, la funzione restituisce il puntatore nullo.

#include <string.h>
char
*strstr (const char *string, const char *substring)
{
    size_t i;
    size_t j;
    size_t k;
    int found;
    if (substring[0] == 0)
      {
        return (char *) string;
      }
    for (i = 0, j = 0, found = 0; string[i] != 0; i++)
      {
        if (string[i] == substring[0])
          {
            for (k = i, j = 0;
                 string[k] == substring[j] && string[k] != 0 && substring[j] != 0;
                 j++, k++)
              {
                ;
              }
            if (substring[j] == 0)
              {
                found = 1;
              } 
          }
        if (found)
          {
            return (char *) (string + i);
          }
      }
    return NULL;
}

Per verificare sommariamente il comportamento della funzione si può utilizzare l'esempio seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char *x = "ciao amore mio";
    char *y = "amore";
    char *p;

    p = strstr (x, y);
    printf ("La stringa \"%s\" che inizia all'indirizzo %u, ", x,
            (unsigned int) x);
    printf ("contiene la stringa \"%s\" ", y);
    printf ("all'indirizzo %u.\n", (unsigned int) p);

    p = strstr (x, "");
    printf ("La stringa \"%s\" che inizia all'indirizzo %u, ", x,
            (unsigned int) x);
    printf ("contiene la stringa \"%s\" ", "");
    printf ("all'indirizzo %u.\n", (unsigned int) p);

    p = strstr (x, "baba");
    printf ("La stringa \"%s\" che inizia all'indirizzo %u, ", x,
            (unsigned int) x);
    printf ("contiene la stringa \"%s\" ", "baba");
    printf ("all'indirizzo %u.\n", (unsigned int) p);

    return 0;
}

Avviando questo programma si deve ottenere un risultato come quello seguente:

La stringa "ciao amore mio" che inizia all'indirizzo 134517000, \
  \contiene la stringa "amore" all'indirizzo 134517005. La stringa "ciao amore mio" che inizia all'indirizzo 134517000, \
  \contiene la stringa "" all'indirizzo 134517000. La stringa "ciao amore mio" che inizia all'indirizzo 134517000, \
  \contiene la stringa "baba" all'indirizzo 0.

602.4.8   Funzione «strtoc()» (string token)

La funzione strtoc() serve a suddividere una stringa in unità, definite token, specificando un elenco di caratteri da intendere come delimitatori, in una seconda stringa. La funzione va usata in fasi successive, fornendo solo inizialmente la stringa da suddividere che continua poi a essere utilizzata se al suo posto viene fornito il puntatore nullo. La funzione restituisce, di volta in volta, il puntatore alla sottostringa contenente l'unità individuata, oppure il puntatore nullo, se non può trovarla.

La funzione deve tenere memoria di un puntatore in un'area di memoria persistente (quello che nei commenti viene definito «puntatore statico») e deve isolare le unità modificando la stringa originale, inserendo il carattere nullo di terminazione alla fine delle unità individuate.

Quando la funzione viene chiamata indicando al posto della stringa da scandire il puntatore nullo, l'insieme dei delimitatori può essere diverso da quello usato nelle fasi precedenti.

#include <string.h>
char
*strtok (char *restrict string, const char *restrict delim)
{
    static char *next = NULL;
    size_t i = 0;
    size_t j;
    int found_token;
    int found_delim;
    //
    // Se la stringa fornita come argomento è un puntatore nullo,
    // occorre avvalersi del puntatore statico. Se però questo
    // è nullo a sua volta, la scansione non può avvenire.
    //
    if (string == NULL)
      {
        if (next == NULL)
          {
            return NULL;
          }
        else
          {
            string = next;
          }
      }
    //
    // Se la stringa fornita come argomento è vuota, la
    // scansione non può avvenire.
    //
    if (string[0] == 0)
      {
        next = NULL;
        return NULL;
      }
    else
      {
        if (delim[0] == 0)
          {
            return string;
          }
      }
    //
    // Trova la prossima unità (token).
    //
    for (i = 0, found_token = 0, j = 0; string[i] != 0 && (!found_token); i++)
      {
        //
        // Cerca tra i delimitatori.
        //
        for (j = 0, found_delim = 0; delim[j] != 0; j++)
          {
            if (string[i] == delim[j])
              {
                found_delim = 1;
              }
          }
        //
        // Se il carattere attuale della stringa non è
        // un delimitatore, si tratta dell'inizio di una
        // nuova unità (token).
        //
        if (!found_delim)
          {
            found_token = 1;
            break;
          }
      }
    //
    // Se è stata trovata una unità (token) viene aggiustato
    // il puntatore che rappresenta la stringa. Se invece
    // non è stata trovata l'unità, vuol dire che non ce ne
    // possono essere altre.
    //
    if (found_token)
      {
        string += i;
      }
    else
      {
        next = NULL;
        return NULL;
      }
    //
    // Cerca la fine dell'unità trovata.
    //
    for (i = 0, found_delim = 0; string[i] != 0; i++)
      {
        for (j = 0; delim[j] != 0; j++)
          {
            if (string[i] == delim[j])
              {
                found_delim = 1;
                break;
              }
          }
        if (found_delim)
          {
            break;
          }
      }
    //
    // Se è stato trovato un delimitatore, allora il carattere
    // corrispondente nella stringa deve essere azzerato.
    // Se invece la stringa originale è terminata per conto proprio,
    // allora non è possibile continuare la ricerca in una fase
    // successiva, perché non ci possono essere altre unità.
    //
    if (found_delim)
      {
        string[i] = 0;
        next = &string[i+1];
      }
    else
      {
        next = NULL;
      }
    //
    // A questo punto, la stringa attuale rappresenta
    // l'unità trovata.
    //
    return string;
}

Per comprendere lo scopo della funzione viene utilizzato lo stesso esempio che appare nel documento ISO/IEC 9899:TC2, al paragrafo 7.21.5.7, con qualche piccola modifica per poterlo rendere un programma autonomo:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    char str[] = "?a???b,,,#c";
    char *t;

    t = strtok (str, "?");              // t punta all'unità "a"
    printf ("strtok: \"%s\"\n", t);
    t = strtok (NULL, ",");             // t punta all'unità "??b"
    printf ("strtok: \"%s\"\n", t);
    t = strtok (NULL, "#,");            // t punta all'unità "c"
    printf ("strtok: \"%s\"\n", t);
    t = strtok (NULL, "?");             // t è un puntatore nullo
    printf ("strtok: \"%s\"\n", t);

    return 0;
}

Avviando il programma si ottiene quanto già descritto dai commenti inseriti nel codice:

strtok: "a"
strtok: "??b"
strtok: "c"
strtok: "(null)"

Ciò che avviene nell'esempio può essere schematizzato dalle figure successive. Inizialmente la stringa str ha in memoria l'aspetto seguente:

?a???b,,,#c

Dopo la prima chiamata della funzione strtok() la stringa risulta alterata e il puntatore ottenuto raggiunge la lettera a:

?a???b,,,#c

Dopo la seconda chiamata della funzione, in cui si usa il puntatore nullo per richiedere una scansione ulteriore della stringa originale, si ottiene un nuovo puntatore che, questa volta, inizia a partire dal quarto carattere, rispetto alla stringa originale, dal momento che il terzo è già stato sovrascritto da un carattere nullo:

?a???b,,,#c

La penultima chiamata della funzione strtok() raggiunge la lettera c che è anche alla fine della stringa originale:

?a???b,,,#c

L'ultimo tentativo di chiamata della funzione non può dare alcun esito, perché la stringa originale si è già conclusa.

Va tenuto in considerazione che la funzione strtok(), dovendo mantenere in memoria la posizione trovata dell'ultima scansione eseguita, da una chiamata a quella successiva, non è «rientrante», pertanto non si presta per i programmi che si suddividono in più thread.

602.5   Funzioni varie

Seguono i prototipi delle funzioni descritte nelle sezioni successive:

void  *memset (void *s, int c, size_t n);
char  *strerror (int errnum);
size_t strlen  (const char *s);

602.5.1   Funzione «memset()» (memory set)

La funzione memset() consente di inizializzare una certa area di memoria con la ripetizione di un certo carattere. Per la precisione, viene usato il valore del parametro c, tradotto in un carattere senza segno, copiandolo per n volte a partire dall'indirizzo a cui punta s. La funzione restituisce s.

#include <string.h>
void
*memset (void *s, int c, size_t n)
{
    unsigned char *a = (unsigned char *) s;
    unsigned char x  = (unsigned char) c;
    size_t i;
    for (i = 0; n > 0 && i < n; i++)
      {
        a[i] = x;
      }
    return s;
}

Per verificare sommariamente il comportamento della funzione si può utilizzare l'esempio seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    int x = 0x12345678;
    printf ("prima: 0x%x\n", x);
    memset (&x, 0xFF, 2);
    printf ("dopo: 0x%x\n", x);

    char X[] = "ciao amore mio";
    printf ("prima: \"%s\"\n", X);
    memset (X, 'Q', 5);
    printf ("dopo: \"%s\"\n", X);

    return 0;
}

Avviando questo programma in un elaboratore con architettura a 32 bit e inversione dei byte (little endian) si deve ottenere il risultato seguente:

prima: 0x12345678
dopo: 0x1234ffff
prima: "ciao amore mio"
dopo: "QQQQQamore mio"

602.5.2   Funzione «strerror()» (string error)

La funzione strerror() serve a tradurre il numero fornito come argomento in un puntatore da cui inizia una stringa contenente una spiegazione. In altri termini, serve a trasformare un numero in una descrizione di un tipo di errore. Temporaneamente viene mostrata una soluzione priva di utilità, anche se risponde alle richieste delle specifiche:

#include <string.h>
char
*strerror (int errnum)
{
    static char answare[] = "Unknown error";
    return answare;
}

L'esempio successivo può servire a dimostrare il senso di questa funzione:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    printf ("%s\n", strerror (0));
    printf ("%s\n", strerror (1));
    printf ("%s\n", strerror (2));
    printf ("%s\n", strerror (3));
    printf ("%s\n", strerror (4));
    return 0;
}

Utilizzando questo programma compilato con le librerie di un sistema GNU si potrebbero vedere i messaggi seguenti:

Success
Operation not permitted
No such file or directory
No such process
Interrupted system call

La stringa a cui punta la funzione può essere condivisa da altre chiamate successive della stessa, pertanto, in un programma con thread multipli, è possibile che avvenga la sovrascrittura, a meno di disporre di un elenco separato di tutti i tipi di messaggio di errore.

602.5.3   Funzione «strlen()» (string length)

La funzione strlen() calcola la lunghezza di una stringa, escludendo dal conteggio il carattere nullo di terminazione:

#include <string.h>
size_t
strlen (const char *s)
{
    size_t i;
    for (i = 0; s[i] != 0 ; i++)
      {
        ; // Esegue solo il conteggio.
      }
    return i;
}

Per verificare sommariamente il comportamento della funzione si può utilizzare l'esempio seguente:

#include <stdio.h>
#include <string.h>
int
main (void)
{
    size_t lunghezza;
    char stringa[] = "ciao amore";
    lunghezza = strlen (stringa);
    printf ("la frase \"%s\" si compone di %d caratteri\n",
            stringa,
            lunghezza);
    return 0;
}

Avviando il programma si deve vedere il risultato seguente:

la frase "ciao amore" si compone di 10 caratteri

602.6   Riferimenti


Appunti di informatica libera 2008 --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome c_171_string_h_187.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home]

Valid ISO-HTML!

CSS validator!

Gjlg Metamotore e Web Directory