Essayer de coder ← Retour aux sujets

Une chaîne est un tableau de char

char[]

En C, il n'existe pas de type « chaîne ». Une chaîne est un tableau de char terminé par le caractère nul '\0'.

char mot[] = "NSI";
4 cases : 'N', 'S', 'I' et '\0'
char nom[20];
Place pour 19 caractères et le '\0'
printf("%s", mot);
Affiche jusqu'au '\0'
mot[0]
Premier caractère ('N')
#include <string.h>
strlen, strcpy, strcat, strcmp…
premier.c
#include <stdio.h>

int main(void) {
    char mot[] = "NSI";

    printf("%s\n", mot);
    printf("%c\n", mot[1]);
    printf("%d\n", mot[3] == '\0');
    return 0;
}
Affichage
NSI
S
1

Les outils de string.h

string.h

Ces fonctions cherchent le '\0' pour savoir où s'arrête le texte. Elles ne vérifient jamais la taille du tableau de destination.

strlen(s)
Longueur, sans compter le '\0'
strcpy(dest, src)
Copie src dans dest
strcat(dest, src)
Colle src à la fin de dest
strcmp(a, b)
0 si égales ; négatif si a précède b ; positif sinon
strchr(s, 'x')
Adresse de la première occurrence de 'x', ou NULL
snprintf(buf, taille, "%d", n)
Écrit dans une chaîne sans dépasser taille
outils.c
#include <stdio.h>
#include <string.h>

int main(void) {
    char a[20] = "Bonjour";
    char b[] = "NSI";

    strcat(a, " ");
    strcat(a, b);
    printf("%s (%d lettres)\n", a, (int) strlen(a));
    printf("%d\n", strcmp("abc", "abd") < 0);
    return 0;
}
Affichage
Bonjour NSI (11 lettres)
1

✂️ Le cours : le texte en C

En C, une « chaîne de caractères » est un simple tableau de char dont la fin est marquée par le caractère nul '\0' (de code 0). Toutes les fonctions de <string.h> cherchent ce '\0' pour savoir où le texte s'arrête. C'est simple et très rapide, mais fragile : si le '\0' manque, elles continuent à lire la mémoire bien au-delà de la chaîne.

Représentation en mémoire

char mot[] = "NSI";

indice :      0       1       2       3
           +-------+-------+-------+-------+
           |  'N'  |  'S'  |  'I'  | '\0'  |
           +-------+-------+-------+-------+
code ASCII :  78      83      73      0

La taille du tableau doit prévoir la place du '\0' : "NSI" occupe 4 cases. Chaque lettre est un char, c'est-à-dire un petit entier : 'A' vaut 65, 'a' vaut 97, '0' vaut 48.

Parcourir une chaîne

On boucle jusqu'à rencontrer le '\0'. Pas besoin de connaître la longueur à l'avance.

voyelles.c
#include <stdio.h>

int main(void) {
    char texte[] = "programmation";
    int voyelles = 0;

    for (int i = 0; texte[i] != '\0'; i++) {
        char c = texte[i];
        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
            voyelles++;
        }
    }
    printf("%d voyelles\n", voyelles);
    return 0;
}
Affichage
5 voyelles

Modifier une chaîne : tableau ou littéral ?

Attention à la différence entre deux écritures qui se ressemblent. char s[] = "NSI"; crée un tableau modifiable qui contient une copie du texte. char *s = "NSI"; crée un pointeur vers un littéral en lecture seule : le modifier est un comportement indéfini (plantage le plus souvent).

À éviter
faux.c
char *s = "NSI";
s[0] = 'n';        /* littéral en lecture seule : plantage */
Correct
correct.c
char s[] = "NSI";
s[0] = 'n';        /* copie modifiable : s vaut "nSI" */

Passer en majuscules avec ctype.h

<ctype.h> fournit toupper, tolower, isdigit, isalpha, isspace… qui travaillent caractère par caractère. Le cast (unsigned char) évite un comportement indéfini avec les caractères négatifs.

majuscules.c
#include <stdio.h>
#include <ctype.h>

int main(void) {
    char s[] = "nsi 2026";

    for (int i = 0; s[i] != '\0'; i++) {
        s[i] = toupper((unsigned char) s[i]);
    }
    printf("%s\n", s);
    return 0;
}
Affichage
NSI 2026

Lire une chaîne au clavier

scanf("%s", mot) s'arrête au premier espace et ne limite pas la longueur lue : un texte trop long écrase la mémoire voisine. Préfère fgets(tableau, taille, stdin), qui lit une ligne entière (espaces compris) sans jamais dépasser la taille donnée. Elle conserve le retour à la ligne final, qu'on remplace par '\0'.

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

int main(void) {
    char nom[30];

    printf("Ton nom ? ");
    fgets(nom, sizeof nom, stdin);
    nom[strcspn(nom, "\n")] = '\0';   /* retire le retour à la ligne */
    printf("Bonjour %s !\n", nom);
    return 0;
}
Si tu tapes Lina Martin
Ton nom ? Lina Martin
Bonjour Lina Martin !

Construire une chaîne avec snprintf

snprintf fonctionne comme printf, mais écrit dans un tableau, en s'arrêtant avant de le dépasser. C'est la façon sûre d'assembler du texte et des nombres.

etiquette.c
#include <stdio.h>

int main(void) {
    char etiquette[32];
    int note = 15, sur = 20;

    snprintf(etiquette, sizeof etiquette, "Note : %d/%d", note, sur);
    printf("%s\n", etiquette);
    return 0;
}
Affichage
Note : 15/20

Convertir une chaîne en nombre

atoi (entier) et atof (réel) de <stdlib.h> convertissent un texte en nombre. Elles ne signalent pas les erreurs : sur "abc", atoi renvoie simplement 0. Pour un contrôle strict, regarde strtol.

convertir.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int n = atoi("42") + 1;
    double x = atof("3.5") * 2;

    printf("%d %.1f\n", n, x);
    return 0;
}
Affichage
43 7.0

⚠️ Erreurs fréquentes

Comparer deux chaînes avec ==

À éviter
faux.c
if (mdp == "secret") {        /* compare des adresses */
    printf("ok\n");
}
Correct
correct.c
if (strcmp(mdp, "secret") == 0) {   /* compare le texte */
    printf("ok\n");
}

== compare l'adresse des deux tableaux, jamais leur contenu. strcmp renvoie 0 quand les deux textes sont identiques.

Oublier la place du caractère nul

À éviter
faux.c
char mot[3] = "NSI";   /* pas de place pour '\0' */
Correct
correct.c
char mot[4] = "NSI";   /* ou simplement char mot[] = "NSI"; */

Sans le '\0', printf("%s", mot) continue d'afficher la mémoire qui suit, jusqu'à tomber sur un 0 par hasard.

Déborder du tableau de destination

À éviter
faux.c
char petit[8];
strcpy(petit, "une phrase bien trop longue");   /* écrase la mémoire voisine */
Correct
correct.c
char petit[8];
snprintf(petit, sizeof petit, "%s", "une phrase bien trop longue");   /* tronqué à 7 caractères */

strcpy et strcat ne vérifient rien : c'est la source des célèbres failles de sécurité par *dépassement de tampon* (buffer overflow). Calcule toujours la place nécessaire, ou utilise snprintf.

Lire avec scanf("%s") sans limite

Pour un tableau char nom[30], écris au minimum scanf("%29s", nom) : la limite (29) laisse la place du '\0'. Mais fgets reste le choix le plus sûr, et le seul qui accepte les espaces.

Compter les lettres avec strlen quand il y a des accents

strlen compte des octets, pas des lettres. En UTF-8, é occupe 2 octets : strlen("été") vaut 5. Les accents posent aussi des problèmes d'affichage selon le terminal ; dans les exercices, on les évite.

📋 Aide-mémoire

  • Chaîne = tableau de char terminé par '\0' : "NSI" occupe 4 cases.
  • Parcours : for (int i = 0; s[i] != '\0'; i++).
  • <string.h> : strlen, strcpy, strcat, strcmp (0 = égales), strchr ; ne vérifient jamais la taille de la destination.
  • Comparer : strcmp(a, b) == 0, jamais a == b. Copier : strcpy / snprintf, jamais a = b.
  • Saisie : fgets(buf, sizeof buf, stdin) puis retirer le '\n' ; éviter scanf("%s") sans limite.
  • char s[] = "…" est modifiable ; char *s = "…" pointe vers un littéral en lecture seule.