Tableaux et chaînes de caractères en C

Découvre comment C stocke plusieurs valeurs dans un tableau et représente le texte par des caractères terminés par un octet nul. Parcours des tableaux à une ou plusieurs dimensions avec des boucles, passe-les à des fonctions, traite des chaînes avec tes propres boucles et avec les fonctions standard, découvre comment le texte UTF-8 est stocké sous forme d’octets et lis les arguments qu’un programme reçoit en ligne de commande. Tout au long du cours, découvre pourquoi C ne vérifie jamais les bornes des tableaux et comment lire et copier les données pour qu’elles tiennent toujours dans l’espace prévu.

DébutantUnité 3 sur 8 de la formation Formation : Langage C : pointeurs, mémoire et structures

Ce que tu vas apprendre

  1. Déclare des tableaux de taille fixe, accède à chaque élément par son indice, parcours-les sans dépasser leur fin et partage-les avec des fonctions.
    • Déclarer et initialiser un tableau, puis accéder à ses éléments par indice
      Crée des tableaux contenant un nombre fixe d’éléments, donne-leur des valeurs initiales et lis ou modifie des éléments à l’aide de leur indice.
    • Parcourir des tableaux avec des boucles sans dépasser leurs limites
      Parcours chaque élément avec une boucle de comptage et utilise ce modèle pour calculer une somme, trouver la plus grande valeur, rechercher, compter et inverser.
    • Passer des tableaux à des fonctions
      Écris des fonctions qui prennent des tableaux en paramètres, transmets leur longueur séparément et sache quand la fonction peut modifier les données de la fonction appelante.
  2. Traite les caractères comme de petits codes entiers, stocke le texte dans des tableaux de char terminés par un caractère nul, traite-le caractère par caractère et découvre comment le texte UTF-8 est stocké sous forme d’octets.
    • Traiter les caractères comme des codes numériques
      Utilise le type char et les constantes caractère comme des nombres, convertis chiffres et lettres par calcul et classe les caractères avec <ctype.h>.
    • Stocker du texte dans des chaînes terminées par un caractère nul
      Explique comment une chaîne de caractères C est organisée dans un tableau de char, pourquoi elle doit se terminer par un caractère nul et en quoi les littéraux de chaîne diffèrent des tableaux.
    • Traiter les chaînes caractère par caractère
      Parcours une chaîne jusqu’à son caractère nul de fin pour compter, convertir, inverser, filtrer et chiffrer du texte, et termine chaque nouvelle chaîne par '\0'.
    • Expliquer comment le texte UTF-8 est stocké dans des tableaux de char
      Relie les caractères, les points de code Unicode et les octets UTF-8, et prévois le comportement des fonctions C fondées sur les octets avec du texte qui dépasse ASCII.
  3. Mesure, copie, concatène et compare des chaînes, et effectue des recherches dans celles-ci avec <string.h>. Assure-toi que chaque destination peut contenir le résultat et son caractère nul de fin.
    • Mesurer, copier et concaténer des chaînes
      Utilise correctement strlen, strcpy et strcat et détermine l’espace nécessaire pour chaque destination.
    • Comparer des chaînes et y effectuer des recherches
      Compare des chaînes avec strcmp et strncmp, recherche des caractères et des sous-chaînes, et découpe du texte en jetons.
    • Copier en respectant les limites et manipuler directement la mémoire
      Utilise correctement les fonctions à taille limitée strncpy, strncat et snprintf, détecte les troncatures, puis copie, remplis et compare des tableaux entiers avec les fonctions de manipulation de la mémoire.
  4. Stocke des tableaux de données et des listes de chaînes dans des tableaux à deux dimensions ou plus, parcours-les avec des boucles imbriquées et passe-les à des fonctions.
    • Déclarer et parcourir des tableaux à deux dimensions
      Déclare et initialise des tableaux de valeurs, explique comment leurs lignes sont disposées en mémoire et traite les lignes et les colonnes avec des boucles imbriquées.
    • Passer des tableaux à plusieurs dimensions à des fonctions et stocker des listes de chaînes
      Écris des fonctions qui prennent des tableaux à deux dimensions et conserve plusieurs chaînes soit dans un tableau de char à 2 dimensions, soit dans un tableau de pointeurs vers des chaînes.
  5. Lis les mots saisis après le nom d’un programme à l’aide de argc et argv, vérifie leur nombre et convertis-les en nombres et en options en toute sécurité.
    • Lire argc et argv
      Déclare main avec ses deux paramètres, décris ce que contient chaque élément de argv et vérifie le nombre d’arguments avant d’en utiliser un.
    • Convertir et valider les arguments numériques
      Convertis les chaînes des arguments en nombres en vérifiant les erreurs, rejette les données invalides et vérifie les bornes des valeurs avant de les utiliser.
  6. Reconnais comment les programmes C lisent et écrivent hors de leurs tableaux, pourquoi cela est dangereux et comment lire et copier du texte pour qu’il tienne toujours dans l’espace prévu.
    • Reconnaître les accès hors limites et leurs effets
      Explique pourquoi C n’arrête pas les accès hors limites, ce qui peut se produire lorsqu’ils surviennent et quelles erreurs les provoquent.
    • Lire et copier du texte en respectant les limites des tampons
      Lis les données d’entrée en limitant leur taille, détecte les lignes trop longues et ne copie le texte que s’il tient dans sa destination.

Tableaux et chaînes de caractères en C : cours

6 chapitres

1

Stocker et traiter des ensembles de valeurs à l’aide de tableaux

Les tableaux permettent à une même boucle de traiter plusieurs valeurs liées. Le tableau détermine l’espace de stockage disponible, tandis que les indices sélectionnent les éléments et qu’un nombre indique combien sont utilisés. Découvre comment les déclarations établissent les valeurs initiales, comment les boucles calculent des résultats sans dépasser les bornes et comment les fonctions partagent les éléments de la fonction appelante. De petits exemples relient le code aux positions exactes qu’il lit ou modifie.

1.1 Déclarer et initialiser un tableau, puis accéder à ses éléments par indice

Un tableau donne un seul nom à un nombre fixe de valeurs de même type. Ses éléments sont placés les uns à côté des autres en mémoire. Utilise un tableau lorsque la même opération s’applique à plusieurs valeurs, par exemple pour mettre à jour un ensemble de scores.

Créer les éléments
int scores[5] = {90, 72, 85, 64, 99};
int primes[] = {2, 3, 5, 7};
int counts[6] = {0};

La première déclaration crée cinq entiers. Le compilateur compte quatre valeurs dans le deuxième initialiseur : primes possède donc quatre éléments. Dans le troisième, le premier élément est explicitement mis à zéro et chaque valeur d’initialisation manquante devient également zéro. De même, int a[5] = {1, 2}; contient 1, 2, 0, 0, 0. Un initialiseur désigné, disponible depuis C99, choisit une position : int b[5] = {[2] = 7}; place 7 dans le troisième élément et zéro dans les autres.

Une déclaration locale automatique comme int data[5]; réserve de l’espace sans fournir de valeurs initiales. Écris chaque élément avant de le lire. Les tableaux déclarés en dehors de toute fonction et ceux déclarés static sont initialisés à zéro lorsqu’aucun initialiseur explicite n’est fourni.

Accéder à une valeur par son indice

Les indices commencent à zéro. Pour cinq éléments, les positions valides vont de 0 à 4. scores[1] désigne le deuxième score, et non le premier. Un élément peut être utilisé partout où une variable ordinaire de son type peut l’être :

scores[1] = 75;
scores[1] += 5;
int last = scores[4];

Le deuxième score vaut maintenant 80. Le dernier vaut toujours 99. Un indice peut être une variable ou une expression : scores[n - 1] accède donc au dernier élément lorsque n est le nombre d’éléments et qu’il est positif. scores[5] ne désigne aucun élément.

Compter les éléments et les octets

sizeof scores mesure tout le tableau en octets. Sur un système où les entiers occupent 4 octets, les cinq éléments occupent 20 octets. Diviser par la taille d’un élément élimine la dépendance à la taille des entiers :

size_t n = sizeof scores / sizeof scores[0];
printf("%zu\n", n);

Ce code affiche 5. size_t est le type entier non signé utilisé pour les tailles ; %zu permet de l’afficher. Ce calcul fonctionne là où scores désigne le tableau lui-même. Un paramètre de fonction ne contient pas la taille complète du tableau.

Distinguer la taille des valeurs

Un nom comme #define NUM_SCORES 5 permet à la déclaration et à ses boucles d’utiliser une même taille. En C17, une déclaration locale const int n = 5; int a[n]; crée au contraire un tableau de longueur variable : const ne fait pas de n une expression constante entière. Sa taille est choisie lors de l’exécution de la déclaration, puis reste fixe pendant toute la durée de vie du tableau. Celui-ci ne peut pas utiliser de liste d’initialisation. La prise en charge des tableaux de longueur variable est facultative en C11 et C17 ; C23 ajoute constexpr pour les constantes connues à la compilation.

Les tableaux ne peuvent pas être affectés dans leur ensemble : b = a; est invalide. Copie leurs éléments avec une boucle ou une fonction de manipulation de la mémoire adaptée. Pour deux tableaux distincts, a == b compare les adresses, et non les valeurs des éléments. Compare les éléments correspondants pour vérifier l’égalité des valeurs. Une comparaison des octets avec memcmp teste quant à elle leurs représentations en mémoire ; des valeurs à virgule flottante égales, comme zéro positif et zéro négatif, peuvent avoir des représentations différentes.

Points clés

  • Les indices d’un tableau vont de 0 au nombre d’éléments moins 1.
  • Les valeurs d’initialisation manquantes deviennent des zéros ; il faut écrire les éléments locaux non initialisés avant de les utiliser.
  • Utilise sizeof a / sizeof a[0] uniquement là où a est un tableau.
  • Un tableau conserve sa taille pendant toute sa durée de vie.
  • Copie et compare les valeurs des tableaux élément par élément.

1.2 Parcourir des tableaux avec des boucles sans dépasser leurs limites

Une boucle de comptage associe une opération aux positions d’un tableau. Détermine quels éléments contiennent des données utiles, puis parcours exactement ces positions. Le même modèle permet de calculer des totaux, d’effectuer des recherches et de mettre à jour des valeurs.

Parcourir les éléments utilisés
int t[5] = {12, 15, 9, 14, 10};
int sum = 0;
for (int i = 0; i < 5; i++) {
    sum += t[i];
}
double average = sum / 5.0;

La boucle utilise les indices 0, 1, 2, 3 et 4. Le total prend successivement les valeurs 12, 27, 36, 50 et 60 : la moyenne est donc de 12,0. Écrire i <= 5 ajoute un accès invalide à l’indice 5. Ce passage supplémentaire est une erreur de décalage d’une unité.

Pour calculer une moyenne, utilise une division à virgule flottante. Avec un total de 61, 61 / 5 donne l’entier 12 ; 61 / 5.0 donne 12,2. Stocker ensuite le premier résultat dans un double ne permet pas de retrouver la partie fractionnaire déjà supprimée.

Trouver un maximum ou une correspondance

Pour un tableau non vide, initialise le maximum avec sa première valeur :

int max = t[0];
for (int i = 1; i < 5; i++) {
    if (t[i] > max) max = t[i];
}

La première comparaison remplace 12 par 15. Les valeurs restantes sont plus petites : 15 est donc conservé. Partir de zéro échouerait pour une liste telle que {-8, -3, -11} : zéro est supérieur à toutes les valeurs stockées, mais ne figure pas dans la liste.

Une recherche séquentielle examine les valeurs dans l’ordre :

int found = -1;
for (int i = 0; i < 5; i++) {
    if (t[i] == 14) {
        found = i;
        break;
    }
}

Ici, found prend la valeur 3. La valeur -1 indique l’absence de correspondance, car elle ne peut pas être un indice valide. Ne signale l’échec qu’après avoir examiné tous les candidats. Renvoyer -1 après le premier élément différent fait manquer les correspondances situées plus loin dans le tableau.

Compter et réorganiser

Un tableau de compteurs stocke un compteur par catégorie. Pour les chiffres, int counts[10] = {0}; fournit les compteurs de 0 à 9. Après vérification de d >= 0 && d < 10, counts[d]++ augmente le compteur du chiffre d. Cette vérification protège le tableau lorsque la valeur du chiffre provient des données d’entrée.

Pour inverser un tableau, échange les paires d’éléments à partir de ses extrémités :

for (int i = 0; i < 5 / 2; i++) {
    int temp = t[i];
    t[i] = t[5 - 1 - i];
    t[5 - 1 - i] = temp;
}

Le premier échange intervertit 12 et 10. Le second intervertit 15 et 14. Le 9 du milieu reste en place, ce qui donne {10, 14, 9, 15, 12}. Arrête-toi à mi-parcours : continuer sur les cinq positions échangerait chaque paire deux fois.

Suivre séparément le nombre d’éléments et la capacité

Un tableau pouvant contenir 100 valeurs peut ne contenir actuellement que 37 éléments utiles. Sa capacité est de 100 ; son nombre d’éléments utilisés est de 37. Traite les positions inférieures à count. Pour ajouter une valeur, vérifie d’abord count < CAPACITY, stocke-la dans a[count], puis incrémente count. Une boucle allant jusqu’à la capacité peut lire des positions qui n’ont jamais reçu de valeurs utiles, même si elles se trouvent physiquement dans le tableau.

Points clés

  • Utilise une borne stricte < pour la boucle.
  • Utilise une division à virgule flottante lorsqu’une moyenne peut avoir une partie fractionnaire.
  • Initialise le maximum d’un tableau non vide à partir d’un de ses éléments, y compris lorsque toutes les données sont négatives.
  • Une recherche est déclarée infructueuse après vérification de tous les candidats.
  • Valide une valeur avant de l’utiliser comme indice.
  • Pour inverser le tableau, effectue les échanges uniquement sur la première moitié des paires.
  • Le nombre d’éléments utilisés indique combien sont utilisés ; la capacité indique l’espace disponible.

1.3 Passer des tableaux à des fonctions

Une fonction peut traiter un tableau sans recevoir de copie distincte de chaque élément. L’appel donne accès au stockage de la fonction appelante. Transmets également le nombre d’éléments pour que la fonction sache où s’arrêter.

Fournir les données et leur longueur
#include <stddef.h>

double average(const int a[], size_t n) {
    if (n == 0) return 0.0;
    int sum = 0;
    for (size_t i = 0; i < n; i++) {
        sum += a[i];
    }
    return (double) sum / n;
}

La fonction appelante peut déclarer int values[] = {7, 8, 10}; et appeler average(values, sizeof values / sizeof values[0]). Les trois additions donnent 25 ; convertir sum en double avant la division produit environ 8,33. Renvoyer 0,0 en l’absence de valeurs est le comportement choisi pour cette fonction lorsque l’entrée est vide. Les petites valeurs de cet exemple maintiennent la somme entière dans la plage représentable.

Dans une déclaration de paramètre, int a[] est ajusté en int *a. Le paramètre reçoit l’adresse du premier élément. Même int a[10] ne vérifie ni n’impose la présence de dix éléments. La fonction appelante doit fournir une longueur correspondant aux données disponibles.

Pourquoi sizeof ne donne plus la longueur

Au point d’appel, sizeof values mesure le tableau. Dans la fonction, sizeof a mesure le paramètre pointeur. Lorsque les pointeurs occupent 8 octets et les entiers 4, diviser ces tailles donne 2, quel que soit le nombre d’éléments de la fonction appelante. Ce résultat ne décrit ni une copie de deux éléments ni le tableau d’origine. Conserve la longueur dans un paramètre explicite.

size_t, déclaré par des fichiers d’en-tête dont <stddef.h>, est le type non signé produit par sizeof. Il peut représenter les tailles des objets, et %zu permet de l’afficher. L’utiliser pour l’indice de boucle évite de comparer un indice signé à une longueur non signée.

Déterminer si les éléments peuvent changer

Le const de const int a[] empêche les affectations aux éléments par l’intermédiaire de ce paramètre. Il convient à une fonction qui calcule un résultat à partir des données. Une fonction destinée à modifier les éléments l’omet :

void zero(int a[], size_t n) {
    for (size_t i = 0; i < n; i++) {
        a[i] = 0;
    }
}

Après zero(values, 3), les trois éléments de la fonction appelante valent tous zéro. Le tableau compte toujours trois éléments. Un paramètre scalaire comme n est une copie distincte ; modifier cette copie ne changerait pas la variable de comptage de la fonction appelante.

Pour produire plusieurs résultats, laisse la fonction appelante fournir un tableau de sortie et sa longueur. Une fonction peut remplir out[i] avec chaque résultat. Les fonctions C ne peuvent pas renvoyer un tableau par valeur, et renvoyer l’adresse d’un tableau local ne fonctionne pas, car ce tableau cesse d’exister lorsque la fonction se termine.

Compter à rebours avec un indice non signé

Un indice non signé ne peut pas devenir négatif. Dans for (size_t i = n - 1; i >= 0; i--), le test est toujours vrai ; après zéro, la valeur reboucle vers un grand nombre positif. Avec n == 0, même la soustraction initiale provoque un rebouclage. Pars plutôt du nombre d’éléments :

for (size_t i = n; i > 0; i--) {
    printf("%d\n", a[i - 1]);
}

Avec trois éléments, les indices utilisés sont 2, 1 et 0. Avec zéro élément, le corps de la boucle ne s’exécute jamais. Inclus <stdio.h> pour printf.

Points clés

  • Passe la longueur d’un tableau séparément : le nombre d’éléments ne peut pas être déduit du paramètre.
  • Les écritures par l’intermédiaire d’un paramètre tableau modifient les éléments de la fonction appelante.
  • Utilise const pour un paramètre qui ne fait que lire les éléments.
  • La fonction appelante fournit le stockage nécessaire à plusieurs valeurs de sortie.
  • Avec size_t, compte à rebours depuis n et accède à i - 1.
2

Représenter du texte avec des caractères et des chaînes terminées par un caractère nul

Le texte commence par des codes de caractères et se termine par une règle de stockage : une chaîne C s’arrête à son premier octet nul. Découvre les différences entre caractères, littéraux et tableaux modifiables, puis utilise des boucles pour compter et transformer le texte. UTF-8 ajoute une distinction essentielle entre un octet et un point de code complet. Suivre à la fois le texte et son stockage explique pourquoi un mot visible peut nécessiter plus de positions dans un tableau que son nombre de lettres ne le laisse penser.

2.1 Traiter les caractères comme des codes numériques

Un caractère C est stocké sous forme de code numérique. Un programme peut ainsi afficher un symbole, le comparer à un autre ou effectuer des calculs sur son code. Le jeu de caractères détermine le nombre qui représente chaque symbole.

Lire le code et le caractère

Un char occupe un octet : sizeof(char) vaut 1 par définition. Une constante caractère comme 'A' est de type int. Dans le jeu de caractères fondé sur ASCII utilisé ici, son code est 65 :

printf("%c %d\n", 'A', 'A');

La sortie est « A 65 ». %c affiche le caractère ; %d affiche son nombre. ASCII attribue les codes de 0 à 127. Les chiffres vont de 48 à 57, les majuscules de 65 à 90, les minuscules de 97 à 122, et l’espace porte le code 32.

Les apostrophes et les guillemets doubles produisent des éléments différents. 'A' est un code de caractère. "A" est un tableau contenant 'A' et un octet nul de fin. Stocke un caractère avec char c = 'A'; et compare-le avec c == 'A'.

Écrire les caractères qui nécessitent un échappement
Écriture en CCaractère
'\n'Saut de ligne, code ASCII 10
'\t'Tabulation, code ASCII 9
'\\'Barre oblique inverse
'\''Apostrophe
'\0'Caractère nul, code 0

Le caractère nul est différent du chiffre visible '0', dont le code ASCII est 48. Une chaîne utilise le caractère nul pour marquer sa fin.

Transformer les codes en valeurs utiles

La norme C garantit que les codes des chiffres sont consécutifs. Après avoir vérifié que c est un chiffre, c - '0' produit sa valeur. Ainsi, '7' - '0' vaut 7, et non 55. Soustraire le code de départ retire la position du chiffre dans le jeu de caractères.

Les lettres ASCII sont elles aussi consécutives : soustraire 'A' convertit donc une majuscule en une position de 0 à 25. Un décalage de César de trois utilise :

char shifted = (c - 'A' + 3) % 26 + 'A';

Pour 'X', soustraire 65 donne 23 ; ajouter trois donne 26 ; le reste de la division par 26 vaut zéro ; ajouter 65 redonne 'A'. L’expression 'X' + 3 seule donne le code 91, soit '['. Les calculs sur les lettres dépendent d’un ordre de type ASCII ; C garantit que les chiffres sont consécutifs, mais ne l’exige pas pour les lettres.

Classer et convertir avec ctype.h

Inclus <ctype.h> pour utiliser isdigit, isalpha, isalnum, isspace, isupper, islower, toupper et tolower. Les tests renvoient une valeur non nulle en cas de correspondance et zéro sinon. toupper('q') renvoie 'Q' ; toupper('3') laisse le chiffre inchangé. isspace reconnaît les séparateurs tels que l’espace, la tabulation et le saut de ligne.

Un char sans autre qualification peut être signé. Un octet supérieur à 127 peut alors devenir une valeur négative, qui n’est pas un argument valide pour ces fonctions, sauf s’il s’agit du marqueur d’entrée spécial EOF. Lorsque tu traites les octets d’une chaîne, convertis-les d’abord :

if (isalpha((unsigned char) c)) {
    c = (char) toupper((unsigned char) c);
}

Dans la locale « C » par défaut, ces fonctions reconnaissent les lettres de base, mais pas les caractères UTF-8 complets codés sur plusieurs octets. La conversion explicite rend l’octet valide comme argument ; elle ne décode pas UTF-8.

Points clés

  • Les constantes caractère utilisent des apostrophes ; les littéraux de chaîne de caractères utilisent des guillemets doubles.
  • \0 est un caractère de valeur zéro, et non le chiffre 0.
  • Soustrais '0' d’un caractère chiffre pour obtenir sa valeur.
  • Les calculs sur les positions des lettres utilisent ici l’ordre ASCII.
  • Convertis un octet de chaîne en unsigned char avant un appel à une fonction de ctype.
  • Un test de ctype renvoie une valeur non nulle en cas de correspondance, pas nécessairement 1.

2.2 Stocker du texte dans des chaînes terminées par un caractère nul

Une chaîne de caractères C est une suite de caractères terminée par '\0'. Le caractère nul de fin fait partie du stockage, mais pas de la longueur du texte. C ne possède pas de type de chaîne intégré distinct : les caractères occupent un tableau.

Voir les octets dans le tableau
char word[] = "cat";
char name[20] = "Ada";

word contient quatre octets : 'c', 'a', 't', '\0'. La taille de son tableau est de 4 et strlen(word) vaut 3. Inclus <string.h> pour utiliser strlen. Le tableau name, plus grand, contient les trois lettres, leur caractère nul de fin et seize autres octets nuls. Sa capacité est de 20 tandis que sa longueur actuelle est de 3.

Un initialiseur caractère par caractère peut créer la même chaîne :

char word[] = {'c', 'a', 't', '\0'};

Omettre le dernier élément crée trois caractères sans caractère nul de fin de chaîne. C autorise aussi char word[3] = "cat";, qui remplit les trois positions et omet l’octet nul. Un tel tableau n’est pas une chaîne C. Une fonction comme strlen ou printf avec %s continue à lire jusqu’à rencontrer un octet nul : elle ne peut donc pas traiter ce tableau de trois octets comme du texte en toute sécurité.

Choisir un tableau modifiable ou un littéral
DéclarationEmplacement du texteSes caractères peuvent-ils changer ?
char a[] = "hello";Une copie dans le tableau aOui
const char *p = "hello";Un littéral de chaîne de caractères désigné par pNon

a[0] = 'H'; modifie la copie pour donner « Hello ». Un littéral ne doit pas être modifié. Même s’il est affecté à un char * sans autre qualification, écrire par l’intermédiaire de ce pointeur provoque un comportement indéfini. Écrire const char * rend cette restriction visible pour le compilateur.

Le compilateur réunit les littéraux de chaîne adjacents : "Hello, " "world" donne le même texte que "Hello, world". La chaîne obtenue ne possède toujours qu’un seul caractère nul de fin. Cela permet de répartir un long littéral sur plusieurs lignes du code source.

Afficher et modifier le texte
printf("%s\n", word);
printf("%c\n", word[0]);

Le premier appel affiche toute la chaîne. Le second affiche son premier caractère. Un littéral de chaîne dans printf est entouré de guillemets doubles parce qu’il s’agit d’un texte contenant un format ; %c reçoit un code de caractère.

L’affectation à un élément modifie un caractère stocké. Avec char name[20] = "Ada";, l’instruction name[0] = 'E'; produit « Eda ». L’instruction name[1] = '\0'; produit ensuite la chaîne « E ». Les octets de 'a' et de l’ancien caractère nul de fin existent toujours plus loin dans le tableau, mais les opérations sur les chaînes s’arrêtent au premier zéro.

Après sa déclaration, un tableau ne peut pas recevoir un texte de remplacement avec name = "Bob";. Copie-y les caractères avec un appel vérifié à strcpy ou une boucle, sans oublier le caractère nul de fin. La longueur du texte de remplacement doit être inférieure à la capacité.

Représenter l’absence de texte

La chaîne vide "" occupe tout de même un octet pour '\0'. Sa longueur est nulle et elle peut être testée avec name[0] == '\0'. Une chaîne vide est une véritable chaîne avec un caractère nul de fin ; un pointeur nul, lui, ne désigne aucun espace de stockage de chaîne.

Points clés

  • Une chaîne C s’arrête à son premier '\0'.
  • La capacité comprend le caractère nul de fin ; la longueur de la chaîne ne le comprend pas.
  • Un tableau de caractères sans caractère nul de fin ne peut pas être passé comme chaîne C.
  • Les copies de littéraux dans des tableaux sont modifiables ; les littéraux eux-mêmes ne le sont pas.
  • Écrire un caractère nul de fin plus tôt raccourcit le texte sans redimensionner son tableau.

2.3 Traiter les chaînes caractère par caractère

Le caractère nul de fin d’une chaîne indique à une boucle où s’arrêter. Parcours les octets qui le précèdent pour compter, convertir ou filtrer le texte. Lors de la création d’une nouvelle chaîne, le programme doit lui-même écrire un nouveau caractère nul de fin.

Parcourir la chaîne une seule fois jusqu’à la fin
for (size_t i = 0; s[i] != '\0'; i++) {
    /* Process s[i]. */
}

À chaque passage, le test vérifie si l’octet courant appartient au texte. La boucle s’arrête avant le caractère nul de fin. Appeler strlen(s) dans ce test peut parcourir à nouveau toute la chaîne à chaque passage. Teste directement l’octet courant ou calcule size_t len = strlen(s); une seule fois lorsque la longueur restera inchangée.

Pour convertir en majuscules, utilise un tableau modifiable et <ctype.h> :

for (size_t i = 0; s[i] != '\0'; i++) {
    s[i] = (char) toupper((unsigned char) s[i]);
}

« Hello, World 42 » devient « HELLO, WORLD 42 ». La conversion conserve la virgule, les espaces et les chiffres. La conversion en type non signé rend chaque octet stocké valide comme argument pour une fonction de ctype.

Compter les catégories et les débuts de mots

Le texte initial « Hello, World 42 » contient 15 octets de texte : 10 lettres, deux chiffres, deux espaces et une virgule. Des compteurs distincts peuvent utiliser isalpha, isdigit et isspace. Définis ce qu’est un mot avant de le compter. Pour une suite de lettres, un nouveau mot commence lorsqu’une lettre suit un caractère qui n’est pas une lettre ou qu’elle est le premier caractère :

int in_word = 0;
size_t words = 0;
for (size_t i = 0; s[i] != '\0'; i++) {
    int letter = isalpha((unsigned char) s[i]) != 0;
    if (letter && !in_word) words++;
    in_word = letter;
}

L’exemple contient deux suites de lettres, « Hello » et « World ». Selon cette définition, les chiffres ne forment pas un mot. La mise à jour de in_word à chaque passage permet à la ponctuation de terminer une suite.

Inverser uniquement le texte

Pour une chaîne dont chaque caractère occupe un octet, obtiens len une seule fois, puis échange s[i] et s[len - 1 - i] tant que i < len / 2. L’inversion de « stressed » échange sa première et sa dernière lettre, puis la paire suivante, jusqu’à obtenir « desserts ». L’octet nul reste à l’indice len. Commencer un échange à s[len] déplacerait cet octet nul au début. Cette inversion des octets convient au texte ASCII ; les caractères codés sur plusieurs octets doivent être décodés avant d’être réorganisés.

Construire un résultat filtré

Utilise des indices distincts pour la lecture et l’écriture, car certains octets d’entrée sont ignorés :

char in[] = "a1b2c3";
char out[sizeof in];
size_t j = 0;
for (size_t i = 0; in[i] != '\0'; i++) {
    if (isalpha((unsigned char) in[i])) {
        out[j++] = in[i];
    }
}
out[j] = '\0';

Le résultat est « abc ». La destination dispose d’assez d’espace, car le filtrage ne peut pas allonger cette entrée. Sans out[j] = '\0';, la chaîne produite n’a pas de fin définie.

Pour un chiffrement de César, décale les majuscules par rapport à 'A' et les minuscules par rapport à 'a', puis copie les autres octets sans les modifier. Avec la clé 13, « Hello, World! » devient « Uryyb, Jbeyq! ». Répéter ce décalage rétablit le texte initial, car deux décalages donnent un total de 26. Une comparaison comme s[i] == 'a' teste un caractère ; utilise strcmp pour comparer des textes complets.

Points clés

  • Teste l’octet courant ou conserve la longueur calculée pour éviter de parcourir toute la chaîne plusieurs fois.
  • Utilise des indices de lecture et d’écriture distincts lors du filtrage.
  • Écris un caractère nul de fin après avoir construit une nouvelle chaîne.
  • Inverse les octets du texte sans déplacer le caractère nul de fin.
  • Définis la frontière d’un mot avant d’écrire un compteur de mots.
  • Applique séparément les décalages des lettres ASCII aux majuscules et aux minuscules.

2.4 Expliquer comment le texte UTF-8 est stocké dans des tableaux de char

La longueur d’un texte peut désigner un nombre d’octets ou un nombre de points de code Unicode. Ces nombres diffèrent souvent. Un tableau C de char donne accès aux octets individuels : ses indices et les fonctions de manipulation des chaînes ne suivent donc pas automatiquement les caractères complets hors ASCII.

Distinguer caractères, points de code et octets

Un encodage des caractères décrit la façon dont le texte est stocké. ASCII utilise les codes de 0 à 127 pour les lettres de base, les chiffres, la ponctuation et les caractères de contrôle. Unicode attribue des points de code aux caractères de nombreux systèmes d’écriture : « é » a pour point de code U+00E9 et « € » a pour point de code U+20AC. UTF-8 encode les valeurs scalaires Unicode sur un à quatre octets.

Les points de code ASCII conservent leur encodage sur un octet. Le « é » précomposé utilise deux octets, 0xC3 et 0xA9 ; « € » en utilise trois. De nombreux points de code correspondant chacun à un émoji utilisent quatre octets. Un symbole affiché peut contenir plusieurs points de code : même le nombre de points de code ne correspond donc pas toujours au nombre de symboles visibles.

Mesurer une chaîne UTF-8
char s[] = "café";
printf("%zu %zu\n", strlen(s), sizeof s);

Avec un texte d’exécution en UTF-8, ce code affiche « 5 6 ». Les trois premières lettres utilisent trois octets et « é » en utilise deux, soit cinq octets de texte. Le caractère nul de fin ajoute un sixième octet de stockage. s[3] est le premier octet de « é », et non la lettre entière.

Une coupure après quatre octets conserverait 0xC3, mais supprimerait son octet de continuation 0xA9. Le résultat ne serait plus du UTF-8 valide. Une limite de tampon exprimée en octets nécessite donc une vérification des frontières de caractères si le programme tronque du texte UTF-8.

Compter les octets de début dans un UTF-8 valide

Un octet de continuation commence par les bits 10. Sa valeur est comprise entre 0x80 et 0xBF. Un octet de début ou un octet ASCII ne présente pas cette configuration :

size_t points = 0;
for (size_t i = 0; s[i] != '\0'; i++) {
    unsigned char c = (unsigned char) s[i];
    if ((c & 0xC0) != 0x80) points++;
}

Le masque 0xC0 ne conserve que les deux bits de poids fort ; 0x80 représente la configuration 10 à ces positions. Le test compte quatre points de code dans « café » en comptant ses quatre octets de début. Il suppose que le texte UTF-8 est valide et ne valide pas les séquences mal formées ni ne regroupe les points de code en symboles visibles.

Choisir des opérations qui préservent l’encodage

Copier une chaîne UTF-8 complète préserve ses octets. Concaténer des chaînes complètes, comparer leurs séquences d’octets pour vérifier leur égalité et rechercher un caractère ASCII ou une sous-chaîne UTF-8 complète fonctionnent également. Les octets de continuation UTF-8 ne peuvent pas être confondus avec des caractères ASCII ni avec des octets de début.

strcmp classe les valeurs des octets non signés : son ordre diffère donc de l’ordre alphabétique propre à chaque langue. En UTF-8, les lettres latines accentuées ordinaires ont des octets de début supérieurs au code ASCII de 'z'. Une comparaison des octets place donc ces lettres après 'z', quelles que soient les conventions du dictionnaire.

Dans la locale « C » par défaut, toupper et isalpha traitent un octet et ne décodent pas « é » comme une lettre. La conversion explicite en unsigned char rend l’appel valide, mais ne peut pas en faire une conversion de casse Unicode. Cette tâche nécessite des fonctions pour caractères larges ou une bibliothèque Unicode. Une boucle de César limitée à ASCII peut préserver les lettres accentuées en ne modifiant que les octets de A à Z ou de a à z.

L’octet zéro est l’encodage UTF-8 de U+0000 ; les autres points de code encodés ne contiennent pas d’octet zéro. Cela convient à la convention du caractère nul de fin en C. UTF-16 peut placer des octets zéro dans du texte ordinaire encodé : un tableau d’octets UTF-16 ne peut donc pas être traité comme une chaîne ordinaire de char.

Points clés

  • strlen compte les octets, y compris dans le texte UTF-8.
  • Un point de code Unicode peut occuper plusieurs octets.
  • Un indice de char peut pointer à l’intérieur d’un caractère encodé.
  • Compter les octets qui ne sont pas des octets de continuation ne compte les points de code que si le texte UTF-8 est valide.
  • La comparaison des octets vérifie l’égalité de textes encodés identiques ; l’ordre des octets n’est pas l’ordre du dictionnaire.
  • Les appels aux fonctions de ctype qui traitent un octet à la fois ne décodent pas UTF-8.
3

Utiliser les fonctions standard de manipulation des chaînes

La bibliothèque standard fournit des opérations courantes sur le texte, mais chaque fonction attend un type précis de données d’entrée et donne un sens précis à son argument de taille. Apprends à mesurer, copier, concaténer et comparer des chaînes, à y effectuer des recherches, puis à choisir le formatage à taille limitée ou les opérations sur les octets lorsqu’ils conviennent. Vérifier la capacité et interpréter les valeurs de retour transforme un simple appel de fonction en une opération prévisible sur un espace de stockage connu.

3.1 Mesurer, copier et concaténer des chaînes

Les fonctions de <string.h> manipulent du texte terminé par un caractère nul. Elles peuvent déterminer sa longueur, le copier ou lui ajouter du texte, mais les fonctions de copie ne découvrent pas la capacité de la destination. Détermine l’espace nécessaire avant d’écrire.

Mesurer la longueur sans le caractère nul de fin

strlen(s) renvoie un size_t indiquant le nombre d’octets avant le premier octet nul. Ainsi, strlen("hello") vaut 5 et strlen("") vaut zéro. Affiche le résultat avec %zu.

char buf[64] = "hi";
printf("%zu %zu\n", strlen(buf), sizeof buf);

Ce code affiche « 2 64 ». Le premier résultat mesure le texte actuel ; le second mesure l’espace disponible dans le tableau. Une copie ultérieure peut modifier le premier sans changer le second. Les deux appels sont utiles ici, car buf est un tableau et contient déjà une chaîne valide.

Copier une chaîne complète

strcpy(dest, src) copie le texte et son octet nul final. La capacité nécessaire est égale à la longueur de la source plus un :

char dest[12];
const char *src = "Maple";
if (strlen(src) < sizeof dest) {
    strcpy(dest, src);
}

« Maple » occupe cinq octets de texte et un caractère nul de fin : la chaîne tient donc dans le tableau. Le signe strict < compte : une source dont la longueur égale la capacité ne laisse aucune place pour son octet nul. Si la vérification échoue, le programme doit traiter l’erreur avant d’utiliser la destination comme nouvelle chaîne.

Une affectation de tableau telle que dest = src; ne peut pas remplacer son contenu. Affecter une variable char * à une autre est autorisé, mais ne copie qu’une référence au même espace de stockage. Cela ne crée pas une autre copie des caractères.

Ajouter du texte à une chaîne existante

strcat(dest, src) cherche d’abord le caractère nul de fin déjà présent dans dest. La fonction le remplace par le premier octet de la source et écrit un nouveau caractère nul après le texte ajouté. La capacité de la destination doit couvrir les deux longueurs actuelles plus un.

char full[16];
strcpy(full, "Ada");
strcat(full, " ");
strcat(full, "Lovelace");

Les longueurs passent de 3 à 4 puis à 12. Le résultat final « Ada Lovelace » nécessite 13 octets de stockage, ce qui laisse trois octets inutilisés. Une destination de 12 octets serait trop petite d’un octet, bien qu’elle corresponde à la longueur du texte visible.

N’ajoute jamais de texte à un tampon local non initialisé. Avec char out[20]; strcat(out, "hi");, strcat ne dispose d’aucune fin de texte établie à rechercher. Commence par char out[20] = "";, écris out[0] = '\0'; ou effectue d’abord une copie vérifiée.

Tenir compte du stockage et du coût des parcours

La source et la destination ne doivent pas se chevaucher avec strcpy ou strcat. Déplacer du texte à l’intérieur d’un même tampon peut créer un chevauchement, même lorsque les deux emplacements sont valides séparément. memmove est la fonction prévue pour les zones d’octets qui se chevauchent.

strlen doit parcourir la chaîne jusqu’au caractère nul de fin. strcat doit parcourir la destination actuelle avant l’ajout. Des ajouts répétés dans une boucle parcourent donc à nouveau le texte déjà construit. Pour assembler de nombreux morceaux, conserve la longueur actuelle de la sortie et écris chaque morceau à cet indice, en vérifiant la capacité restante et en maintenant le caractère nul de fin. Une longueur connue n’est utile que tant qu’elle correspond au contenu réel.

Points clés

  • strlen mesure le texte actuel ; sizeof appliqué à un tableau mesure sa capacité.
  • Une copie nécessite la longueur de la source plus un octet.
  • Une concaténation nécessite la somme des longueurs des deux chaînes plus un octet.
  • Initialise la destination comme une chaîne avant d’y ajouter du texte.
  • Copier ou concaténer des zones de chaînes qui se chevauchent est invalide.

3.2 Comparer des chaînes et y effectuer des recherches

La comparaison de chaînes répond à des questions sur leur texte, tandis que la recherche trouve un emplacement dans ce texte. Aucune de ces opérations ne se fait en comparant des noms de tableaux avec ==. Utilise le résultat de la bibliothèque selon ce qu’il représente : un signe de comparaison, une longueur ou l’emplacement d’une correspondance.

Comparer le texte et les préfixes

strcmp(a, b) compare les octets correspondants comme des valeurs unsigned char jusqu’à une différence ou à la fin de la chaîne. Le résultat est nul si les textes sont égaux, négatif si a vient en premier et positif si cette chaîne vient après. Seul le signe est spécifié ; ne t’attends pas exactement à -1 ou 1.

if (strcmp(command, "quit") == 0) {
    puts("Goodbye");
}

Le test explicite de zéro signifie que les textes sont égaux. Un simple if (strcmp(command, "quit")) entre dans le bloc lorsque les textes diffèrent, car une valeur non nulle est vraie. La comparaison command == "quit" comparerait les emplacements de stockage.

Dans l’ordre ASCII, « apple » vient avant « banana » dès la première lettre. « Zebra » vient avant « apple », car la majuscule 'Z' a le code 90 et la minuscule 'a' le code 97. « app » vient avant « apple », car son octet nul est rencontré avant le 'l' de l’autre chaîne. Il s’agit d’un classement des octets, et non d’une comparaison selon le dictionnaire.

strncmp(a, b, n) compare au plus n octets. strncmp(s, "--", 2) == 0 reconnaît un préfixe de deux tirets, mais ne signifie pas que toute la chaîne se limite à « -- ». Le C standard ne possède pas de fonction de comparaison de chaînes entières insensible à la casse. Un programme peut comparer lui-même les octets convertis ; POSIX fournit strcasecmp dans <strings.h>.

Rechercher un emplacement

Utilise strchr pour la première occurrence d’un caractère, strrchr pour la dernière et strstr pour la première occurrence d’une sous-chaîne complète. Ces fonctions renvoient un pointeur vers l’emplacement de la correspondance ou NULL s’il n’y en a pas.

char name[] = "report.final.txt";
char *extension = strrchr(name, '.');
if (extension != NULL) {
    printf("%s\n", extension);
}

Ce code affiche « .txt », point trouvé compris. Partir du premier point avec strchr afficherait « .final.txt ». strstr(name, "final") trouve la partie finale qui commence par « final.txt » ; rechercher « draft » donne NULL. Vérifie que le résultat n’est pas NULL avant de l’afficher ou de le lire.

Repérer un séparateur ou découper du texte

strcspn(s, set) compte les octets initiaux qui ne correspondent à aucun des caractères de set. Avec "oak:pine,birch" et l’ensemble ":,", la fonction s’arrête aux deux-points. Pour une chaîne d’entrée valide, ce modèle supprime le premier saut de ligne :

buf[strcspn(buf, "\n")] = '\0';

S’il n’y a pas de saut de ligne, l’indice renvoyé est la longueur de la chaîne : l’affectation réécrit donc le caractère nul de fin déjà présent.

strtok découpe une chaîne modifiable en utilisant n’importe quel caractère d’un ensemble de délimiteurs :

char colors[] = "red, green,blue";
char *token = strtok(colors, " ,");
while (token != NULL) {
    puts(token);
    token = strtok(NULL, " ,");
}

Les jetons sont « red », « green » et « blue ». Le premier appel fournit le tableau ; les appels suivants transmettent NULL pour continuer. La fonction écrit des octets nuls dans l’entrée et conserve un état caché entre les appels. Utilise un espace de stockage modifiable et ne t’attends pas à retrouver intacte la chaîne d’origine avec ses séparateurs. Des délimiteurs consécutifs ne produisent pas de jetons vides.

Points clés

  • Utilise strcmp(a, b) == 0 pour vérifier l’égalité des textes.
  • Interprète le résultat d’une comparaison selon son signe, et non sa valeur exacte.
  • La correspondance d’un préfixe ne prouve pas l’égalité des chaînes entières.
  • Vérifie qu’un résultat de recherche n’est pas un pointeur nul.
  • strcspn renvoie une longueur de préfixe ; strtok modifie son entrée et mémorise sa position.
  • Le classement des chaînes suit les codes des octets non signés.

3.3 Copier en respectant les limites et manipuler directement la mémoire

Une limite de longueur n’est utile que si elle décrit la bonne quantité. Certaines fonctions limitent les octets de la source, d’autres la capacité de la destination, et les fonctions de manipulation de la mémoire traitent des octets bruts sans tenir compte des fins de chaînes. Lis les règles de chaque fonction avant de choisir sa limite.

Comprendre ce que signifie n

strncpy(dest, src, n) écrit exactement n positions lorsque la source est plus courte, en complétant avec des octets nuls. Lorsque la source contient au moins n octets de texte, la fonction copie ces octets sans caractère nul de fin. Pour un tableau de capacité positive, voici une copie avec troncature qui se termine par un caractère nul :

strncpy(dest, src, sizeof dest - 1);
dest[sizeof dest - 1] = '\0';

La dernière affectation est essentielle lorsque la source atteint la limite. Tronquer un nom ou une commande peut tout de même en changer le sens : rejette donc une entrée trop longue lorsqu’une copie complète est nécessaire.

strncat(dest, src, n) ajoute au plus n octets de texte, puis un caractère nul de fin. La fonction ne reçoit pas la capacité totale. Pour une chaîne valide déjà présente dans un tableau de destination, l’espace restant pour le texte est sizeof dest - strlen(dest) - 1. Passer sizeof dest comme valeur de n peut provoquer un débordement.

Formater et détecter la troncature

snprintf, déclarée dans <stdio.h>, reçoit la capacité totale de la destination. Si la capacité est supérieure à zéro, la fonction écrit au plus ce nombre d’octets de texte moins un, puis un caractère nul de fin :

char buf[8];
int needed = snprintf(buf, sizeof buf, "%s-%d", "item", 2026);
if (needed < 0) {
    puts("Formatting error");
} else if ((size_t) needed >= sizeof buf) {
    puts("Text did not fit");
}

Le résultat complet « item-2026 » contient neuf octets de texte. Le tampon stocke « item-20 » et son octet nul, tandis que needed vaut 9. La valeur de retour compte le texte qui aurait été produit, sans le caractère nul de fin. Vérifie si le résultat est négatif avant de le convertir en size_t.

Copier et remplir des octets

memcpy(dest, src, n) copie exactement n octets, y compris les éventuels octets nuls, sans chercher de caractère nul de fin. Pour deux tableaux d’entiers de même taille, memcpy(b, a, sizeof a) copie tout leur espace de stockage lorsque les zones ne se chevauchent pas. Lorsque chacun des cinq entiers occupe quatre octets, cela représente 20 octets. memmove effectue une copie d’octets dont le comportement est défini pour les zones qui se chevauchent.

memset(a, 0, sizeof a) remplit chaque octet avec zéro et met à zéro un tableau d’entiers. Son deuxième argument décrit chaque octet, et non chaque élément. Avec des entiers de quatre octets, un remplissage avec 1 donne les octets 01 01 01 01, soit 16 843 009 dans la représentation ordinaire, et non l’entier 1. Utilise une boucle pour affecter des valeurs entières non nulles.

memcmp(a, b, n) compare les octets stockés. Un résultat nul signifie que ces séquences d’octets correspondent. Pour vérifier l’égalité des valeurs, compare les éléments : les valeurs à virgule flottante 0.0 et -0.0 sont égales à la comparaison, même si leurs représentations peuvent différer.

Reconnaître d’autres familles de bibliothèques

strlcpy et strlcat, issues de BSD, ont rejoint POSIX en 2024, mais ne font pas partie des fonctions de base de C17. Elles renvoient une longueur qu’elles ont tenté de créer ; un résultat supérieur ou égal à la taille fournie indique une troncature. strlcpy écrit un caractère nul de fin lorsque la taille est positive. strlcat ne le fait que si le texte existant se termine dans la taille indiquée. Elles sont disponibles dans glibc 2.38 et les versions ultérieures. Les fonctions facultatives de l’annexe K, comme strcpy_s, sont absentes de nombreuses bibliothèques, dont glibc.

Points clés

  • strncpy peut omettre le caractère nul de fin ; strncat nécessite de la place pour en ajouter un nouveau.
  • snprintf renvoie la longueur complète du texte nécessaire ou une valeur négative en cas d’erreur.
  • Un résultat de formatage non négatif supérieur ou égal à la capacité indique une troncature.
  • Les fonctions de manipulation de la mémoire comptent les octets et ne s’arrêtent pas à zéro.
  • Utilise memmove pour les zones qui se chevauchent.
  • memset remplit des octets ; memcmp compare des représentations.
4

Organiser les données dans des tableaux à plusieurs dimensions

Les tableaux de données organisent les valeurs selon plusieurs positions. En C, un tel tableau stocke successivement des lignes de même largeur, et des boucles imbriquées permettent à un programme de travailler par ligne ou par colonne. Apprends à déclarer cette structure, à la passer à une fonction et à garder les deux indices valides. Les listes de texte présentent un choix utile : des lignes de caractères modifiables réservent un espace fixe, tandis que des tableaux de pointeurs désignent des chaînes stockées ailleurs.

4.1 Déclarer et parcourir des tableaux à deux dimensions

Un tableau de données nécessite un indice de ligne et un indice de colonne. En C, un tableau à deux dimensions est un tableau dont les éléments sont eux-mêmes des tableaux. Chaque ligne possède le même nombre d’éléments et chaque indice a sa propre borne.

Déclarer les lignes et les colonnes
int grid[3][4];
int m[2][3] = {{1, 2, 3}, {4, 5, 6}};

grid contient trois lignes de quatre entiers chacune, soit douze entiers en tout. Ses indices de ligne vont de 0 à 2 ; ses indices de colonne vont de 0 à 3. grid[1][2] accède à la troisième valeur de la deuxième ligne.

Les accolades d’initialisation imbriquées montrent le regroupement par ligne. Les éléments dont la valeur d’initialisation manque deviennent nuls. Tu peux laisser le compilateur compter les lignes dans int m[][3] = {{1, 2, 3}, {4, 5, 6}};, mais le nombre de colonnes doit être fourni. Sans lui, le compilateur ne pourrait pas déterminer où chaque ligne se termine.

Suivre le rangement par lignes

C stocke une ligne complète avant de commencer la suivante. Dans grid, les quatre premiers entiers stockés constituent la ligne 0, les quatre suivants la ligne 1 et les quatre derniers la ligne 2. grid[1][2] est le septième entier à partir du début, à la position 6 lorsque les éléments sont numérotés à partir de zéro : une ligne complète de quatre éléments, puis deux éléments supplémentaires.

Lorsque les entiers occupent quatre octets, une ligne utilise seize octets et le tableau entier quarante-huit. À l’endroit de la déclaration :

size_t rows = sizeof grid / sizeof grid[0];
size_t cols = sizeof grid[0] / sizeof grid[0][0];

La première division donne 3 et la seconde 4. Une ligne est elle-même un tableau : c’est pourquoi sizeof grid[0] mesure plus d’un entier.

Parcourir le tableau et calculer ses sommes
int sales[2][3] = {{4, 0, 7}, {5, 2, 1}};
int total = 0;
for (int r = 0; r < 2; r++) {
    int row_sum = 0;
    for (int c = 0; c < 3; c++) {
        row_sum += sales[r][c];
    }
    printf("%d\n", row_sum);
    total += row_sum;
}

La première ligne donne 11 et la seconde 8. L’addition de ces sommes donne 19. Réinitialiser row_sum dans la boucle externe permet de commencer une nouvelle somme pour chaque ligne. Si la variable n’était initialisée qu’une fois avant les deux boucles, la deuxième valeur affichée inclurait aussi la première ligne.

Pour les sommes par colonne, place la boucle des colonnes à l’extérieur et celle des lignes à l’intérieur, en accédant toujours à sales[r][c]. Les trois sommes deviennent 9, 2 et 8, ce qui donne à nouveau 19. Changer l’ordre du parcours n’oblige pas à changer le sens des deux indices. Un parcours ligne par ligne suit le stockage contigu et améliore souvent l’utilisation du cache pour les grands tableaux.

Respecter les bornes de chaque dimension

grid[c][r] inverse le sens des indices. Si c atteint 3, l’expression demande une quatrième ligne qui n’existe pas. Le fait que l’objet entier contienne douze entiers n’autorise pas à dépasser la borne d’une ligne avec un indice de colonne.

Écris deux opérations d’indexation distinctes : grid[1][2]. En C17, grid[1, 2] évalue l’expression avec l’opérateur virgule et sélectionne grid[2], une ligne, au lieu d’un élément. Avec davantage de dimensions, le même principe s’applique à plusieurs reprises : int cube[2][3][4] contient 24 éléments entiers, sélectionnés par trois indices.

Points clés

  • Un tableau à deux dimensions est un tableau de lignes de même largeur.
  • Les lignes sont stockées les unes après les autres, selon le rangement par lignes.
  • Distingue les bornes des lignes et celles des colonnes.
  • Réinitialise l’accumulateur d’une ligne ou d’une colonne au début d’un nouveau groupe.
  • Seule la première dimension peut être déduite d’un initialiseur.

4.2 Passer des tableaux à plusieurs dimensions à des fonctions et stocker des listes de chaînes

Une fonction qui reçoit un tableau de données doit disposer d’assez d’informations pour identifier chaque ligne. Une liste de chaînes présente un autre choix : stocker les caractères dans des lignes de même largeur ou stocker des références à des chaînes de longueurs différentes.

Donner sa largeur de ligne à un paramètre tableau
void double_grid(int rows, int g[][4]) {
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < 4; c++) {
            g[r][c] *= 2;
        }
    }
}

La première dimension peut être omise, car le nombre de lignes est transmis séparément. La largeur 4 définit le type de chaque ligne. Sans elle, l’écart entre les lignes ne serait pas connu pour accéder à g[r][c]. Une déclaration avec int g[][] est invalide. Les modifications effectuées par l’intermédiaire de ce paramètre persistent dans le tableau de la fonction appelante ; un paramètre tableau accessible en lecture seule peut utiliser const int g[][4].

Depuis C99, les compilateurs qui prennent en charge les paramètres de type variablement modifié acceptent des dimensions déclarées plus tôt dans la liste des paramètres :

void print_grid(int rows, int cols, int g[rows][cols]);

GCC et Clang prennent en charge cette forme en C17. Elle permet à une seule fonction de recevoir des lignes de différentes largeurs ; transmets des dimensions positives qui correspondent au tableau réel. C23 exige la prise en charge de ces types de paramètres, tandis que les objets locaux de type tableau de longueur variable restent une fonctionnalité facultative distincte. Les paramètres de largeur fixe sont utiles lorsque la prise en charge par le compilateur est limitée.

Stocker les chaînes dans des lignes
char days[7][10] = {
    "Monday", "Tuesday", "Wednesday", "Thursday",
    "Friday", "Saturday", "Sunday"
};

Chaque ligne dispose d’un espace de stockage de dix caractères, quelle que soit la longueur actuelle de son texte. « Wednesday » nécessite les dix positions : neuf lettres et un caractère nul de fin. days[2] sélectionne toute cette ligne comme chaîne ; days[2][0] sélectionne 'W'.

Une ligne peut être affichée avec %s, mesurée avec strlen ou comparée avec strcmp. Elle peut aussi recevoir une copie vérifiée. strcpy(days[0], "Mon"); tient dans dix octets et modifie le texte de la ligne 0. La ligne conserve sa largeur de dix octets et la suivante reste au même emplacement. Un texte de remplacement de dix octets nécessiterait onze octets et ne tiendrait pas.

Stocker des références à des littéraux
const char *names[] = {"Ann", "Bartholomew", "Li"};

Cette instruction déclare un tableau de pointeurs. Chaque élément désigne un littéral occupant l’espace correspondant à sa longueur plus un caractère nul de fin. names[1] désigne « Bartholomew » et names[1][0] vaut 'B'. Les littéraux ne doivent pas être modifiés.

Les éléments pointeurs peuvent changer, même si les caractères des littéraux ne le peuvent pas. names[0] = "Anna"; change le littéral désigné par le premier élément ; cette instruction n’allonge pas « Ann » en place. Dans la forme à 2 dimensions, un élément est un tableau de caractères de largeur fixe et ne peut pas être réaffecté de cette façon. Choisis des lignes modifiables pour le texte modifié en place, et des références à des littéraux pour une liste de textes fixes. Le paramètre de ligne de commande argv prend la forme d’un tableau de pointeurs, même si les caractères des arguments fournis sont modifiables.

Points clés

  • Les paramètres représentant des tableaux à plusieurs dimensions nécessitent toutes les dimensions après la première.
  • Une dimension transmise séparément doit correspondre au tableau réel.
  • Chaque ligne contenant une chaîne doit inclure son propre caractère nul de fin dans sa largeur fixe.
  • Un tableau de pointeurs stocke des références, et non des lignes de caractères de même largeur.
5

Traiter les arguments de ligne de commande

Une ligne de commande fournit du texte à un programme au démarrage. Le nombre d’arguments, leur regroupement par l’interpréteur de commandes et les opérations sur les chaînes permettent au programme d’interpréter ce texte sans supposer qu’un argument existe ou qu’il contient déjà un nombre. Suis un chemin vérifié depuis argv jusqu’à une valeur utilisable : vérifie la présence, effectue une conversion complète, détecte les erreurs de conversion et applique la plage réellement acceptée par le programme.

5.1 Lire argc et argv

Les arguments de ligne de commande permettent à la fonction appelante de fournir du texte au lancement d’un programme. L’environnement d’exécution met ces chaînes à la disposition de main. Vérifie combien ont été reçues avant d’y accéder par indice.

Lire la liste des arguments
int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i++) {
        printf("%d: %s\n", i, argv[i]);
    }
    return 0;
}

Inclus <stdio.h> pour l’affichage. argc est le nombre d’arguments et argv est la liste des chaînes. L’écriture équivalente char **argv décrit la même interface. La boucle commence à 1, car l’indice 0 contient normalement le nom utilisé pour lancer le programme.

Dans un interpréteur de commandes ordinaire, l’exécution de ./greet Ada Lovelace fournit trois chaînes : « ./greet », « Ada » et « Lovelace ». Ainsi, argc vaut 3 et le dernier argument utilisateur est argv[2]. Un pointeur nul se trouve à argv[argc], ici argv[3] ; il sert de sentinelle après les chaînes des arguments proprement dits.

Laisser l’interpréteur regrouper le texte

Les guillemets influent sur la façon dont l’interpréteur construit les arguments. L’exécution de ./greet "Ada Lovelace" fournit un argument utilisateur contenant un espace. Les guillemets regroupent les mots et ne font pas partie du texte de l’argument. argc vaut maintenant 2.

Les interpréteurs de type Unix peuvent aussi développer les motifs avant le démarrage du programme. Dans ./count *.txt, le programme reçoit généralement les noms correspondant au motif comme arguments distincts. Il reçoit les chaînes résultantes, et non une demande de développer lui-même le motif. Le comportement exact dépend de l’interpréteur et de ses paramètres.

Rejeter un argument manquant ou supplémentaire

Si un programme a besoin d’exactement un argument utilisateur, exige argc == 2 avant de l’utiliser :

if (argc != 2) {
    printf("Usage: %s name\n", argv[0]);
    return 1;
}
printf("Hello, %s\n", argv[1]);

Lorsque argc vaut 1, argv[1] est le pointeur nul servant de sentinelle et ne peut pas être passé à strlen ni affiché avec %s. Les indices au-delà de la sentinelle sont hors du tableau d’arguments.

Renvoyer zéro depuis main indique une réussite. Un code de retour non nul, comme le 1 ci-dessus, indique à l’interpréteur que le programme ne s’est pas terminé correctement. <stdlib.h> fournit aussi EXIT_SUCCESS et EXIT_FAILURE.

Traiter chaque argument comme une chaîne

argv[i][0] accède au premier caractère de l’argument ; strlen(argv[i]) mesure les octets de son texte ; strcmp(argv[i], "-v") == 0 vérifie une option complète. Un argument qui ressemble à un nombre reste du texte et doit être converti avant tout calcul.

argv[0] indique généralement comment le programme a été lancé, mais peut être vide lorsque cette information n’est pas disponible. Il est utile pour les messages, mais pas pour une vérification d’identité fixe. Les caractères des arguments peuvent être modifiés pendant l’exécution, mais l’espace de stockage fourni ne permet pas de supposer qu’un texte de remplacement plus long y tiendra. Pour ajouter une extension ou allonger le texte autrement, copie-le d’abord dans un tampon dimensionné séparément.

Points clés

  • argc compte les chaînes d’arguments fournies, y compris l’entrée contenant normalement le nom de lancement.
  • Vérifie le nombre d’arguments avant de lire un argument utilisateur.
  • argv[argc] est un pointeur nul, et non une chaîne d’argument vide.
  • Les guillemets de l’interpréteur de commandes permettent de conserver des espaces dans un même argument.
  • Utilise les opérations sur les chaînes pour le texte des arguments et une conversion pour les nombres.

5.2 Convertir et valider les arguments numériques

Un argument numérique arrive sous forme de caractères, et non d’un entier. Une conversion fiable vérifie trois points distincts : des chiffres ont-ils formé un nombre, la conversion a-t-elle utilisé le texte requis et la valeur obtenue est-elle autorisée ?

Éviter de perdre les informations sur les erreurs

atoi, déclarée dans <stdlib.h>, effectue une conversion simple. Elle transforme « 13 » en 13, mais aussi « 12abc » en 12. Elle renvoie zéro aussi bien pour « 0 » que pour un texte comme « abc » qui ne commence pas par un nombre. Un résultat hors de la plage représentable provoque un comportement indéfini : un test vérifiant uniquement la présence de chiffres, suivi de atoi, reste donc dangereux pour une entrée très longue.

Une règle de forme comme « un ou plusieurs chiffres uniquement » nécessite un parcours distinct. Rejette une chaîne vide et exige que chaque octet satisfasse isdigit((unsigned char) c). Cette règle accepte « 13 » et rejette « 13a », « -5 » et « ». Elle vérifie la forme du texte, pas si la valeur est représentable dans un entier machine.

Utiliser strtol et examiner où la conversion s’est arrêtée
#include <errno.h>
#include <stdlib.h>

char *end;
errno = 0;
long count = strtol(argv[1], &end, 10);
if (end == argv[1] || *end != '\0' || errno == ERANGE) {
    puts("Enter a whole number");
    return 1;
}
if (count < 1 || count > 100) {
    puts("Count must be from 1 to 100");
    return 1;
}

Ce fragment vient après une vérification du nombre d’arguments et utilise <stdio.h> pour puts. Le 10 sélectionne une conversion décimale. end reçoit l’emplacement où la conversion s’est arrêtée ; &end permet à la fonction de stocker cet emplacement. *end lit le caractère qui s’y trouve. Aucune arithmétique des pointeurs n’est nécessaire.

Pour « 13a », la valeur renvoyée est 13 mais *end vaut 'a' : le texte est donc rejeté. Pour une chaîne vide ou « abc », end est égal au début de l’argument, ce qui montre qu’aucun nombre n’a été consommé. Les deux vérifications sont nécessaires : tester seulement le zéro final accepterait à tort une chaîne vide.

Avant chaque conversion, remets errno à zéro. Une valeur hors de la plage de long amène strtol à renvoyer une valeur extrême et à définir l’erreur ERANGE. Sans cette remise à zéro, une ancienne erreur pourrait sembler provenir de cette conversion. Vérifie le résultat avant une conversion vers le type plus restreint int ; utilise INT_MIN et INT_MAX de <limits.h> lorsque toute la plage de int constitue le domaine accepté.

Appliquer la règle propre au programme

strtol accepte les caractères blancs initiaux et un signe facultatif. Décide si ces formes sont autorisées. Si l’interface exige uniquement des chiffres, effectue le parcours vérifiant que la chaîne n’est pas vide et ne contient que des chiffres, en plus des vérifications de conversion. Après une conversion réussie, vérifie la plage de valeurs autorisée par l’application avant d’utiliser une valeur comme nombre d’éléments ou comme indice. « 0 » peut être un texte numérique parfaitement valide tout en étant invalide pour un nombre d’éléments qui doit être positif.

Un programme de César qui accepte une clé non négative vérifie d’abord argc, puis sa forme composée uniquement de chiffres, puis le résultat complet de strtol et la plage de valeurs. Réduire une clé valide avec % 26 produit un décalage de 0 à 25 avant les calculs sur les lettres. La clé 27 a le même effet que la clé 1. Vérifie les bornes avant une conversion explicite vers un type plus restreint ou tout calcul susceptible de déborder. Pour les valeurs décimales, strtod fournit une interface correspondante pour la position de fin et les erreurs de dépassement de plage.

Points clés

  • Les arguments qui ressemblent à des nombres doivent tout de même être convertis.
  • atoi ne peut pas distinguer un zéro valide d’un échec de conversion.
  • Vérifie que strtol a lu quelque chose et consommé tout le texte requis.
  • Remets errno à zéro, vérifie ERANGE, puis vérifie la plage de valeurs autorisée par l’application.
  • Un parcours vérifiant uniquement la présence de chiffres n’exclut pas un débordement.
  • Valide une valeur avant de la convertir vers un type plus restreint ou de l’utiliser comme indice.
6

Prévenir les accès hors limites et les débordements de tampon

Les erreurs de bornes relient plusieurs idées déjà étudiées : une boucle peut effectuer un passage de trop, un texte peut nécessiter un octet supplémentaire et une fonction peut perdre la capacité d’un tableau. Apprends à identifier l’accès invalide avant d’en prévoir les effets. Lis et copie ensuite les données d’entrée dans des limites connues, en vérifiant séparément la réussite et l’exhaustivité, afin qu’un tampon de taille suffisante contienne bien les données que le programme devait accepter.

6.1 Reconnaître les accès hors limites et leurs effets

Chaque accès à un tableau nécessite un indice valide. C n’exige pas de vérification des bornes à l’exécution : le programmeur doit donc maintenir l’indice à l’intérieur de l’objet. Un accès hors de ses bornes a un comportement indéfini : le langage ne garantit aucun résultat.

Reconnaître un accès invalide

Pour int a[5], les indices valides vont de 0 à 4. L’indice 5 est déjà trop grand et -1 est négatif. Un compilateur peut signaler une erreur visible, mais de nombreux indices invalides dépendent des données reçues à l’exécution et ne sont pas rejetés à la compilation.

Un programme défectueux peut sembler fonctionner, planter ou produire des valeurs inattendues. Une écriture peut corrompre des données voisines ; le symptôme peut apparaître plus tard dans un calcul sans rapport. Une lecture peut accéder à des octets hors de l’objet visé. Aucune des deux opérations n’a de résultat fiable. Répéter une exécution réussie ne permet pas d’établir que l’accès est valide.

Compter chaque écriture, y compris celle du caractère nul de fin
char name[8];
strcpy(name, "Christopher");

« Christopher » compte onze octets de texte. Sa copie écrit aussi le caractère nul de fin : cet appel tente donc d’écrire douze octets dans huit positions. C’est un débordement de tampon. Sur les systèmes réels, un débordement peut endommager d’autres données ou des informations de contrôle. Historiquement, des attaques, dont le ver Morris de 1988, ont exploité de tels bogues de traitement des données d’entrée.

Un débordement peut ne concerner qu’un octet :

char s[5];
for (int i = 0; i <= 5; i++) {
    s[i] = 'x';
}

Le corps s’exécute six fois et écrit à l’indice 5. Remplacer le test par i < 5 maintient cinq écritures de caractères dans le tableau, mais ne crée toujours pas de chaîne. Pour une chaîne de quatre caractères 'x', écris uniquement aux indices de 0 à 3, puis stocke '\0' à l’indice 4.

Valider les indices calculés

Un tableau de compteurs peut transformer un caractère en indice, mais la soustraction seule ne garantit aucune plage de valeurs :

int counts[26] = {0};
if (c >= 'a' && c <= 'z') {
    counts[c - 'a']++;
}

Avec l’ordre ASCII, ce test limite le résultat à l’intervalle de 0 à 25. Pour 'A' ou un octet de ponctuation, utiliser c - 'a' sans le test pourrait créer un indice négatif. Teste la valeur d’origine avant d’accéder au tableau ; vérifier après l’écriture est trop tard.

Pour un tableau à plusieurs dimensions, valide séparément la ligne et la colonne. Dans int g[2][3], un indice de colonne égal à 3 est invalide, même si la ligne suivante est adjacente en mémoire. Ne te sers pas de l’espace de stockage du tableau entier pour justifier le dépassement de la borne d’une ligne.

Utiliser des vérifications adaptées à l’opération

Une boucle sur un tableau utilise une borne supérieure stricte ; un ajout compare le nombre d’éléments à la capacité ; une copie de chaîne vérifie la longueur du texte plus un. Les fonctions reçoivent les longueurs ou capacités réelles de leurs fonctions appelantes. Ces vérifications portent sur des quantités différentes : une seule taille inscrite en dur ne peut donc pas toutes les remplacer.

Compile avec des avertissements comme -Wall -Wextra. L’option -fsanitize=address -g de GCC et Clang peut signaler de nombreux accès invalides sur les chemins exécutés et montrer leur emplacement dans le code source. Ces tests aident à trouver les erreurs, mais les chemins non exécutés nécessitent toujours un raisonnement sur les bornes. Examine chaque lecture et écriture par indice en identifiant son objet, sa borne et la condition qui maintient cet indice valide.

Points clés

  • Les lectures et écritures hors limites ont un comportement indéfini.
  • Une exécution réussie ne prouve pas qu’un indice est valide.
  • La copie d’une chaîne comprend l’écriture de son caractère nul de fin.
  • Valide les données avant d’en déduire un indice de tableau.
  • Vérifie chaque dimension du tableau indépendamment.
  • Les avertissements et les sanitizers aident à détecter les bogues sur les chemins testés.

6.2 Lire et copier du texte en respectant les limites des tampons

La longueur des données d’entrée dépend de la personne qui les fournit. Donne aux fonctions de lecture une limite correspondant réellement au tampon et vérifie ce qu’elles renvoient. Détermine ensuite si les données forment une ligne complète et si elles respectent les règles propres au programme.

Lire un mot avec une largeur

Pour char word[16];, scanf("%15s", word) lit au plus quinze caractères qui ne sont pas des caractères blancs et ajoute '\0'. La largeur laisse une des seize positions pour le caractère nul de fin. %s sans largeur n’impose aucune limite de longueur ; gets posait le même problème fondamental pour les lignes et a été retirée du C en C11.

Vérifie que scanf renvoie 1 avant d’utiliser un mot. La fonction lit un mot, et non une ligne entière contenant des espaces. Les octets excédentaires du mot peuvent rester non lus : une largeur protège donc le stockage sans décider si toute l’entrée est acceptable.

Lire une ligne avec fgets
char buf[8];
if (fgets(buf, sizeof buf, stdin) == NULL) {
    return 1;
}

Ici, fgets lit au plus sept caractères et écrit un octet nul final. La fonction conserve un saut de ligne lorsqu’elle l’atteint avant la limite. Une ligne contenant « hello » et un saut de ligne devient "hello\n" plus le caractère nul de fin. La lecture d’une dernière ligne qui se termine en fin de fichier sans saut de ligne peut tout de même réussir. Si aucun caractère n’a été lu avant la fin du fichier ou si une erreur de lecture s’est produite, le résultat est NULL ; ne traite pas alors ce tampon comme une nouvelle entrée.

Distinguer un saut de ligne stocké d’une ligne partielle

Repère un saut de ligne avant de le supprimer :

size_t end = strcspn(buf, "\n");
int had_newline = buf[end] == '\n';
buf[end] = '\0';

Inclus <string.h>. Si aucun saut de ligne n’a été stocké, end est la longueur du texte et l’affectation réécrit le caractère nul de fin existant. L’absence de saut de ligne peut indiquer une ligne partielle, un tampon rempli exactement avant un saut de ligne ou une dernière ligne terminée en fin de fichier. Elle ne suffit pas à établir qu’il reste des caractères.

Pour la ligne d’entrée « abcdefghij » et un tampon de huit octets, la première lecture stocke « abcdefg » et la suivante peut lire « hij\n ». Traiter le second morceau comme une réponse distincte couperait en deux une même entrée logique. Un programme peut rejeter une ligne à laquelle manque un saut de ligne obligatoire, ou lire et éliminer le reste de la ligne avant de redemander une saisie. Définis la règle de saisie avant de l’implémenter.

Pour au plus trente caractères ASCII de nom, plus un saut de ligne et un caractère nul de fin, utilise 32 octets. Pour UTF-8, il s’agit d’une limite en octets : trente caractères affichés peuvent nécessiter davantage d’espace.

Copier uniquement après avoir vérifié toutes les conditions
char user[10];
if (argc != 2) return 1;
if (strlen(argv[1]) >= sizeof user) {
    puts("Name too long");
    return 1;
}
strcpy(user, argv[1]);

La vérification du nombre d’arguments vient en premier. Celle de la longueur accepte ensuite au plus neuf octets de texte, laissant la dixième position pour zéro. Une fonction qui écrit devrait recevoir explicitement la capacité, comme dans read_name(out, capacity), car sizeof out mesure un paramètre pointeur à l’intérieur de cette fonction.

Pour une entrée numérique, lis une ligne complète et convertis-la avec strtol, en vérifiant la position de fin, l’erreur de dépassement de plage et la plage de valeurs autorisée. Un échec de scanf("%d", &n) peut laisser le texte en cause non lu ; répéter aveuglément l’appel peut échouer indéfiniment sur les mêmes octets. Vérifie au minimum le nombre d’affectations réussies et traite l’entrée invalide avant de réessayer.

Points clés

  • Fixe la largeur de lecture d’un mot à la capacité du tampon moins un.
  • Vérifie le résultat d’une lecture avant d’utiliser son tampon.
  • fgets ne conserve un saut de ligne que si la fonction l’atteint dans la limite fixée.
  • L’absence de saut de ligne ne suffit pas à établir qu’il reste des données à lire.
  • Prévois de la place pour les octets du texte, le saut de ligne s’il est conservé et le caractère nul de fin.
  • Vérifie la présence d’un argument avant de mesurer et de copier son texte.
  • Transmets la capacité du tampon à une fonction qui y écrit.

Tableaux et chaînes de caractères en C : exemples

6 Leçons Interactives

1

Suivre un tableau de sa déclaration à l’appel d’une fonction

13 étapes
Suis les éléments initialisés, calcule une moyenne et partage les données du tableau avec une fonction.
  1. 1
    IntroductionDonner un nom à plusieurs valeurs

    Un tableau contient un nombre fixe d’éléments de même type. Une boucle sélectionne des positions, tandis qu’une fonction peut travailler sur le même espace de stockage grâce à un paramètre tableau.

    Suis quatre mesures d’un capteur depuis leur déclaration jusqu’au calcul d’un total et d’une moyenne. À chaque étape, distingue trois quantités : le nombre d’éléments, le dernier indice valide et le nombre d’octets utilisés pour le stockage.

  2. 2
    ExempleLire les positions initiales
    int readings[4] = {11, 16, 13};
    

    Il y a quatre éléments, d’indices 0 à 3. L’initialiseur fournit 11, 16 et 13 aux trois premières positions. La valeur omise devient zéro : le tableau est donc {11, 16, 13, 0}.

    Ce zéro résulte d’une règle d’initialisation et ne signifie pas que le tableau ne possède que trois éléments. Les valeurs d’un tableau local sans initialiseur devraient être écrites avant utilisation.

  3. 3
    ExplicationCompter les éléments à l’endroit de la déclaration
    size_t n = sizeof readings / sizeof readings[0];
    

    Le numérateur mesure les quatre éléments et le dénominateur en mesure un. Lorsque int occupe quatre octets, cela donne seize divisé par quatre, soit 4. La même expression fonctionne avec une autre taille d’entier.

    readings[3] est le dernier élément. readings[4] se trouve après la fin, même si le tableau compte 4 éléments. size_t est le type non signé utilisé pour ce résultat de taille.

  4. 4
    DéfiModifier la dernière mesure

    La déclaration est toujours int readings[4] = {11, 16, 13};. Quelle affectation remplace le zéro par 20, et quel est alors le nombre d’éléments ?

    ---reveal---

    Utilise readings[3] = 20;. Les valeurs obtenues sont {11, 16, 13, 20} et le nombre d’éléments reste 4. L’affectation à un élément change une valeur, pas le nombre de positions. L’indice 4 serait une position trop loin et ne peut pas ajouter d’espace à ce tableau.

  5. 5
    ExempleConstruire le total passage par passage
    int sum = 0;
    for (size_t i = 0; i < n; i++) {
        sum += readings[i];
    }
    

    Avec {11, 16, 13, 20}, la somme cumulée prend successivement les valeurs 11, 27, 40 et 60. Après l’indice 3, i devient 4 et le test échoue avant tout nouvel accès.

    Initialiser la somme à zéro donne un point de départ neutre à la première valeur. La borne supérieure stricte permet à la boucle de parcourir exactement les quatre éléments existants.

  6. 6
    Point cléConserver la partie fractionnaire d’une moyenne

    Pour ces quatre mesures, (double) sum / n donne 15,0. La conversion explicite a lieu avant la division : l’opération peut donc produire un résultat fractionnaire lorsque le total change.

    Si le total était de 61, la division entière sum / 4 produirait 15, tandis que sum / 4.0 produirait 15,25. Affecter à un double le résultat entier déjà tronqué ne produirait que 15,0 ; cela ne permettrait pas de retrouver la partie fractionnaire supprimée.

  7. 7
    ConseilChoisir une valeur initiale valide

    Une recherche de maximum nécessite une valeur initiale tirée d’un tableau non vide. Pour {-6, -2, -9}, initialise max à -6, puis remplace-le par -2 lorsque cette valeur plus grande apparaît. La dernière comparaison laisse -2 inchangé.

    Initialiser max à zéro renverrait zéro, qui n’est pas présent. Pour une recherche séquentielle, la règle d’arrêt correspondante compte aussi : une seule différence ne suffit pas à établir l’échec ; il faut encore examiner les éléments suivants.

  8. 8
    DéfiPoursuivre une recherche

    Une recherche de 13 examine {11, 16, 13, 20}. Après avoir vérifié l’indice 0, elle renvoie -1 parce que 11 diffère de 13. Que faut-il changer et où se trouve la correspondance ?

    ---reveal---

    Continue la recherche après une différence et ne renvoie -1 qu’après l’échec de tous les candidats. Ici, l’indice 1 diffère aussi, mais l’indice 2 correspond. Une recherche réussie peut s’arrêter à cet endroit. La première comparaison infructueuse décrit un élément, pas le tableau entier.

  9. 9
    LienPlacer le calcul de la moyenne dans une fonction
    double mean(const int a[], size_t n);
    

    Le paramètre tableau partage l’accès aux éléments de la fonction appelante. Il ne contient pas leur nombre : le second paramètre le fournit donc. const empêche les écritures accidentelles par l’intermédiaire de a dans cette opération en lecture seule.

    Calcule le nombre d’éléments là où readings est déclaré et appelle mean(readings, n). Dans mean, sizeof a mesure un paramètre pointeur au lieu du tableau de quatre éléments de la fonction appelante.

  10. 10
    ExempleTraiter la plage vide avant de diviser
    double mean(const int a[], size_t n) {
        if (n == 0) return 0.0;
        int sum = 0;
        for (size_t i = 0; i < n; i++) sum += a[i];
        return (double) sum / n;
    }
    

    Pour les quatre petites mesures, le total reste de 60 et le résultat est de 15,0. Lorsque n vaut zéro, le résultat choisi est 0,0 et aucun accès au tableau ni aucune division n’a lieu. La fonction appelante doit transmettre un nombre d’éléments utilisables exact.

  11. 11
    DéfiExpliquer la modification du tableau de la fonction appelante

    Une autre fonction reçoit int a[], size_t n et met à zéro chaque a[i] parcouru. Que deviennent les mesures de la fonction appelante et comment une fonction qui calcule seulement un total pourrait-elle empêcher ces écritures ?

    ---reveal---

    Les éléments de la fonction appelante deviennent nuls parce que la fonction écrit dans l’espace de stockage partagé du tableau. Ses quatre positions existent toujours. Une fonction qui calcule seulement un total devrait utiliser const int a[], ce qui rend invalides les affectations aux éléments par l’intermédiaire de a. Modifier une copie scalaire de n ne changerait pas la variable de comptage de la fonction appelante.

  12. 12
    DéfiUtiliser uniquement les mesures présentes

    Un tampon a une capacité de 10, mais seulement quatre mesures sont utilisées. Une nouvelle mesure doit être ajoutée avant le calcul d’une moyenne. Quelles vérifications et quel nombre d’éléments le programme doit-il utiliser ?

    ---reveal---

    Vérifie que le nombre d’éléments utilisés, 4, est inférieur à la capacité 10. Écris à l’indice 4, puis porte le nombre d’éléments à 5. Transmets ce nombre à mean pour que la fonction traite exactement les cinq valeurs. Transmettre la capacité inclurait des positions pour lesquelles aucune mesure n’a été fournie.

  13. 13
    RécapitulatifAssocier chaque nombre d’éléments à son rôle

    Une déclaration crée les positions, une boucle parcourt celles qui sont utilisées et une fonction reçoit explicitement le nombre d’éléments utilisables. Un paramètre en lecture seule empêche les calculs d’écraser les données d’entrée.

    Lorsque tu examines du code utilisant un tableau, suis les premier et dernier indices parcourus ainsi que l’état de chaque accumulateur. Pour les boucles size_t à rebours, commence à n, continue tant que i est positif et accède à a[i - 1] : une plage vide ne nécessite ainsi aucune soustraction à partir de zéro.

2

Transformer les octets stockés par des opérations sur le texte

16 étapes
Construis et transforme une chaîne terminée par un caractère nul, puis suis un caractère UTF-8 codé sur plusieurs octets.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionObserver à la fois le texte et son stockage
  2. 2
    ExplicationLire un caractère comme un code
  3. 3
    DéfiRevenir au début de l’alphabet
  4. 4
    ExempleConstruire une chaîne modifiable
  5. 5
    Point cléDéplacer la fin sans déplacer le stockage
  6. 6
    DéfiLaisser une position pour la fin
  7. 7
    ExempleSéparer la lecture de l’écriture
  8. 8
    ExempleTerminer la nouvelle chaîne
  9. 9
    DéfiInverser les lettres sans le caractère nul de fin
  10. 10
    ConseilClasser les octets avec des arguments valides
  11. 11
    ExempleReprésenter une lettre accentuée en UTF-8
  12. 12
    ExplicationReconnaître les octets de continuation
  13. 13
    DéfiMesurer un nouveau mot encodé
  14. 14
    LienChoisir des opérations qui gardent les caractères entiers
  15. 15
    DéfiExaminer un raccourci proposé pour le texte
  16. 16
    RécapitulatifRepérer la fin et les frontières des caractères
3

Assembler, rechercher et formater du texte en toute sécurité

14 étapes
Vérifie les capacités, interprète les résultats de recherche et gère les troncatures et les chevauchements.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionIdentifier les règles de chaque fonction
  2. 2
    ExempleCommencer par une copie complète
  3. 3
    ExempleAjouter du texte à la fin existante
  4. 4
    DéfiDéterminer si un autre ajout peut tenir
  5. 5
    ExplicationUtiliser zéro pour reconnaître des textes égaux
  6. 6
    ExempleLire à partir d’un emplacement trouvé
  7. 7
    DéfiExaminer une vérification de commande fondée sur un préfixe
  8. 8
    ConseilPrévoir que le découpage en jetons modifie le texte
  9. 9
    ExempleFormater dans une capacité connue
  10. 10
    DéfiInterpréter le même format avec moins d’espace
  11. 11
    Point cléUne limite peut compter les octets de la source
  12. 12
    ExempleDéplacer une zone qui se chevauche avec sa destination
  13. 13
    DéfiConserver un résultat complet après un décalage
  14. 14
    RécapitulatifDistinguer les octets des résultats textuels
4

Lire un tableau et choisir comment stocker une liste de chaînes

10 étapes
Suis les sommes des lignes et des colonnes, passe un tableau à une fonction et réserve de l’espace pour chaque chaîne.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionDonner deux indices à chaque position
  2. 2
    ExemplePlacer les valeurs dans des lignes
  3. 3
    ExempleRéinitialiser la somme au début de chaque ligne
  4. 4
    DéfiChanger le regroupement en conservant les indices
  5. 5
    ExplicationIndiquer la largeur des lignes à une fonction
  6. 6
    ExempleRéserver une chaîne terminée par un caractère nul par ligne
  7. 7
    Point cléUtiliser des références pour des chaînes de longueurs différentes
  8. 8
    DéfiRemplacer le texte dans l’espace approprié
  9. 9
    DéfiMaintenir les deux dimensions valides dans une fonction
  10. 10
    RécapitulatifGarder visible la forme du tableau
5

Valider une sélection en ligne de commande

11 étapes
Interprète des arguments regroupés et convertis un nombre vérifié en une sélection utilisable.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionRecevoir le texte avant de l’interpréter
  2. 2
    ExempleAssocier une commande de l’interpréteur à ses entrées
  3. 3
    ExplicationVérifier le nombre d’arguments avant la conversion
  4. 4
    DéfiRegrouper correctement un nom
  5. 5
    ConseilUn entier renvoyé ne suffit pas
  6. 6
    ExempleExaminer une conversion complète
  7. 7
    ExplicationVérifier la plage propre à la sélection
  8. 8
    DéfiRepérer un texte partiellement numérique
  9. 9
    Point cléDistinguer les règles de forme et de valeur
  10. 10
    DéfiCombiner le regroupement et la validation numérique
  11. 11
    RécapitulatifVérifier la présence, la conversion et l’usage
6

Corriger une procédure de saisie à taille limitée

13 étapes
Suis les morceaux d’une ligne, conserve de la place pour le caractère nul de fin et ne copie qu’un résultat complet et accepté.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionLimiter l’écriture et vérifier le résultat
  2. 2
    ExempleTrouver l’écriture supplémentaire
  3. 3
    Point cléUtiliser la dernière position valide pour la fin
  4. 4
    DéfiVérifier un indice déduit d’un octet
  5. 5
    ExplicationLire un mot en laissant de la place pour le caractère nul de fin
  6. 6
    ExempleLire un morceau de ligne de taille limitée
  7. 7
    ExempleObserver où une longue ligne est coupée
  8. 8
    ConseilExaminer un saut de ligne avant de le supprimer
  9. 9
    DéfiPrévoir l’espace pour une ligne complète
  10. 10
    ExempleVérifier une copie avant d’écrire
  11. 11
    DéfiDistinguer un préfixe sûr d’une réponse acceptée
  12. 12
    LienUtiliser les diagnostics et raisonner sur les bornes
  13. 13
    RécapitulatifDistinguer quatre vérifications

Tableaux et chaînes de caractères en C : QCM

60 Questions Pratiques en 6 séries

Série 1 : Valeurs des tableaux, boucles et appels de fonctions10 Questions Pratiques

Question 1 sur 10

Quelle valeur est stockée dans a[3] après int a[5] = {6, 9}; ?
  1. 6
  2. 9
  3. 0
  4. Une valeur indéterminée
Afficher la réponseMasquer la réponse
Réponse : C
L’initialiseur fournit les deux premières valeurs et C initialise les éléments restants à zéro. L’indice 3 contient donc 0. Des valeurs indéterminées seraient à craindre pour un tableau local déclaré sans initialiseur, ce qui est différent de ce tableau partiellement initialisé.

Question 2 sur 10

Un tableau est déclaré avec int a[7]; et int occupe 4 octets. Quel couple donne sizeof a et le dernier indice valide ?
  1. 28 octets ; indice 7
  2. 28 octets ; indice 6
  3. 7 octets ; indice 6
  4. 24 octets ; indice 6
Afficher la réponseMasquer la réponse
Réponse : B
Sept éléments de quatre octets occupent 28 octets et, les indices commençant à zéro, le dernier est 6. Le dernier indice est inférieur de 1 au nombre d’éléments. Utiliser l’indice 7 confond le nombre d’éléments avec la position du dernier et provoquerait un accès au-delà du tableau.

Question 3 sur 10

Pour int a[] = {-12, -4, -9};, quelle valeur une recherche de maximum doit-elle renvoyer ?
  1. -4
  2. 0
  3. -12
  4. -9
Afficher la réponseMasquer la réponse
Réponse : A
La plus grande valeur stockée est -4, car elle est supérieure à -12 et à -9. Une recherche de maximum doit partir d’un élément réel et le remplacer lorsqu’une valeur plus grande apparaît. Partir de zéro renverrait une valeur que ce tableau entièrement négatif ne contient pas.

Question 4 sur 10

Qu’affiche ce code ?

int a[] = {3, 8, 5, 2};
int sum = 0;
for (int i = 1; i < 4; i++) sum += a[i];
printf("%d", sum);
  1. 18
  2. 13
  3. 16
  4. 15
Afficher la réponseMasquer la réponse
Réponse : D
La boucle commence à l’indice 1 : elle additionne donc 8, 5 et 2 pour obtenir 15. L’indice 0 n’est jamais parcouru. Le total 18 inclut le 3 initial et ne serait correct que pour une boucle commençant à zéro, ce que ce code ne fait pas.

Question 5 sur 10

Une recherche de 7 dans {2, 9, 7, 4} renvoie -1 dès le premier élément différent. À quel moment doit-elle renvoyer une valeur d’échec ?
  1. Dans la boucle, après tout candidat différent.
  2. Après que la boucle a vérifié tous les candidats.
  3. Avant la vérification du dernier candidat.
  4. Juste après la première incrémentation de la boucle.
Afficher la réponseMasquer la réponse
Réponse : B
La première valeur, 2, ne correspond pas, mais l’indice 2 contient bien 7. L’échec n’est justifié que lorsque la boucle se termine sans correspondance. Renvoyer une valeur après une seule différence revient à tirer une conclusion sur tout le tableau à partir d’un seul élément.

Question 6 sur 10

Quel tableau obtient-on en échangeant a[i] et a[5 - 1 - i] pour i = 0 et i = 1, à partir de {4, 7, 1, 8, 6} ?
  1. {6, 7, 1, 8, 4}
  2. {4, 7, 1, 8, 6}
  3. {6, 8, 1, 7, 4}
  4. {8, 6, 1, 4, 7}
Afficher la réponseMasquer la réponse
Réponse : C
Le premier échange intervertit 4 et 6 ; le second intervertit 7 et 8. La valeur centrale 1 reste en place, ce qui produit le tableau inversé. Le résultat partiellement inversé où 7 et 8 restent inchangés ne tient compte que du premier échange, alors que deux échanges sont indiqués.

Question 7 sur 10

Une fonction void set_first(int a[]) exécute a[0] = 11;. Que vaut le premier élément du tableau de la fonction appelante après l’appel ?
  1. Il vaut 11.
  2. Il reste inchangé.
  3. Il est indéfini.
  4. Il vaut 0.
Afficher la réponseMasquer la réponse
Réponse : A
Le paramètre donne à la fonction accès aux éléments de la fonction appelante : cette affectation donne donc la valeur 11 au premier élément d’origine. Il n’existe pas de copie distincte de l’élément qui serait abandonnée au retour de la fonction. Le passage d’un tableau diffère ici du passage d’une valeur scalaire seule.

Question 8 sur 10

Dans void f(int a[], size_t n), les pointeurs occupent 8 octets et les entiers 4 octets. Que vaut sizeof a / sizeof a[0] ?
  1. n, à chaque appel
  2. 8, quelle que soit la valeur de n
  3. 4, à chaque appel
  4. 2, quelle que soit la valeur de n
Afficher la réponseMasquer la réponse
Réponse : D
Le paramètre tableau est ajusté en pointeur : sa taille est donc de 8 octets dans cet environnement. Un élément occupe 4 octets, ce qui donne 2. Ce résultat ne permet pas de retrouver la longueur du tableau de la fonction appelante ; la fonction doit utiliser n, fourni séparément, comme nombre d’éléments.

Question 9 sur 10

Une fonction en lecture seule utilise size_t pour n et i. Elle doit afficher un tableau à rebours et fonctionner pour n = 0. Quels paramètre et boucle satisfont ces deux exigences ?
  1. const int a[] ; commencer i à n - 1, tester i >= 0, accéder à a[i].
  2. int a[] ; commencer i à n, tester i > 0, accéder à a[i].
  3. const int a[] ; commencer i à n, tester i > 0, accéder à a[i - 1].
  4. int a[] ; commencer i à n - 1, tester i > 0, accéder à a[i - 1].
Afficher la réponseMasquer la réponse
Réponse : C
Le paramètre const empêche les écritures par l’intermédiaire de a, tandis que commencer à n évite une soustraction non signée lorsque la plage est vide. L’accès à i - 1 parcourt ensuite les éléments du dernier indice valide jusqu’à zéro. Commencer à n - 1 avec un i non signé et tester i >= 0 provoque un rebouclage et ne fournit jamais de condition d’arrêt.

Question 10 sur 10

Que garantit C après la lecture de a[4] dans int a[4] par un programme ?
  1. Aucun résultat n’est garanti.
  2. La lecture renvoie zéro.
  3. La lecture renvoie a[3].
  4. La lecture provoque toujours un plantage.
Afficher la réponseMasquer la réponse
Réponse : A
Les indices valides du tableau vont de 0 à 3 : cette lecture est donc hors limites et a un comportement indéfini. C n’impose aucun résultat pour cette opération. Un plantage est possible, mais s’y attendre à chaque fois reviendrait à prendre un symptôme possible pour une garantie du langage.
Série 2 : Caractères, fins de chaînes et UTF-810 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quelle valeur numérique produit '6' - '0' ?
  1. 54
  2. 48
  3. 0
  4. 6
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

En ASCII, quel caractère résulte de ('W' - 'A' + 5) % 26 + 'A' ?
  1. 'B'
  2. 'A'
  3. 'C'
  4. '\\'
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Comment faut-il passer un octet c de type char à isalpha sans risquer de fournir un octet négatif comme argument ?
  1. isalpha((signed char) c)
  2. isalpha(c - '0')
  3. isalpha((unsigned char) c)
  4. isalpha((int) c)
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Quelles sont la longueur du texte et la taille du tableau dans char color[] = "amber"; ?
  1. Longueur 6 ; taille 6
  2. Longueur 5 ; taille 6
  3. Longueur 5 ; taille 5
  4. Longueur 6 ; taille 5
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Quelle chaîne reste après char s[8] = "planet"; s[3] = '\0'; s[0] = 'P'; ?
  1. "Pla"
  2. "Planet"
  3. "Pla0et"
  4. "Plan"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Pourquoi char tag[4] = "east"; printf("%s", tag); présente-t-il un risque ?
  1. L’initialiseur contient trop peu de caractères.
  2. Le format n’affiche qu’un seul octet.
  3. Le tableau n’a pas d’octet nul de fin.
  4. Les caractères du tableau sont en lecture seule.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un filtre ne conserve que les lettres de "m8n2p" et les écrit dans un tableau de sortie assez grand. Que doit-il écrire après le dernier p ?
  1. Un octet nul à l’indice de sortie 2
  2. Un chiffre zéro à l’indice de sortie 3
  3. Un octet nul à l’indice de sortie 5
  4. Un octet nul à l’indice de sortie 3
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un programme inverse char s[] = "lamp"; en échangeant s[i] et s[len - i] tant que i < len / 2, où len vaut strlen(s). Quelles sont la valeur finale de strlen(s) et la capacité, qui reste inchangée ?
  1. Longueur 4 ; capacité 5
  2. Longueur 0 ; capacité 5
  3. Longueur 0 ; capacité 4
  4. Longueur 5 ; capacité 5
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

En UTF-8, « é » précomposé utilise deux octets. Que vaut strlen et quel est l’espace minimal nécessaire pour stocker la chaîne « écho » ?
  1. 5 octets de texte ; 6 octets de stockage
  2. 4 octets de texte ; 5 octets de stockage
  3. 5 octets de texte ; 5 octets de stockage
  4. 6 octets de texte ; 7 octets de stockage
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une chaîne UTF-8 valide contient les octets 41 C3 B1 42 00. Un programme écrit zéro à l’indice d’octet 2. Quelles sont la nouvelle valeur de strlen et la validité UTF-8 du texte ?
  1. Longueur 2 ; UTF-8 valide
  2. Longueur 2 ; UTF-8 invalide
  3. Longueur 3 ; UTF-8 valide
  4. Longueur 1 ; UTF-8 invalide
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 3 : Choisir et vérifier les opérations de bibliothèque10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quelle est la capacité minimale d’un tableau de char pour copier entièrement "silver" ?
  1. 7 octets
  2. 6 octets
  3. 8 octets
  4. 5 octets
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

char label[10] = "blue"; strcat(label, "berry"); peut-il stocker le résultat complet ?
  1. Non ; le résultat nécessite 11 octets.
  2. Oui ; le résultat nécessite 9 octets.
  3. Oui ; le résultat nécessite 10 octets.
  4. Non ; le résultat nécessite 12 octets.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Dans une fonction, un tableau local automatique est utilisé ainsi : char out[20]; strcat(out, "go");. Pourquoi est-ce une façon invalide de commencer à construire une chaîne ?
  1. out est trop petit pour le texte ajouté.
  2. out n’a pas de caractère nul de fin établi.
  3. strcat exige un tableau de pointeurs pour out.
  4. strcat ne peut pas copier un littéral de chaîne.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Quelle condition reconnaît l’égalité du texte de deux chaînes valides a et b ?
  1. a == b
  2. strcmp(a, b) > 0
  3. strlen(a) == strlen(b)
  4. strcmp(a, b) == 0
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Après l’exécution réussie de char *p = strrchr("archive.backup.bin", '.');, quel texte commence à p ?
  1. ".bin"
  2. "bin"
  3. ".backup.bin"
  4. "archive.backup"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un tableau modifiable contient "on,,off;wait". Les appels utilisent strtok(s, ",;"), puis répètent strtok(NULL, ",;") jusqu’à NULL. Quels jetons sont produits et s est-il préservé ?
  1. « on », « », « off », « wait » ; s est modifié.
  2. « on », « off;wait » ; s est modifié.
  3. « on », « off », « wait » ; s est modifié.
  4. « on », « off », « wait » ; s est préservé.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Que stocke et que renvoie char b[6]; int r = snprintf(b, sizeof b, "%s:%d", "job", 84); ?
  1. La fonction stocke « job:8 » et renvoie 5.
  2. La fonction stocke « job:84 » et renvoie 6.
  3. La fonction stocke « job: » et renvoie 4.
  4. La fonction stocke « job:8 » et renvoie 6.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un tableau de sept octets contient initialement "AB". Le programme exécute strncat(b, "123456", sizeof b - strlen(b) - 1). Quels sont le texte obtenu et son nombre d’octets stockés, zéro compris ?
  1. « AB12345 » ; 8 octets
  2. « AB1234 » ; 7 octets
  3. « AB123 » ; 6 octets
  4. « AB123456 » ; 9 octets
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Après char s[] = "wxyz"; memmove(s, &s[1], 4);, que contient s en tant que chaîne ?
  1. "xyzz"
  2. "wxy"
  3. "xyz"
  4. "yz"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Deux tableaux de double sont égaux élément par élément, mais l’un stocke un zéro positif là où l’autre stocke un zéro négatif. Que peut établir une comparaison des octets ?
  1. Si leurs représentations stockées correspondent.
  2. Si leurs valeurs numériques sont différentes.
  3. Si l’un contient davantage d’éléments.
  4. Si les deux valeurs sont des zéros positifs.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 4 : Tableaux de données, listes de texte et données au démarrage10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quel est le dernier couple valide de ligne et de colonne pour int table[4][6] ?
  1. Ligne 4, colonne 6
  2. Ligne 3, colonne 5
  3. Ligne 3, colonne 6
  4. Ligne 4, colonne 5
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Lorsque int occupe 4 octets, que vaut sizeof table[0] pour int table[3][5] ?
  1. 12 octets
  2. 15 octets
  3. 60 octets
  4. 20 octets
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Un tableau est {{2, 7, 4}, {6, 1, 5}}. Une boucle initialise sum une seule fois à zéro avant les deux boucles, additionne une ligne à la fois et affiche le résultat après chaque ligne sans remettre sum à zéro. Quelles valeurs sont affichées et comment corriger le calcul ?
  1. 13 puis 25 ; remettre sum à zéro avant chaque ligne.
  2. 13 puis 12 ; remettre sum à zéro avant chaque ligne.
  3. 13 puis 25 ; remettre sum à zéro avant chaque case.
  4. 8 puis 16 ; remettre sum à zéro avant chaque colonne.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Quel paramètre tableau de largeur fixe reçoit des lignes de sept entiers chacune ?
  1. int g[7][]
  2. int g[][]
  3. int g[][7]
  4. int g[][6]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Quelle est la largeur minimale des lignes de char names[3][width] pour stocker « Iris », « Magnolia » et « Ash » comme chaînes ASCII complètes ?
  1. 8 octets
  2. 10 octets
  3. 16 octets
  4. 9 octets
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un programme possède char rows[2][5] = {"oak", "elm"}; et const char *refs[] = {"oak", "elm"};. Il doit remplacer le premier mot de la liste par le texte complet « cedar ». Quel traitement est valide pour chaque forme de stockage ?
  1. Copier « cedar » dans rows[0] ; réaffecter refs[0].
  2. Rejeter la copie dans la ligne ; réaffecter refs[0] à « cedar ».
  3. Rejeter la copie dans la ligne ; copier « cedar » dans refs[0].
  4. Affecter rows[0] = "cedar" ; réaffecter refs[0].
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Dans un interpréteur de commandes ordinaire, un programme est lancé avec ./mark "West Room" 9. Que valent argc et argv[2] ?
  1. argc vaut 3 ; argv[2] vaut « 9 ».
  2. argc vaut 4 ; argv[2] vaut « Room ».
  3. argc vaut 2 ; argv[2] vaut NULL.
  4. argc vaut 3 ; argv[2] vaut « West Room ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un programme nécessite deux arguments utilisateur. Il vérifie argc == 2, puis appelle strlen(argv[2]). Quelle vérification du nombre et quel dernier indice correspondent à son interface réelle ?
  1. Vérifier argc == 2 ; lire les arguments jusqu’à l’indice 2.
  2. Vérifier argc == 3 ; lire les arguments jusqu’à l’indice 3.
  3. Vérifier argc == 3 ; lire les arguments jusqu’à l’indice 2.
  4. Vérifier argc == 2 ; lire les arguments jusqu’à l’indice 1.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Après la conversion décimale de « 42rest » par strtol, qu’indiquent le résultat et le pointeur de fin de conversion ?
  1. Valeur 0 ; aucun caractère n’a été consommé.
  2. Valeur 42 ; le texte non consommé commence par r.
  3. Valeur 42 ; toute l’entrée a été consommée.
  4. Valeur 42 ; une erreur de dépassement de plage a forcément eu lieu.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une clé composée uniquement de chiffres est représentable dans long, mais pas dans int. Le programme la convertit explicitement en int avant de calculer key % 26. Comment peut-il préserver le décalage prévu sans effectuer d’abord cette conversion vers un type plus restreint ?
  1. Convertir d’abord en int, puis calculer le reste.
  2. Utiliser atoi, puis calculer le reste en int.
  3. Calculer le reste en long, puis convertir le résultat de 0 à 25.
  4. Revérifier les chiffres, puis convertir la valeur d’origine.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 5 : Limites de saisie et résultats complets10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quelle est la plus grande largeur %s qui laisse une position pour le caractère nul de fin dans char word[18] ?
  1. %18s
  2. %16s
  3. %17s
  4. %19s
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Un appel réussi à fgets lit l’entrée "pine\n" dans un tableau de 10 octets. Quelles sont la valeur de strlen du résultat et l’indice de son caractère nul de fin ?
  1. Longueur 4 ; indice de fin 4
  2. Longueur 5 ; indice de fin 6
  3. Longueur 6 ; indice de fin 5
  4. Longueur 5 ; indice de fin 5
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

La ligne d’entrée est « qrstuvwxy » suivie d’un saut de ligne. Deux appels à fgets utilisent le même char b[6] sans autre lecture entre eux. Quel texte le second appel stocke-t-il ?
  1. "uvwxy"
  2. "vwxy\n"
  3. "vwxy"
  4. "qrst\n"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un programme autorise 12 caractères de texte ASCII dans un nom saisi comme ligne complète terminée par un saut de ligne. Il doit examiner le saut de ligne, puis stocker uniquement le nom dans un tableau distinct. Quelles capacités minimales faut-il pour l’entrée et le résultat final ?
  1. Entrée : 14 octets ; résultat final : 13 octets
  2. Entrée : 13 octets ; résultat final : 13 octets
  3. Entrée : 14 octets ; résultat final : 12 octets
  4. Entrée : 13 octets ; résultat final : 12 octets
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Un tampon de 9 octets reçoit un résultat réussi de fgets de longueur 8 sans saut de ligne. Aucune donnée supplémentaire n’a été examinée. Que peut-on conclure au sujet de la ligne logique ?
  1. Elle dépasse forcément huit caractères.
  2. Elle peut se terminer là ou avoir une suite en attente.
  3. Elle s’est forcément déjà terminée en fin de fichier.
  4. Son saut de ligne a été lu et retiré par fgets.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Pourquoi counts[c - 'a']++ présente-t-il un risque lorsque le caractère d’entrée n’est pas vérifié ?
  1. L’indice obtenu peut être hors du tableau.
  2. L’incrémentation ne peut pas mettre à jour des compteurs entiers.
  3. La soustraction renvoie toujours une valeur négative.
  4. L’expression compare deux chaînes entières.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un tableau de char de six octets est rempli de lettres aux indices de 0 à 5, puis passé à strlen. Quelle propriété manque-t-il ?
  1. Un octet inutilisé après le tableau pour zéro.
  2. Un saut de ligne explicite après la dernière lettre.
  3. Un caractère nul de fin parmi les six positions valides.
  4. Un entier distinct stockant sa capacité en octets.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un programme stocke un code complet dans char out[6]. L’appel snprintf(out, sizeof out, "%s%d", "R-", 1234) est suivi de if (r > sizeof out) reject();, où r est sa valeur de retour non négative. Que stocke le tampon, le test rejette-t-il le résultat et que faut-il changer ?
  1. « R-1234 » ; accepté ; conserver le test actuel.
  2. « R-123 » ; rejeté ; conserver le test actuel.
  3. « R-12 » ; accepté ; rejeter si r >= capacité.
  4. « R-123 » ; accepté ; rejeter si r >= capacité.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un analyseur décimal rejette ERANGE et exige *end == '\0', mais ne vérifie pas end == start. Quelle entrée invalide peut encore être acceptée comme zéro ?
  1. Une chaîne vide
  2. Un mot alphabétique
  3. Un chiffre puis une lettre
  4. Un nombre hors de la plage de long
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une chaîne UTF-8 valide contient les octets 41 C3 A9 E2 82 AC 00. Un programme la copie dans char b[5], en réservant sa dernière position pour zéro. Quels sont la valeur de strlen, le nombre d’octets de début et la validité de l’encodage obtenus ?
  1. Longueur 4 ; 3 octets de début ; UTF-8 valide.
  2. Longueur 4 ; 3 octets de début ; UTF-8 invalide.
  3. Longueur 3 ; 3 octets de début ; UTF-8 valide.
  4. Longueur 4 ; 2 octets de début ; UTF-8 invalide.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 6 : Suivre et corriger des opérations C combinées10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quel tableau est créé par int a[4] = {[2] = 9}; ?
  1. {0, 9, 0, 0}
  2. {0, 0, 9, 0}
  3. {9, 0, 0, 0}
  4. {0, 0, 0, 9}
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Un tableau de huit positions contient 5 éléments utilisés. Une valeur est ajoutée à a[count], puis count est incrémenté. À quel indice a-t-on écrit et quel est le nouveau nombre d’éléments utilisés ?
  1. Indice 5 ; nombre d’éléments 6
  2. Indice 4 ; nombre d’éléments 6
  3. Indice 6 ; nombre d’éléments 6
  4. Indice 5 ; nombre d’éléments 5
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Pour int g[3][4], quelle est la position de l’élément g[2][1] dans le rangement par lignes, en numérotant les éléments à partir de zéro ?
  1. 7
  2. 8
  3. 10
  4. 9
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un interpréteur de commandes exécute ./pick "" blue. En quoi argv[1] et argv[argc] diffèrent-ils ?
  1. argv[1] est un pointeur nul ; argv[argc] est une chaîne vide.
  2. Les deux entrées sont des chaînes vides avec leur propre caractère nul de fin.
  3. argv[1] est une chaîne vide ; argv[argc] est un pointeur nul.
  4. Les deux entrées sont des pointeurs nuls indiquant l’absence de texte.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Une fonction reçoit int a[], size_t n et exécute a[0] = 0; n = 0;. La fonction appelante a fourni {5, 8, 2} et le nombre d’éléments 3, puis calcule la somme entière de ses éléments divisée par leur nombre. Quels sont la moyenne et le nombre d’éléments obtenus dans la fonction appelante ?
  1. Moyenne 0 ; nombre d’éléments 3
  2. Moyenne 3 ; nombre d’éléments 3
  3. Moyenne 5 ; nombre d’éléments 3
  4. Division indéfinie ; nombre d’éléments 0
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un analyseur découpe le texte modifiable « run,runner » aux virgules avec strtok. Il incrémente un compteur lorsque strncmp(token, "run", 3) == 0. Quel nombre obtient-il, quel nombre une recherche de commande exacte devrait-elle donner et quelle comparaison corrige le problème ?
  1. Actuel : 2 ; exact : 1 ; strcmp(token, "run") == 0.
  2. Actuel : 1 ; exact : 1 ; strcmp(token, "run") == 0.
  3. Actuel : 2 ; exact : 2 ; strncmp(token, "run", 2) == 0.
  4. Actuel : 1 ; exact : 2 ; strstr(token, "run") != NULL.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un tableau b de cinq octets est rempli par strncpy(b, "planet", sizeof b);. Le programme exige le mot d’origine complet. Quelle correction satisfait cette exigence ?
  1. Écrire zéro dans b[4] après la copie.
  2. Ajouter zéro dans b[5] après la copie.
  3. Passer sizeof b - 1, puis utiliser b sans changement.
  4. Rejeter le mot comme trop long avant la copie.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un programme utilise int values[4] = {14, 28, 35, 49};. Il convertit entièrement « 04 » avec strtol en base décimale, accepte les sélections de 1 à 4, puis lit values[selected]. Il doit autoriser les quatre sélections et associer la sélection 1 à la première valeur. Que se passe-t-il et quelle règle d’indexation corrige le problème ?
  1. Il affiche 49 ; conserver l’indice selected.
  2. Il affiche 49 ; utiliser l’indice selected - 1.
  3. Son comportement est indéfini ; utiliser l’indice selected - 1.
  4. Son comportement est indéfini ; exiger une sélection < 4.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Une fonction read_text(char out[], size_t cap) appelle fgets(out, sizeof out, stdin). La fonction appelante passe un tableau de 30 octets ; un pointeur occupe 8 octets. Si « sunflower\n » attend dans l’entrée, quel morceau est stocké, que reste-t-il et par quelle limite remplacer sizeof out ?
  1. « sunflower\n » ; rien ne reste ; utiliser cap.
  2. « sunflowe » ; « r\n » reste ; utiliser cap.
  3. « sunflow » ; « er\n » reste ; utiliser strlen(out).
  4. « sunflow » ; « er\n » reste ; utiliser cap.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Un compteur de suites de lettres ASCII commence en dehors d’un mot et s’incrémente chaque fois qu’une lettre suit un caractère qui n’est pas une lettre. Combien de mots compte-t-il dans « go2fast now! » ?
  1. 3
  2. 2
  3. 4
  4. 1
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Tu bloques sur ton propre exercice ? Aide aux Devoirs

Mots-Clés

85 Mots-Clés, chacun avec sa définition

A

Accès hors limites
Un accès hors limites lit ou écrit à une position repérée par un indice en dehors du tableau ou de la ligne effectivement utilisé ; son comportement est indéfini.
Accéder à a[8] dans un tableau de huit éléments est invalide, même si une exécution de test semble renvoyer une valeur utile.
Accumulateur
Un accumulateur est une variable qui recueille un résultat au fur et à mesure, comme une somme ou un comptage, pendant qu’une boucle traite des valeurs successives.
Initialiser sum à zéro permet à chaque sum += a[i] d’ajouter l’élément suivant du tableau au total courant.
argc
Le paramètre argc donne le nombre de chaînes d’arguments fournies à main, y compris normalement la chaîne utilisée pour lancer le programme.
L’exécution de ./label red blue dans un interpréteur ordinaire donne argc égal à 3 : le nom de lancement et deux couleurs.
Argument de ligne de commande
Un argument de ligne de commande est une chaîne fournie au démarrage d’un programme, souvent regroupée ou développée par un interpréteur de commandes avant d’être reçue.
Placer « North Hall » entre guillemets dans la ligne de commande peut fournir un seul argument contenant un espace au lieu de deux mots.
argv
Le paramètre argv donne accès aux chaînes d’arguments par indice ; elles sont suivies d’un pointeur nul à la position indiquée par argc.
Après avoir vérifié argc, un programme peut utiliser strcmp(argv[1], "-v") pour reconnaître sa première option.
ASCII
ASCII est un encodage des caractères qui attribue les valeurs de 0 à 127 aux lettres de base, aux chiffres, à la ponctuation et aux caractères de contrôle.
Le calcul '8' - '0' produit 8, car les codes des caractères chiffres sont consécutifs.
atoi
La fonction atoi convertit une partie numérique initiale en int sans signaler les erreurs de façon fiable et a un comportement indéfini en cas de débordement.
L’entrée « 18x » produit 18 avec atoi : un nombre renvoyé ne prouve donc pas que toute l’entrée était numérique.

B

Boucles imbriquées
Les boucles imbriquées placent une boucle à l’intérieur d’une autre afin que la boucle interne se répète pour chaque valeur de la boucle externe, par exemple pour les colonnes de chaque ligne.
Un parcours de deux lignes et cinq colonnes exécute le corps de la boucle interne dix fois lorsque les deux indices restent dans leurs bornes.

C

Capacité
La capacité d’un tableau est le nombre d’éléments que son espace de stockage alloué peut contenir, quel que soit le nombre d’éléments qui contiennent actuellement des valeurs utiles.
Un tableau de capacité 80 dont 29 éléments sont utilisés peut accueillir 51 valeurs supplémentaires si ce nombre est correctement tenu à jour.
Caractère nul de fin de chaîne
Un caractère nul de fin de chaîne est le caractère de valeur zéro qui marque la fin d’une chaîne C ; il occupe de l’espace de stockage sans augmenter la longueur du texte.
Écrire text[2] = '\0' amène les fonctions de manipulation des chaînes à s’arrêter après les deux premiers caractères de ce tableau.
Chaîne de caractères C
Une chaîne de caractères C est une suite de caractères qui se termine à un caractère nul, le texte étant stocké dans un tableau plutôt que dans un type de chaîne intégré distinct.
Le tableau initialisé par char pet[] = "dog" contient trois lettres suivies d’un caractère de valeur zéro.
Chaîne vide
Une chaîne vide ne contient aucun caractère de texte et est représentée par un caractère nul de fin à sa première position, ce qui lui donne une longueur nulle.
char message[20] = "" fournit une destination vide valide pour un ajout ultérieur qui respecte sa capacité.
Classification des caractères
La classification des caractères teste l’appartenance d’un code de caractère à une catégorie, comme les chiffres, les lettres ou les caractères blancs, à l’aide des fonctions de <ctype.h>.
isdigit((unsigned char) c) donne un résultat non nul lorsque l’octet stocké représente un chiffre décimal.
Code de retour
Un code de retour indique à l’environnement appelant comment le programme s’est terminé ; renvoyer zéro depuis main signale une exécution réussie.
Un argument obligatoire manquant peut amener un programme à afficher des informations d’utilisation et à renvoyer un code d’échec non nul.
Colonne
Une colonne regroupe les éléments situés à la même position dans les lignes d’un tableau ; son indice est le second indice dans g[r][c].
Pour calculer la somme de la colonne 2, garde c égal à 2 et fais varier r sur toutes les lignes en lisant g[r][c].
Comparaison lexicographique des octets
Une comparaison lexicographique des octets classe les chaînes selon les valeurs non signées des octets stockés, ce qui peut différer des conventions alphabétiques d’une langue.
En UTF-8, strcmp place une lettre latine accentuée après le z ASCII, car son octet de début a une valeur plus élevée.
Comportement indéfini
Un comportement indéfini signifie que la norme C n’impose aucune exigence sur le résultat d’une opération : aucun résultat particulier n’est donc garanti.
Une écriture invalide dans un tableau peut sembler sans effet dans une version compilée et provoquer un plantage ou corrompre des données dans une autre.
Concaténation
La concaténation joint des séquences de texte dans l’ordre et nécessite assez de place dans la destination pour le texte combiné et son caractère nul de fin.
Joindre « north » et « east » forme « northeast », qui nécessite dix octets comme chaîne ASCII terminée par un caractère nul.
Constante caractère
Une constante caractère est une expression C entre apostrophes, de type int, qui représente un code de caractère, par exemple celui d’une lettre.
Avec les codes ASCII, printf("%c %d", 'B', 'B') affiche la lettre B et la valeur numérique 66.
Conversion numérique
Une conversion numérique interprète du texte comme un nombre et nécessite des vérifications distinctes de la forme acceptée, du texte consommé et de la plage de valeurs autorisée.
Les octets « 27 » doivent être convertis avant qu’un programme puisse réduire la valeur numérique avec % 26.

D

Débordement de tampon
Un débordement de tampon est une écriture au-delà de l’espace de stockage disponible d’un tampon, qui peut corrompre des données voisines ou des informations de contrôle du programme.
Copier six octets de texte et un caractère nul de fin dans un tableau de six octets dépasse ce tableau d’un octet.
Décalage de César
Un décalage de César remplace chaque lettre par une autre située à un nombre fixe de positions dans l’alphabet, en revenant au début de sa plage de lettres si nécessaire.
Dans un texte ASCII, décaler le Y majuscule de deux positions donne A en revenant au début, tandis qu’un chiffre ou une virgule peut rester inchangé.
Découpage en jetons
Le découpage en jetons divise un texte en morceaux séparés par des délimiteurs ; strtok le fait en modifiant l’entrée et en mémorisant une position.
Un second appel à strtok(NULL, ",") poursuit le découpage de la même entrée modifiable au lieu de le recommencer.
Délimiteur
Un délimiteur est un caractère utilisé pour séparer des parties d’un texte, comme la virgule ou l’espace fournis à une fonction de découpage en jetons.
Avec la virgule et l’espace comme délimiteurs, le texte « one, two » peut être découpé en jetons « one » et « two ».

É

Élément
Un élément est une valeur stockée dans un tableau, de même type déclaré que les autres valeurs et possédant sa propre position repérée par un indice.
Dans int a[3] = {8, 1, 6}, l’élément a[1] vaut 1 et peut recevoir un autre entier.

E

Encodage des caractères
Un encodage des caractères définit une correspondance entre le texte et sa représentation numérique stockée, notamment les octets utilisés pour sa transmission ou son stockage.
Une chaîne C contenant le même mot visible peut nécessiter des nombres d’octets différents selon l’encodage.
ERANGE
La macro ERANGE désigne une erreur de dépassement de plage signalée par errno, comme un résultat de strtol trop grand ou trop petit pour long.
Mets errno à zéro avant la conversion, puis vérifie s’il vaut ERANGE avant d’accepter une longue suite de chiffres.
Erreur de décalage d’une unité
Une erreur de décalage d’une unité utilise une borne trop éloignée ou trop courte d’une position, souvent parce que le nombre d’éléments est confondu avec le dernier indice valide.
La condition i <= n amène un parcours de n éléments commençant à zéro à tenter un accès supplémentaire à l’indice n.

F

fgets
La fonction fgets lit une ligne dans une limite de taille, conserve le saut de ligne si elle l’atteint et ajoute un caractère nul de fin lorsqu’elle lit du texte avec succès.
Un tampon de huit octets peut recevoir au plus sept caractères d’entrée, laissant le texte supplémentaire de la ligne pour les lectures suivantes.
Filtrage
Le filtrage construit un résultat à partir de caractères d’entrée sélectionnés, en utilisant une position d’écriture distincte, car les caractères rejetés n’occupent aucune place dans la sortie.
Ne conserver que les lettres de « q2r7 » écrit « qr » dans la sortie, puis ajoute son octet nul de fin.
Fin de fichier
La fin de fichier indique qu’aucune autre donnée d’entrée n’est disponible ; fgets peut tout de même réussir si elle a lu des caractères avant d’atteindre cet état.
Un fichier qui se termine par « done » sans saut de ligne permet tout de même à un tampon fgets suffisamment grand de recevoir ce texte final.
Frontière de mot
Une frontière de mot est la transition utilisée par un programme pour déterminer où un mot commence ou se termine, selon la définition du mot qu’il a choisie.
Un compteur de suites de lettres commence un nouveau mot lorsqu’il rencontre une lettre après un espace, un signe de ponctuation ou au début de la chaîne.

I

Indice
Un indice est une position entière utilisée pour sélectionner un élément d’un tableau ; les indices commencent à zéro et se terminent au nombre d’éléments moins un.
Pour un tableau de sept éléments, l’indice 6 accède au dernier élément ; l’indice 7 est déjà hors du tableau.
Initialiseur
Un initialiseur fournit des valeurs initiales lors de la déclaration d’un objet ; les valeurs manquantes dans l’initialiseur d’un tableau deviennent nulles.
int hits[4] = {3} initialise le premier compteur à 3 et les trois autres à zéro.

L

Largeur de champ
Une largeur de champ dans une conversion %s limite le nombre de caractères d’entrée stockés avant l’octet nul de fin supplémentaire.
Pour char word[10], la conversion %9s réserve le dixième octet disponible au caractère nul de fin.
Largeur de ligne
La largeur de ligne est le nombre d’éléments dans chaque tableau interne ; elle est nécessaire dans un paramètre représentant un tableau à plusieurs dimensions pour localiser les éléments par leurs indices.
Le paramètre int g[][6] accepte des lignes de six entiers, tandis que la fonction appelante fournit le nombre de lignes séparément.
Ligne
Une ligne est un tableau interne d’un tableau à deux dimensions, qui contient un nombre fixe d’éléments consécutifs de même type.
Dans int table[2][5], table[1] désigne la seconde ligne, qui contient cinq positions d’entiers.
Ligne partielle
Une ligne partielle est la partie lue avant que la limite de taille d’un tampon n’arrête la lecture, laissant éventuellement une suite non lue de cette ligne logique.
Une longue réponse peut arriver en deux morceaux lus par fgets : le second ne doit donc pas devenir une nouvelle réponse.
Liste de chaînes de capacité fixe
Une liste de chaînes de capacité fixe stocke le texte dans les lignes d’un tableau de char à 2 dimensions, chaque ligne réservant sa propre capacité fixe et de la place pour le caractère nul de fin.
Dans char labels[5][12], chaque étiquette dispose de douze octets de stockage, même si son texte actuel est plus court.
Littéral de chaîne de caractères
Un littéral de chaîne de caractères est un texte entre guillemets doubles qui fournit un tableau de caractères terminé par un caractère nul et dont le programme en cours d’exécution ne doit pas modifier le contenu.
const char *label = "ready" désigne un littéral ; une copie modifiable peut être créée avec char label[] = "ready".
Locale
Une locale fournit des conventions utilisées par les fonctions de bibliothèque ; la locale « C » par défaut fournit ses règles de base à la classification sur un seul octet.
La fonction toupper appliquée aux octets dans la locale « C » ne convertit pas une lettre accentuée UTF-8 complète en sa majuscule.
Longueur de chaîne
Une longueur de chaîne est le nombre d’octets de texte avant le premier caractère nul, sans compter ce caractère ni la capacité inutilisée.
Un tableau de 40 octets contenant « June » a une longueur de 4, même si son espace de stockage disponible reste de 40 octets.

M

Masque de bits
Un masque de bits sélectionne certaines positions de bits pour les tester ; une opération ET ne conserve que les bits d’entrée marqués par des uns dans le masque.
Le masque 0xC0 conserve les deux bits de poids fort pour permettre à un programme de reconnaître la configuration d’un octet de continuation UTF-8.
memcmp
La fonction memcmp compare un nombre fixe d’octets et indique leur ordre, en testant les représentations stockées plutôt que les valeurs numériques.
Le zéro positif et le zéro négatif à virgule flottante peuvent être égaux comme valeurs alors que memcmp trouve des octets stockés différents.
memcpy
La fonction memcpy copie exactement le nombre d’octets demandé entre des zones qui ne se chevauchent pas, sans interpréter les caractères nuls de fin de chaîne.
memcpy(b, a, sizeof a) copie tout l’espace de stockage du tableau a lorsque b a assez de place et constitue une zone distincte.
memmove
La fonction memmove copie un nombre d’octets demandé avec un comportement défini même lorsque les zones source et destination se chevauchent.
Déplacer trois octets dans un même tableau de caractères nécessite une opération qui autorise le chevauchement, comme memmove.
memset
La fonction memset remplit une zone en répétant une valeur d’octet, sans affecter séparément cette valeur numérique à chaque élément du tableau.
memset(counts, 0, sizeof counts) met à zéro un tableau d’entiers ; l’octet de valeur 1 n’affecterait pas la valeur entière 1.

N

Nombre d’affectations réussies
Le nombre d’affectations réussies est le nombre d’affectations d’entrée que scanf a effectuées avec succès ; il permet de vérifier que les données demandées ont bien été lues.
Une lecture d’un seul nombre attend une valeur de retour de 1 ; un échec de correspondance peut laisser les mêmes octets invalides en attente dans l’entrée.
Nombre d’éléments utilisés
Le nombre d’éléments utilisés indique combien d’éléments du tableau appartiennent actuellement aux données actives et détermine la borne de la boucle de traitement.
Si seulement 12 entrées ont été remplies dans un tableau de 50 éléments, une boucle de traitement des données s’arrête au nombre d’éléments utilisés, soit 12.

O

Octet de continuation
Un octet de continuation UTF-8 commence par la configuration de bits 10 et suit un octet de début dans un point de code encodé sur plusieurs octets.
L’octet 0xA9 poursuit la séquence de « é » ; il ne doit pas être conservé seul comme caractère UTF-8 complet.

P

Paramètre de type variablement modifié
Un paramètre de type variablement modifié utilise des paramètres de taille précédents dans son type tableau afin qu’une fonction puisse recevoir des tableaux dont les lignes ont des largeurs différentes.
GCC et Clang acceptent int g[rows][cols] après des paramètres définissant des nombres de lignes et de colonnes positifs et correspondants.
Paramètre qualifié const
Un paramètre qualifié const empêche de modifier les éléments désignés par son intermédiaire, tout en permettant de les lire.
Une fonction de calcul de total utilise const int a[], car additionner les valeurs d’entrée ne nécessite pas de les modifier.
Paramètre tableau
Un paramètre tableau est ajusté en paramètre pointeur, ce qui donne à une fonction accès aux éléments de la fonction appelante sans leur nombre.
Une fonction déclarée avec int a[] a toujours besoin d’une longueur distincte avant de pouvoir parcourir son entrée.
Plage de valeurs autorisée par l’application
Une plage de valeurs autorisée par l’application est l’intervalle de valeurs qu’un programme permet pour un usage donné ; elle peut être plus restreinte que la plage complète du type numérique.
Un nombre d’éléments converti de 120 est représentable dans un entier, mais ne respecte pas une règle de programme qui exige un nombre de 1 à 100.
Point de code Unicode
Un point de code Unicode est une position numérotée dans l’espace de codes Unicode, utilisée pour identifier des caractères et d’autres valeurs textuelles attribuées.
La lettre précomposée « é » est U+00E9, même si son stockage en UTF-8 se compose de deux octets distincts.
Pointeur de fin de conversion
Un pointeur de fin de conversion indique où une conversion numérique s’est arrêtée, ce qui permet à un programme de détecter une absence de conversion ou des caractères restants indésirables.
Pour l’entrée « 9z », strtol renvoie 9, mais le pointeur de fin de conversion désigne le z qui n’a pas été consommé.
Pointeur nul
Un pointeur nul est une valeur de pointeur qui ne désigne aucun objet ; les fonctions de recherche l’utilisent pour signaler qu’aucun emplacement correspondant n’existe.
Vérifie strchr(name, '.') != NULL avant d’utiliser le résultat comme début d’une partie finale de nom de fichier.

R

Rangement par lignes
Le rangement par lignes stocke tous les éléments d’une ligne à la suite avant ceux de la ligne suivante, comme l’exige C pour les tableaux à plusieurs dimensions.
Dans le stockage d’un tableau à quatre colonnes, l’élément qui suit grid[0][3] est grid[1][0].
Rebouclage des entiers non signés
Le rebouclage des entiers non signés réduit un résultat arithmétique non signé modulo l’étendue de son type : soustraire un à zéro donne ainsi une grande valeur.
Un compte à rebours de type size_t ne peut pas s’arrêter en devenant négatif ; utilise i > 0 et accède à la position i - 1.
Recherche séquentielle
Une recherche séquentielle examine les éléments dans l’ordre jusqu’à trouver la valeur recherchée ou avoir vérifié tous les candidats sans correspondance.
La recherche de 2 dans {3, 8, 2} réussit à l’indice 2 après vérification des éléments précédents, qui sont différents.

S

Séquence d’échappement
Une séquence d’échappement est une écriture dans le code source fondée sur une barre oblique inverse, utilisée pour un caractère qui nécessite une notation spéciale, comme un saut de ligne ou un guillemet.
Le littéral "A\nB" contient un saut de ligne entre ses lettres ; la barre oblique inverse et n encodent un seul caractère.
size_t
Le type size_t est un type entier non signé utilisé pour les tailles d’objets et renvoyé par sizeof ; il est couramment utilisé pour les longueurs de tableaux.
printf("%zu", sizeof data) utilise le format des tailles pour afficher le nombre d’octets occupés par data.
snprintf
La fonction snprintf formate du texte dans une capacité fournie et renvoie la longueur complète du texte nécessaire ou un résultat négatif en cas d’erreur.
Une valeur de retour de 12 pour une capacité de 10 signifie que le résultat stocké a été tronqué, même s’il reste terminé par un caractère nul.
Sous-chaîne
Une sous-chaîne est une suite consécutive de caractères dans une autre chaîne ; strstr trouve le premier emplacement où elle commence.
Rechercher « green » dans « blue-green » renvoie un emplacement à partir duquel la chaîne restante est « green ».
strcat
La fonction strcat ajoute une chaîne source à l’emplacement du caractère nul de fin existant de la destination, puis écrit un nouveau caractère nul après le texte combiné.
Ajouter « box » à « red » nécessite huit octets de stockage dans la destination, octet nul final compris.
strchr
La fonction strchr trouve le premier caractère correspondant dans une chaîne et renvoie son emplacement, ou un pointeur nul s’il n’y a pas de correspondance.
Rechercher un point dans « name.part.ext » avec strchr trouve la partie finale « .part.ext », premier point compris.
strcmp
La fonction strcmp compare des chaînes terminées par un caractère nul comme des octets non signés et renvoie un résultat négatif, nul ou positif selon leur ordre.
strcmp("oak", "oak") == 0 teste l’égalité des contenus même lorsque les deux chaînes occupent des espaces de stockage distincts.
strcpy
La fonction strcpy copie une chaîne source complète et son caractère nul de fin dans une destination suffisamment grande qui ne chevauche pas la source.
Copier « pine » écrit cinq octets, zéro compris : la chaîne tient donc dans une destination déclarée avec char out[5].
strcspn
La fonction strcspn mesure la partie initiale d’une chaîne qui ne contient aucun des caractères fournis dans son second argument.
strcspn("fir:oak", ":,") renvoie 3, car le premier séparateur indiqué apparaît après les trois lettres de fir.
strlen
La fonction strlen parcourt une chaîne valide jusqu’à son caractère nul de fin et renvoie le nombre d’octets qui le précèdent sous forme d’une valeur size_t.
Pour char tag[30] = "oak", strlen(tag) vaut 3, tandis que sizeof tag indique la capacité totale de 30 octets.
strncat
La fonction strncat ajoute au plus un nombre indiqué d’octets de texte source, puis écrit un caractère nul de fin à leur suite.
Pour une chaîne de destination valide, l’espace restant pour le texte est la capacité moins sa longueur actuelle moins un.
strncmp
La fonction strncmp compare au plus un nombre indiqué d’octets de chaînes et s’arrête plus tôt si elle rencontre une fin ou une différence.
Une correspondance de trois octets entre « run-fast » et « run-slow » établit un préfixe commun, mais pas l’égalité des chaînes complètes.
strncpy
La fonction strncpy copie jusqu’à une limite et complète un texte plus court avec des zéros, mais n’ajoute pas de caractère nul de fin lorsque la source atteint cette limite.
Copier « abcd » avec une limite de 3 stocke a, b et c sans octet nul : une autre étape doit donc terminer le résultat.
strrchr
La fonction strrchr trouve le dernier caractère correspondant dans une chaîne et renvoie son emplacement, ou un pointeur nul s’il n’y a pas de correspondance.
Le dernier point dans « name.part.ext » commence « .ext » : strrchr peut donc localiser le séparateur de l’extension.
strtol
La fonction strtol convertit du texte en long selon une base choisie et fournit l’emplacement où elle s’est arrêtée ainsi que des informations sur les erreurs de dépassement de plage.
L’appel strtol(text, &end, 10) permet au programme de rejeter une lettre restante après des chiffres décimaux par ailleurs valides.

T

Tableau
Un tableau est une suite de taille fixe composée d’éléments voisins de même type, auxquels on accède par un nom commun et un indice entier.
int levels[6] réserve six entiers ; modifier levels[2] change la troisième valeur stockée.
Tableau à deux dimensions
Un tableau à deux dimensions est un tableau de lignes de même largeur, elles-mêmes des tableaux ; deux indices sélectionnent un élément par sa ligne et sa colonne.
int board[4][6] fournit 24 entiers, accessibles par quatre indices de ligne valides et six indices de colonne valides.
Tableau de compteurs
Un tableau de compteurs stocke un compteur par catégorie et utilise une valeur de catégorie validée pour sélectionner le compteur à incrémenter.
Après conversion d’un chiffre en la valeur 4, counts[4]++ ajoute une occurrence à son compteur.
Tableau de longueur variable
Un tableau de longueur variable reçoit sa taille lors de l’exécution de sa déclaration et la conserve jusqu’à la fin de sa durée de vie.
En C17, une déclaration locale const int n = 6; int a[n]; crée un tableau de longueur variable, car n n’est pas une expression constante.
Tableau de pointeurs vers des chaînes
Un tableau de pointeurs vers des chaînes stocke une référence par chaîne, ce qui permet aux textes stockés ailleurs d’avoir des longueurs différentes.
const char *names[] = {"Al", "Mina"} stocke deux références et permet d’en remplacer une.
Tableau de sortie
Un tableau de sortie est un espace de stockage fourni par une fonction appelante pour qu’une fonction y place plusieurs résultats, avec une capacité ou un nombre d’éléments convenu.
Une fonction qui calcule des carrés peut écrire chaque résultat dans out[i], tandis que la fonction appelante conserve la propriété du tableau.
Tampon
Un tampon est une zone de stockage réservée aux données en cours de lecture, d’écriture ou de transformation, dont la capacité limite les écritures valides.
Un tampon de nom de 32 octets peut contenir trente caractères de texte ASCII, un saut de ligne conservé et un octet nul final.
Transformation en place
Une transformation en place modifie les valeurs dans leur espace de stockage existant au lieu de construire un tableau de sortie distinct.
La conversion en majuscules d’une chaîne ASCII modifiable peut réaffecter chaque caractère converti à la même position repérée par son indice.
Troncature
La troncature est la perte du texte qui dépasse une limite de longueur disponible ; elle peut éviter un débordement tout en changeant le sens des données.
Une étiquette de fichier raccourcie peut désigner un texte différent : une interface exigeant un nom complet devrait donc rejeter un résultat tronqué.

U

UTF-8
UTF-8 est un encodage Unicode qui stocke chaque valeur scalaire sur un à quatre octets et préserve les encodages ASCII sur un octet.
La chaîne « café » occupe cinq octets de texte UTF-8, plus un octet nul lorsqu’elle est stockée comme chaîne C.

À propos de cette unité

Par StudeliSignaler une erreur

Crée ton propre Matériel d'Étude

Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.

Commencer