- Apprendre
- Informatique et numérique
- Programmation
- Langage C : pointeurs, mémoire et structures
- Tableaux et chaînes de caractères en C
Tableaux et chaînes de caractères en C
DébutantUnité 3 sur 8 de la formation Formation : Langage C : pointeurs, mémoire et structures
Ce que tu vas apprendre
- 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 indiceCré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 limitesParcours 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.
- Déclarer et initialiser un tableau, puis accéder à ses éléments par indice
- Traite les caractères comme de petits codes entiers, stocke le texte dans des tableaux de
charterminé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ériquesUtilise le type
charet 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 nulExplique 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èreParcours 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 charRelie 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.
- Traiter les caractères comme des codes numériques
- 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înesUtilise correctement
strlen,strcpyetstrcatet détermine l’espace nécessaire pour chaque destination. - Comparer des chaînes et y effectuer des recherchesCompare des chaînes avec
strcmpetstrncmp, 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émoireUtilise correctement les fonctions à taille limitée
strncpy,strncatetsnprintf, détecte les troncatures, puis copie, remplis et compare des tableaux entiers avec les fonctions de manipulation de la mémoire.
- Mesurer, copier et concaténer des chaînes
- 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 dimensionsDé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.
- Déclarer et parcourir des tableaux à deux dimensions
- Lis les mots saisis après le nom d’un programme à l’aide de
argcetargv, vérifie leur nombre et convertis-les en nombres et en options en toute sécurité.- Lire argc et argvDéclare
mainavec ses deux paramètres, décris ce que contient chaque élément deargvet vérifie le nombre d’arguments avant d’en utiliser un. - Convertir et valider les arguments numériquesConvertis 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.
- Lire argc et argv
- 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 effetsExplique 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 tamponsLis 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.
- Reconnaître les accès hors limites et leurs effets
Tableaux et chaînes de caractères en C : cours
1Stocker 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ùaest 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
constpour 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 depuisnet accède ài - 1.
2Repré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 C | Caractè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.
\0est un caractère de valeur zéro, et non le chiffre0.- 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 charavant 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éclaration | Emplacement du texte | Ses caractères peuvent-ils changer ? |
|---|---|---|
char a[] = "hello"; | Une copie dans le tableau a | Oui |
const char *p = "hello"; | Un littéral de chaîne de caractères désigné par p | Non |
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
strlencompte 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.
3Utiliser 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
strlenmesure le texte actuel ;sizeofappliqué à 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) == 0pour 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.
strcspnrenvoie une longueur de préfixe ;strtokmodifie 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
strncpypeut omettre le caractère nul de fin ;strncatnécessite de la place pour en ajouter un nouveau.snprintfrenvoie 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
memmovepour les zones qui se chevauchent. memsetremplit des octets ;memcmpcompare des représentations.
4Organiser 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.
5Traiter 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
argccompte 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.
atoine peut pas distinguer un zéro valide d’un échec de conversion.- Vérifie que
strtola lu quelque chose et consommé tout le texte requis. - Remets
errnoà zéro, vérifieERANGE, 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.
6Pré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.
fgetsne 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
1Suivre un tableau de sa déclaration à l’appel d’une fonction
13 étapes
- 1IntroductionDonner 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.
- 2ExempleLire 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.
- 3ExplicationCompter 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
intoccupe 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_test le type non signé utilisé pour ce résultat de taille. - 4Dé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. - 5ExempleConstruire 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.
- 6Point cléConserver la partie fractionnaire d’une moyenne
Pour ces quatre mesures,
(double) sum / ndonne 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 / 4produirait 15, tandis quesum / 4.0produirait 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. - 7ConseilChoisir une valeur initiale valide
Une recherche de maximum nécessite une valeur initiale tirée d’un tableau non vide. Pour
{-6, -2, -9}, initialisemaxà -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.
- 8Dé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.
- 9LienPlacer 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.
constempê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ù
readingsest déclaré et appellemean(readings, n). Dans mean,sizeof amesure un paramètre pointeur au lieu du tableau de quatre éléments de la fonction appelante. - 10ExempleTraiter 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.
- 11DéfiExpliquer la modification du tableau de la fonction appelante
Une autre fonction reçoit
int a[], size_t net met à zéro chaquea[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. - 12Dé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.
- 13Ré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.
2Transformer les octets stockés par des opérations sur le texte
16 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionObserver à la fois le texte et son stockage
- 2ExplicationLire un caractère comme un code
- 3DéfiRevenir au début de l’alphabet
- 4ExempleConstruire une chaîne modifiable
- 5Point cléDéplacer la fin sans déplacer le stockage
- 6DéfiLaisser une position pour la fin
- 7ExempleSéparer la lecture de l’écriture
- 8ExempleTerminer la nouvelle chaîne
- 9DéfiInverser les lettres sans le caractère nul de fin
- 10ConseilClasser les octets avec des arguments valides
- 11ExempleReprésenter une lettre accentuée en UTF-8
- 12ExplicationReconnaître les octets de continuation
- 13DéfiMesurer un nouveau mot encodé
- 14LienChoisir des opérations qui gardent les caractères entiers
- 15DéfiExaminer un raccourci proposé pour le texte
- 16RécapitulatifRepérer la fin et les frontières des caractères
3Assembler, rechercher et formater du texte en toute sécurité
14 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionIdentifier les règles de chaque fonction
- 2ExempleCommencer par une copie complète
- 3ExempleAjouter du texte à la fin existante
- 4DéfiDéterminer si un autre ajout peut tenir
- 5ExplicationUtiliser zéro pour reconnaître des textes égaux
- 6ExempleLire à partir d’un emplacement trouvé
- 7DéfiExaminer une vérification de commande fondée sur un préfixe
- 8ConseilPrévoir que le découpage en jetons modifie le texte
- 9ExempleFormater dans une capacité connue
- 10DéfiInterpréter le même format avec moins d’espace
- 11Point cléUne limite peut compter les octets de la source
- 12ExempleDéplacer une zone qui se chevauche avec sa destination
- 13DéfiConserver un résultat complet après un décalage
- 14RécapitulatifDistinguer les octets des résultats textuels
4Lire un tableau et choisir comment stocker une liste de chaînes
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDonner deux indices à chaque position
- 2ExemplePlacer les valeurs dans des lignes
- 3ExempleRéinitialiser la somme au début de chaque ligne
- 4DéfiChanger le regroupement en conservant les indices
- 5ExplicationIndiquer la largeur des lignes à une fonction
- 6ExempleRéserver une chaîne terminée par un caractère nul par ligne
- 7Point cléUtiliser des références pour des chaînes de longueurs différentes
- 8DéfiRemplacer le texte dans l’espace approprié
- 9DéfiMaintenir les deux dimensions valides dans une fonction
- 10RécapitulatifGarder visible la forme du tableau
5Valider une sélection en ligne de commande
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionRecevoir le texte avant de l’interpréter
- 2ExempleAssocier une commande de l’interpréteur à ses entrées
- 3ExplicationVérifier le nombre d’arguments avant la conversion
- 4DéfiRegrouper correctement un nom
- 5ConseilUn entier renvoyé ne suffit pas
- 6ExempleExaminer une conversion complète
- 7ExplicationVérifier la plage propre à la sélection
- 8DéfiRepérer un texte partiellement numérique
- 9Point cléDistinguer les règles de forme et de valeur
- 10DéfiCombiner le regroupement et la validation numérique
- 11RécapitulatifVérifier la présence, la conversion et l’usage
6Corriger une procédure de saisie à taille limitée
13 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLimiter l’écriture et vérifier le résultat
- 2ExempleTrouver l’écriture supplémentaire
- 3Point cléUtiliser la dernière position valide pour la fin
- 4DéfiVérifier un indice déduit d’un octet
- 5ExplicationLire un mot en laissant de la place pour le caractère nul de fin
- 6ExempleLire un morceau de ligne de taille limitée
- 7ExempleObserver où une longue ligne est coupée
- 8ConseilExaminer un saut de ligne avant de le supprimer
- 9DéfiPrévoir l’espace pour une ligne complète
- 10ExempleVérifier une copie avant d’écrire
- 11DéfiDistinguer un préfixe sûr d’une réponse acceptée
- 12LienUtiliser les diagnostics et raisonner sur les bornes
- 13RécapitulatifDistinguer quatre vérifications
Tableaux et chaînes de caractères en C : QCM
Série 1 : Valeurs des tableaux, boucles et appels de fonctions10 Questions Pratiques
Question 1 sur 10
a[3] après int a[5] = {6, 9}; ?Afficher la réponseMasquer la réponse
Question 2 sur 10
int a[7]; et int occupe 4 octets. Quel couple donne sizeof a et le dernier indice valide ?Afficher la réponseMasquer la réponse
Question 3 sur 10
int a[] = {-12, -4, -9};, quelle valeur une recherche de maximum doit-elle renvoyer ?Afficher la réponseMasquer la réponse
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);
Afficher la réponseMasquer la réponse
Question 5 sur 10
{2, 9, 7, 4} renvoie -1 dès le premier élément différent. À quel moment doit-elle renvoyer une valeur d’échec ?Afficher la réponseMasquer la réponse
Question 6 sur 10
a[i] et a[5 - 1 - i] pour i = 0 et i = 1, à partir de {4, 7, 1, 8, 6} ?Afficher la réponseMasquer la réponse
Question 7 sur 10
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 ?Afficher la réponseMasquer la réponse
Question 8 sur 10
void f(int a[], size_t n), les pointeurs occupent 8 octets et les entiers 4 octets. Que vaut sizeof a / sizeof a[0] ?Afficher la réponseMasquer la réponse
Question 9 sur 10
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 ?Afficher la réponseMasquer la réponse
Question 10 sur 10
a[4] dans int a[4] par un programme ?Afficher la réponseMasquer la réponse
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
'6' - '0' ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
('W' - 'A' + 5) % 26 + 'A' ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
c de type char à isalpha sans risquer de fournir un octet négatif comme argument ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
char color[] = "amber"; ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
char s[8] = "planet"; s[3] = '\0'; s[0] = 'P'; ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
char tag[4] = "east"; printf("%s", tag); présente-t-il un risque ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
"m8n2p" et les écrit dans un tableau de sortie assez grand. Que doit-il écrire après le dernier p ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
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 ?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
"silver" ?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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
char out[20]; strcat(out, "go");. Pourquoi est-ce une façon invalide de commencer à construire une chaîne ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
char *p = strrchr("archive.backup.bin", '.');, quel texte commence à p ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
"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é ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
char b[6]; int r = snprintf(b, sizeof b, "%s:%d", "job", 84); ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
"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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
char s[] = "wxyz"; memmove(s, &s[1], 4);, que contient s en tant que chaîne ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
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
int table[4][6] ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
sizeof table[0] pour int table[3][5] ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
{{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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
char names[3][width] pour stocker « Iris », « Magnolia » et « Ash » comme chaînes ASCII complètes ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
./mark "West Room" 9. Que valent argc et argv[2] ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
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
char word[18] ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
"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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
char b[6] sans autre lecture entre eux. Quel texte le second appel stocke-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
counts[c - 'a']++ présente-t-il un risque lorsque le caractère d’entrée n’est pas vérifié ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
ERANGE et exige *end == '\0', mais ne vérifie pas end == start. Quelle entrée invalide peut encore être acceptée comme zéro ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
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 ?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
int a[4] = {[2] = 9}; ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
./pick "" blue. En quoi argv[1] et argv[argc] diffèrent-ils ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
strncpy(b, "planet", sizeof b);. Le programme exige le mot d’origine complet. Quelle correction satisfait cette exigence ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
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 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
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
A
Accès hors limites
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
sum à zéro permet à chaque sum += a[i] d’ajouter l’élément suivant du tableau au total courant.argc
argc donne le nombre de chaînes d’arguments fournies à main, y compris normalement la chaîne utilisée pour lancer le programme../label red blue dans un interpréteur ordinaire donne argc égal à 3 : le nom de lancement et deux couleurs.Argument de ligne de commande
argv
argv donne accès aux chaînes d’arguments par indice ; elles sont suivies d’un pointeur nul à la position indiquée par argc.argc, un programme peut utiliser strcmp(argv[1], "-v") pour reconnaître sa première option.ASCII
'8' - '0' produit 8, car les codes des caractères chiffres sont consécutifs.atoi
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.atoi : un nombre renvoyé ne prouve donc pas que toute l’entrée était numérique.B
Boucles imbriquées
C
Capacité
Caractère nul de fin de chaîne
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
char pet[] = "dog" contient trois lettres suivies d’un caractère de valeur zéro.Chaîne vide
char message[20] = "" fournit une destination vide valide pour un ajout ultérieur qui respecte sa capacité.Classification des caractères
<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
main signale une exécution réussie.Colonne
g[r][c].g[r][c].Comparaison lexicographique des octets
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
Concaténation
Constante caractère
int, qui représente un code de caractère, par exemple celui d’une lettre.printf("%c %d", 'B', 'B') affiche la lettre B et la valeur numérique 66.Conversion numérique
% 26.D
Débordement de tampon
Décalage de César
Découpage en jetons
strtok le fait en modifiant l’entrée et en mémorisant une position.strtok(NULL, ",") poursuit le découpage de la même entrée modifiable au lieu de le recommencer.Délimiteur
É
Élément
int a[3] = {8, 1, 6}, l’élément a[1] vaut 1 et peut recevoir un autre entier.E
Encodage des caractères
ERANGE
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.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é
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
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.Filtrage
Fin de fichier
fgets peut tout de même réussir si elle a lu des caractères avant d’atteindre cet état.fgets suffisamment grand de recevoir ce texte final.Frontière de mot
I
Indice
Initialiseur
int hits[4] = {3} initialise le premier compteur à 3 et les trois autres à zéro.L
Largeur de champ
%s limite le nombre de caractères d’entrée stockés avant l’octet nul de fin supplémentaire.char word[10], la conversion %9s réserve le dixième octet disponible au caractère nul de fin.Largeur de ligne
int g[][6] accepte des lignes de six entiers, tandis que la fonction appelante fournit le nombre de lignes séparément.Ligne
int table[2][5], table[1] désigne la seconde ligne, qui contient cinq positions d’entiers.Ligne partielle
fgets : le second ne doit donc pas devenir une nouvelle réponse.Liste de chaînes de capacité fixe
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
const char *label = "ready" désigne un littéral ; une copie modifiable peut être créée avec char label[] = "ready".Locale
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
M
Masque de bits
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
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.memcmp trouve des octets stockés différents.memcpy
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
memmove copie un nombre d’octets demandé avec un comportement défini même lorsque les zones source et destination se chevauchent.memmove.memset
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
scanf a effectuées avec succès ; il permet de vérifier que les données demandées ont bien été lues.Nombre d’éléments utilisés
O
Octet de continuation
10 et suit un octet de début dans un point de code encodé sur plusieurs octets.P
Paramètre de type variablement modifié
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
const int a[], car additionner les valeurs d’entrée ne nécessite pas de les modifier.Paramètre tableau
int a[] a toujours besoin d’une longueur distincte avant de pouvoir parcourir son entrée.Plage de valeurs autorisée par l’application
Point de code Unicode
Pointeur de fin de conversion
strtol renvoie 9, mais le pointeur de fin de conversion désigne le z qui n’a pas été consommé.Pointeur nul
strchr(name, '.') != NULL avant d’utiliser le résultat comme début d’une partie finale de nom de fichier.R
Rangement par lignes
grid[0][3] est grid[1][0].Rebouclage des entiers non signés
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
{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
"A\nB" contient un saut de ligne entre ses lettres ; la barre oblique inverse et n encodent un seul caractère.size_t
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
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.Sous-chaîne
strstr trouve le premier emplacement où elle commence.strcat
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é.strchr
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.strchr trouve la partie finale « .part.ext », premier point compris.strcmp
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
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.char out[5].strcspn
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
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.char tag[30] = "oak", strlen(tag) vaut 3, tandis que sizeof tag indique la capacité totale de 30 octets.strncat
strncat ajoute au plus un nombre indiqué d’octets de texte source, puis écrit un caractère nul de fin à leur suite.strncmp
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.strncpy
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.strrchr
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.strrchr peut donc localiser le séparateur de l’extension.strtol
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.strtol(text, &end, 10) permet au programme de rejeter une lettre restante après des chiffres décimaux par ailleurs valides.T
Tableau
int levels[6] réserve six entiers ; modifier levels[2] change la troisième valeur stockée.Tableau à deux dimensions
int board[4][6] fournit 24 entiers, accessibles par quatre indices de ligne valides et six indices de colonne valides.Tableau de compteurs
counts[4]++ ajoute une occurrence à son compteur.Tableau de longueur variable
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
const char *names[] = {"Al", "Mina"} stocke deux références et permet d’en remplacer une.Tableau de sortie
out[i], tandis que la fonction appelante conserve la propriété du tableau.Tampon
Transformation en place
Troncature
U
UTF-8
À propos de cette unité
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.