Informasjon

Frist Ingen frist
Innleveringsgrense Ingen begrensning

Merkelapper

Logg inn

[8.1] Rappel des concepts [Obligatoire]

Les chaines de caractères

Une chaine de caractères (ou string en anglais) est le terme que l'on utilise pour parler d'un tableau de caractères qui se termine par le caractère nul '\0'.

Quand l'on veut déclarer du texte, il ne serait pas très pratique de devoir créer un tableau contenant chaque caractère un par un. C'est pour cela qu'il existe un sucre syntaxique en C pour faciliter la déclaration des chaines de caractères et vous l'avez en réalité déjà utilisé sans le savoir ! Ce sucre syntaxique consiste à entourer le texte que vous voulez utiliser avec des guillemets doubles "", comme dans la chaine de caractères "Hello World!" par exemple. Comme vous pouvez le voir, vous avez déjà utilisé cette notation lors de vos appels aux fonctions printf ou scanf.

Pour déclarer une chaine de caractères, vous devez donc déclarer un tableau de caractères mais vous pouvez utiliser le sucre syntaxique pour initialiser ce tableau :

  • Déclaration d'une chaine de caractères :

    char hello[6] = "Hello";  // équivalent à {'H', 'e', 'l', 'l', 'o', '\0'} donc de taille 6
    
  • Déclaration simplifiée d'une chaine de caractères :

    char coucou[] = "Coucou";  // la taille est déduite automatiquement comme pour les tableaux classiques (7 dans ce cas)
    
  • Déclaration d'une chaine de caractères dans un tableau plus grand que nécessaire :

    char salut[10] = "Salut";  // le reste du tableau est initialisé à '\0' automatiquement
    

    Cela peut être utile si vous prévoyez d'ajouter des caractères à la chaine de caractères plus tard.

  • Allocation dynamique d'une chaine de caractères de taille x :

    char *message = (char *)malloc((x + 1) * sizeof(char));
    

    Le + 1 est nécessaire pour prendre en compte le caractère nul '\0' à la fin de la chaine de caractères. Il faut faire attention à bien libérer la mémoire allouée avec free(message); lorsque vous n'en avez plus besoin comme pour les autres tableaux dynamiques. Il est important de noter que dans ce cas, le tableau n'est pas initialisé donc il ne contient pas de '\0' à la fin tant que vous ne l'avez pas fait vous-même.

Itération sur les chaines de caractères

Quand l'on veut manipuler une chaine de caractères, on a besoin de la parcourir comme on le ferait avec un tableau classique. Cependant, avec un tableau classique, on avait à chaque fois besoin de stocker la taille du tableau dans une variable à part pour être sûr de ne pas dépasser les limites du tableau lors de l'itération. Avec une chaine de caractères, on peut se passer de cette variable contenant la taille du tableau car le caractère nul '\0' à la fin de la chaine de caractères nous indique où nous arrêter.

Voici un exemple d'itération sur une chaine de caractères pour afficher chaque caractère un par un :

Comme vous pouvez le voir, au lieu d'utiliser une condition basée sur une variable contenant la taille du tableau comme i < taille, on utilise la condition string[i] != '\0' pour s'arrêter dès que l'on rencontre le caractère nul '\0' à la fin de la chaine de caractères.

Fonctions prédéfinies pour les chaines de caractères

Il existe plusieurs fonctions qui sont disponibles dans la bibliothèque standard du C pour manipuler les chaines de caractères.

Dans le module stdio

  • printf : Affiche une chaine de caractères formatée à l'écran.

    #include <stdio.h>
    
    printf("Hello World!\n");  // Affiche "Hello World!" suivi d'un saut de ligne
    
  • scanf : Lit le premier mot d'une ligne (la première chaine de caractères sans espaces) depuis l'entrée standard.

    #include <stdio.h>
    
    char string[50];
    scanf("%s", string);  // Lit une chaine de caractères
    
    #include <stdio.h>
    
    char string[50];
    scanf("%49s", string);  // Lit une chaine de caractères (max 49 caractères + '\0')
    
    #include <stdio.h>
    
    char *string;
    scanf("%ms", &string);  // Lit une chaine de caractères allouée dynamiquement (pensez à free(string) quand string n'est plus nécessaire)
    

    Dans ce dernier exemple, il faut bien utiliser un & avant le nom de la variable car scanf va modifier l'adresse stockée dans string pour qu'elle pointe vers la mémoire allouée dynamiquement.

  • fgets : Lit au maximum n-1 caractères d'une ligne depuis un flux d'entrée (comme l'entrée standard).

    #include <stdio.h>
    
    char string[50];
    fgets(string, 50, stdin);  // Lit une ligne de texte (max 49 caractères + '\0')
    

    Contrairement à scanf, fgets lit toute la ligne jusqu'au saut de ligne ou jusqu'à atteindre la limite de caractères spécifiée, ce qui permet de lire des chaines de caractères contenant des espaces.

Dans le module string

  • strlen : Calcule la longueur d'une chaine de caractères (sans compter le caractère nul '\0').

    #include <string.h>
    
    char string[] = "Hello";
    int length = strlen(string);  // length vaut 5
    
  • strcmp : Compare deux chaines de caractères.

    #include <string.h>
    
    char str1[] = "Hello";
    char str2[] = "World";
    int result = strcmp(str1, str2);  // result < 0 car "Hello" est lexicographiquement inférieur à "World"`
    
  • strncmp : Compare les n premiers caractères de deux chaines de caractères.

    #include <string.h>
    
    char str1[] = "Hello";
    char str2[] = "Helium";
    int result = strncmp(str1, str2, 3);  // result == 0 car les 3 premiers caractères sont identiques
    
  • strcpy : Copie une chaine de caractères dans une autre.

    #include <string.h>
    
    char source[] = "Hello";
    char destination[6];
    strcpy(destination, source);  // destination contient maintenant "Hello" (avec le '\0')
    
  • strncpy : Copie les n premiers caractères d'une chaine de caractères dans une autre.

    #include <string.h>
    
    char source[] = "Hello";
    char destination[4];
    strncpy(destination, source, 3);  // destination contient maintenant "Hel" (pas de '\0' ajouté automatiquement)
    
    #include <string.h>
    
    char source[] = "Hello";
    char destination[10];
    strncpy(destination, source, 10);  // destination contient maintenant "Hello" (avec le '\0') mais la fin du tableau n'est pas utilisée
    

Spørsmål 1: Tableau char

Est-ce qu'une chaine de caractères est en réalité un tableau de caractères ?

Spørsmål 2: Chaine de caractères

Est-ce que "Victor !" est une chaine de caractères ?

Spørsmål 3: Caractère spécial

Quel est le caractère spécial qui marque la fin d'une chaine de caractères ? (N'oubliez pas les guillemets simples, c'est un caractère !)

Spørsmål 4: Référence (partie 1)
char chaine[] = "Bonjour";

Dans l'instruction ci-dessus, la variable chaine contient ...

Spørsmål 5: Référence (partie 2)
char* mot = "Bonjour";

Est-ce que l'instruction ci-dessus est correcte ?

Spørsmål 6: scanf
char* mot;
scanf("%ms", &mot);

Est-ce que les deux instructions ci-dessus permettent de lire une chaine de caractères entrée par l'utilisateur et de stocker sa référence dans la variable mot ?

Spørsmål 7: Premier code (partie 1)
#include <stdio.h>

int f(char l, char* str) {
    int i = 0;
    int nb = 0;
    while (str[i] != '\0') {
        if (str[i] == l) {
            nb++;
        }
        i++;
    }
    return nb;
}

int main(void) {
    printf("%i\n", f('!', "coucou !"));
    printf("%i\n", f('u', "coucou !"));
    return 0;
}

Observez le programme ci-dessus mais ne l'exécutez pas. Il devrait afficher deux nombres, quel est le premier ?

Spørsmål 8: Premier code (partie 2)

Dans le programme de l'exercice précédent, quel est le second nombre qui est affiché ?

Spørsmål 9: Second code
#include <stdio.h>

int g(char* str1, char* str2) {
    int i = 0;
    int nb = 0;
    while (str1[i] != '\0') {
        int j = 0;
        while (str2[j] != '\0') {
            if (str1[i] == str2[j]) {
                nb++;
            }
            j++;
        }
        i++;
    }
    return nb;
}

int main(void) {
    printf("%i\n", g("aei","Salut toi !"));

    return 0;
}

Observez le programme ci-dessus mais ne l'exécutez pas. Qu'affiche ce programme ?