home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / dos / prg / alb_c10 / chap_10 / chap_10.txt < prev   
Encoding:
Text File  |  1994-10-03  |  22.7 KB  |  469 lines

  1.  
  2.  ========================================================================= 
  3.                              APPRENTISSAGE du C             version ALB_10                
  4.                              
  5.                    CHAPITRE 10: DES CHAINES DE CARACTERES.                   
  6.  =========================================================================
  7.  
  8.  
  9.                 1. QU'EST CE QU'UNE CHAINE DE CARACTERES ?               
  10.                 ==========================================
  11.  
  12.         "Petrus", avec des guillemets anglais, est une chaîne.
  13.                 
  14.       En C, une chaîne de caractères est un tableau de caractères 
  15.       dont le dernier élément est le caractère nul \0.
  16.  
  17.         +--------+--------+--------+--------+--------+--------+--------+
  18.         |    P   |    e   |    t   |    r   |    u   |    s   |   \0   |
  19.         +--------+--------+--------+--------+--------+--------+--------+
  20.  
  21.            Ce tableau compte 7 éléments, un de plus que le mot.
  22.  
  23.    1° Il ne faut pas confondre le caractère ASCII nul \0 avec le zéro décimal 
  24.       dont la valeur ASCII est 48.
  25.  
  26.    2° Une chaîne de caractères est un tableau, donc un objet particulier, 
  27.       différent dans sa nature des caractères qui la composent.
  28.  
  29.       La chaîne "P" est un objet différent du caractère 'P'.
  30.  
  31.                 int char car0= 'P', 
  32.                     chaine[]= "P";        // chaine[0]= 'P' et chaine[1]= \0
  33.  
  34.       Nous avons déclarés et initialisé une variable car de type caractère
  35.       et un tableau de 1 caractère du nom de chaine. 
  36.         
  37.    3° Nous savons déjà que tableaux et variables ordinaires n'ont pas 
  38.       les mêmes propriétés.
  39.  
  40.       Il sera possible de modifier car0:        car0= 'Z';
  41.       car0 est une variable, une L-value.
  42.  
  43.       Mais non pas le tableau:                  chaine= "Z";  // refus
  44.  
  45.       chaine est une adresse invariable, une constante et on ne peut ni la
  46.       modifier ni à plus forte raison lui affecter une chaîne d'octets. Ce
  47.       n'est pas une L-value. 
  48.       
  49.    Pour modifier le contenu de la chaîne il faudra s'y prendre autrement.
  50.   Chapitre 10: Des chaînes de caractères.                           page 1
  51.                                                       
  52.  
  53.  
  54.                 2. DECLARATION ET INITIALISATION.               
  55.                 =================================
  56.  
  57.       Les chaînes sont des tableaux. On pourra les initialiser comme les
  58.    tableaux, avec la notation des tableaux ou avec des pointeurs, mais il y
  59.    a quelques particularités.
  60.  
  61.                 Nous écrirons par analogie avec int tab[3]= { 0, 1, 2}; 
  62.    
  63.                 char chaine[7]= { 'P', 'e', 't', 'r', 'u', 's', '\0'};
  64.  
  65.    mais ce n'est pas très pratique et on écrira plutôt:
  66.  
  67.                 char chaine0[]= "Petrus"; le \0 est ajouté automatiquement,
  68.    ou bien      char chaine0[8]= "Petrus";  en laissant 1 élément inutilisé.
  69.  
  70.    On pourra de la même façon utiliser un pointeur:
  71.  
  72.                 char *chaine1;
  73.                 chaine1= "Albulus";  ou plus directement, 
  74.                 
  75.                 char *chaine1= "Albulus";
  76.  
  77.                                                                 ************
  78.    2.1. Déclaration et initialisation simultanées                 CH10_01.C
  79.    ----------------------------------------------               ************
  80.  
  81.    1°  Nous déclarons deux chaînes, l'une avec la notation tableau de huit
  82.    caractères pour voir ce qui va se passer avec les espaces que le nom 
  83.    n'utilise pas, l'autre avec un pointeur. 
  84.    L'initialisation est faite en même temps que la déclaration.
  85.  
  86.    2° Nous affichons les chaînes en utilisant le symbole s dans printf().
  87.    Puis nous affichons caractère par caractère le contenu entier des tableaux.
  88.    
  89.    Pour le premier, nous gardons l'affichage avec des lettres. Il contient le
  90.    nom Petrus complété par des caractères nuls. Ceux ci sont représentés de
  91.    manières différentes selon les polices utilisées par votre C.   
  92.    
  93.    Pour le second nous utilisons l'équivalence entre les lettres et les 
  94.    caractères ASCII pour sortir des nombres. On vérifie la présence du 
  95.    caractère nul en bout de chaîne.
  96.    
  97.    3° A titre d'exercice, nous avons utilisé l'accès aux éléments par la 
  98.    notation tableau puis par pointeur:
  99.                                         chaine0[i], *chaine1++
  100.  
  101.    Remarque 1: le compilateur aurait rejeté *chaine0++. Pourquoi?
  102.    Parce que chaine0 est une adresse constante qui ne peut donc être modifiée 
  103.    par incrémentation ou de toute autre manière. Ce n'est pas une L-value.
  104.    chaine1 par contre est une référence de pointeur, donc une variable 
  105.    adresse, qui peut être modifiée. C'est une L-value.
  106.   Chapitre 10: Des chaînes de caractères.                           page 2
  107.                                                       
  108.  
  109.    Remarque 2: à la sortie de la boucle, la valeur de chaine1 est égale à sa 
  110.    valeur de départ + i * sizeof( char), il y a eu 8 incrémentations. 
  111.    Si nous voulions utiliser à nouveau ce pointeur il faudrait ramener sa
  112.    référence à sa valeur initiale: 
  113.    
  114.         valeur initiale de chaine1= valeur actuelle  - i* sizeof( char)
  115.  
  116.    Ce n'est pas très pratique. Il semble préférable dans ce cas de ne pas 
  117.    toucher à la valeur initiale de chaine1 en écrivant:
  118.  
  119.                 *( chaine1+ i)   au lieu de    *chaine1++
  120.  
  121.  
  122.    2.2. Saisie normale d'une chaîne de caractères.
  123.    -----------------------------------------------
  124.  
  125.    => On utilise normalement scanf() en prenant la précaution de nettoyer le 
  126.    tampon d'entrée et en se limitant en général à la saisie d'une seule
  127.    chaîne. Mais il est nécessaire dans certains cas d'en saisir plusieurs.
  128.  
  129.                   char prenom[16], nom[24];
  130.                   printf(" Entrez votre prénom et votre nom:   ");
  131.                   scanf("%s %s", prenom, nom);
  132.  
  133.    Il ne faudra pas utiliser le symbole & puisque prenom et nom sont des
  134.    chaînes de caractères et donc des adresses.
  135.    Cette fonction ne permet pas de saisir les espaces, à moins de l'écrire 
  136.    sous la forme, 
  137.                   scanf("%[^\n]", chaine);
  138.  
  139.    => On utilise aussi les fonctions puts() et gets() qui ne permettent de 
  140.    traiter qu'une chaîne à la fois. 
  141.    La fonction gets() équivalente à scanf() ignore les séparateurs autres que 
  142.    \n qui indique la fin de la lecture et permet donc la saisie de chaînes
  143.    contenant des espaces.
  144.  
  145.                   char nom[24];
  146.                   printf(" Entrez votre nom:   ");
  147.                   gets( nom);
  148.  
  149.                   printf("\n Votre nom est:  ");
  150.                   puts( nom);
  151.  
  152.    La fonction gets() renvoie un pointeur NULL sur la chaîne en cas d'échec, 
  153.    ce qui permet de contrôler la validité de la saisie.
  154.  
  155.                                                                 ************
  156.                         Saisie d'une chaîne de caractères :       CH10_02.C
  157.                                                                 ************
  158.    Exécutez ce programme. Vous constaterez qu'il ne fonctionne pas 
  159.    correctement. Vous aurez l'impression que la fonction gets() a été sautée.
  160.    En réalité, la fonction scanf() a laissé des caractères nuls dans le 
  161.    tampon. La fonction gets() les a saisi et puts() les a affichés!
  162.  
  163.    Effacez la ligne qui débute avec scanf() et enlevez les symboles /* et */
  164.    qui encadrent les trois lignes du code de saisie contrôlée.
  165.    Le tampon sera vidé après chaque appel à scanf(). 
  166.    Le programme fonctionnera normalement. 
  167.   Chapitre 10: Des chaînes de caractères.                           page 3
  168.                                                       
  169.  
  170.  
  171.                 3. MODIFICATION DU CONTENU D'UNE CHAINE.               
  172.                 ========================================
  173.  
  174.    Nous avons vu qu'il n'est pas possible d'affecter directement à une chaîne
  175.    déjà déclarée une autre chaîne.
  176.  
  177.                 char chaine[7];
  178.                 chaine= "Petrus";      //  est refusé.
  179.  
  180.    Mais pourquoi ne pas tenter une affectation indirecte, avec bien sûr, des 
  181.    pointeurs?
  182.  
  183.    Nous allons écrire une fonction CopieChaine() qui permettra de copier, 
  184.    lettre par lettre, une chaine source désignée par un pointeur à la place
  185.    d'une chaine cible désignée elle aussi par un pointeur.
  186.  
  187.                                                                 ************
  188.                         Copie d'une chaîne dans une autre :       CH10_03.C
  189.                                                                 ************
  190.  
  191.    1° Définition de la fonction:
  192.    les arguments seront 2 pointeurs, le premier sur la chaîne "cible", 
  193.    le second sur la chaîne "source" avec le qualificatif "const" pour qu'elle 
  194.    ne puisse pas être modifiée par erreur.
  195.    On affecte à un pointeur *p l'adresse "cible" qui ainsi ne sera pas 
  196.    elle même modifiée. C'est la référence de p qui sera incrémentée et non
  197.    l'adresse "cible".
  198.    Tant que le caractère de "source" sera différent du \0 de fin de chaîne,
  199.    ce caractère sera remplacé par celui qui lui correspond de "cible".
  200.    L'incrémentation parallèle des références des pointeurs assure la 
  201.    progression à l'intérieur de la chaîne.
  202.    Pour finir il faudra copier ce caractère de fin de chaîne dans "source".
  203.  
  204.    2° Nous avons fixé les dimensions des tableaux à 10 et ajouté 2 espaces
  205.    devant le nom Albulus.
  206.       La première ligne imprimée montre que les caractères espaces sont pris 
  207.    en compte. La seconde que CopieChaine() fonctionne correctement.
  208.       L'impression du contenu total des 2 chaînes montre que chaine0 a été 
  209.    copiée dans chaine1, y compris son caractère \0. Mais la suite n'a pas été 
  210.    modifiée. 
  211.  
  212.       En réalité, vous n'aurez pas à utiliser la fonction CopieChaine(). 
  213.    Vous trouverez dans la bibliothèque string.h qui regroupe toutes les 
  214.    fonctions utiles à la manipulation des chaînes, une fonction strcpy() dont 
  215.    le nom est un condensé de "string copy", qui fait la même chose beaucoup 
  216.    mieux. Nous y reviendrons plus loin dans ce chapitre.
  217.   Chapitre 10: Des chaînes de caractères.                           page 4
  218.                                                      
  219.  
  220.  
  221.         4. UTILISATION DE FONCTIONS DE LA BIBLIOTHEQUE STRING.H               
  222.         =======================================================
  223.  
  224.    Il faut, pour pouvoir utiliser les fonctions de cette bibliothèque,
  225.    inclure string.h dans l'en-tête.
  226.  
  227.                                                                 ************
  228.    4.1. Mesure de la longueur d'une chaîne, strlen().             CH10_04.C
  229.    --------------------------------------------------           ************
  230.  
  231.         char chaine0[20]= "Petrus Albulus";
  232.         printf(" longueur de la chaîne: %d", strlen( chaine0) );
  233.  
  234.     L'argument est une adresse, la fonction renvoie le nombre de caractères 
  235.     de la chaîne jusqu'au code nul \0 NON compris.
  236.  
  237.     Dans CH10_04.C nous avons utilisé la fonction strlen() et l'opérateur
  238.     sizeof() pour que vous puissiez en comparer les effets.
  239.  
  240.  
  241.    4.2. Copie d'une chaîne dans une autre, strcpy() et strncpy(). 
  242.    --------------------------------------------------------------
  243.  
  244.    4.2.1. Le prototype de la fonction strcpy() est:  
  245.     
  246.         *char strcpy( char *cible, const char *source);
  247.  
  248.    La fonction renvoie l'adresse cible, qui peut parfois être utile.
  249.  
  250.         char chaine[18]= "Petrus Albulus";
  251.         strcpy( chaine, "abcdef  ghijkl");  chaîne de 14 caractères + \0.
  252.  
  253.     Dans CH10_04.C nous avons contrôlé, à titre d'exemple, la valeur renvoyée 
  254.     par la fonction. Est elle bien égale à l'adresse de la cible?
  255.     Notez dans printf( ...%s...%d.., chaine, chaine, ptr), %s pour afficher 
  256.     une chaîne qui commence à l'adresse chaine et %d qui affiche l'adresse
  257.     chaine. 
  258.  
  259.    4.2.2. La fonction strncpy() est un peu différente. 
  260.    
  261.       Elle permet, en ajoutant un troisième argument qui est un nombre entier
  262.    non signé, de limiter à sa valeur la longueur maximum de la recopie. 
  263.    L'espace, quand il existe, entre la fin de la recopie et cette longueur
  264.    maximum est complété par des codes nuls \0. 
  265.    ATTENTION: si la chaîne source est plus longue que la longueur maximum, la
  266.    fonction ne copie que ce nombre de caractères, mais sans \0 final.
  267.  
  268.    *char strcpy( char *cible, const char *source, unsigned int longmax);
  269.  
  270.         char chaine[18]= "Petrus Albulus";
  271.         strncpy( chaine, "uvw xyz", 10);                        ************
  272.                                                                   CH10_05.C
  273.                                                                 ************
  274.    La déclaration et l'initialisation de chaine a eu pour effet de placer 
  275.    14 caractères et le \0 dans la chaîne. Les 3 éléments restants sont 
  276.    ramenés à \0 automatiquement.
  277.    La fonction strncpy() a eu le même effet  dans la limite des 10 premiers
  278.    éléments. Les autres, au delà du dixième chaine[9], n'ont pas été touchés.
  279.   Chapitre 10: Des chaînes de caractères.                           page 5
  280.                                                       
  281.  
  282.                                                                 ************
  283.                     Utilisation sans précautions de strncpy:      CH10_06.C
  284.                                                                 ************
  285.       Nous avons allongé la chaîne source au delà de 10 caractères.
  286.    Vous pouvez constater que les 10 premiers caractères de la source sont
  287.    pris en compte et affectés à la cible, SANS LE CARACTERE nul \0 de 
  288.    fin de chaîne! Les caractères au delà du dixième ne changent pas. C'est
  289.    à dire que lorsque la nouvelle chaîne sera lue, la lecture ne s'arrêtera
  290.    qu'au premier caractère \0, qui est chaine[14] et nous aurons:
  291.  
  292.         "rst uvw xyulus" cela fait du beau latin de cuisine mais ce n'était
  293.         pas ce que nous attendions!
  294.  
  295.    Donc, en règle générale, on emploie cette fonction avec comme dernier 
  296.    argument la taille de la chaîne cible - 1, mais on doit ajouter dans 
  297.    certains cas le \0 final. 
  298.    
  299.                                                                 ************
  300.         Comment copier une chaîne sans "déborder", 1ère étape:    CH10_07.C
  301.                                                                 ************
  302.  
  303.    Avec dim= 18, on peut écrire sans débordement 17 caractères. Il semble que 
  304.    tout se passe bien parce que la chaîne cible possède déjà un \0 de fin de 
  305.    chaîne. Vérifiez le en plaçant 4 caractères quelconques devant le P de la 
  306.    chaîne cible: "wxyzPetrus Albulus". Relancez le programme et vous verrez
  307.    que nous n'avons plus de caractère \0 pour marquer la fin de la chaîne.
  308.    On ne pourra donc plus la lire correctement.
  309.  
  310.                                                                 ************
  311.                             Saisie "contrôlée" d'une chaîne:      CH10_08.C
  312.                                                                 ************
  313.       Il faut donc, dans ce cas, ajouter le \0 de fin de chaîne.
  314.    La fonction LitChaine() doit permettre une saisie de chaîne avec un 
  315.    minimum de sécurité.
  316.    Nous avons, provisoirement, utilisé un pointeur t1 pour pouvoir affecter 
  317.    la chaîne saisie avec scanf(). Nous verrons plus loin qu'il vaut mieux 
  318.    faire autrement.
  319.    On s'assure de la présence du \0 final à l'adresse ( t0+ dimension -1),... 
  320.    en l'ajoutant systématiquement!
  321.    On vide comme d'habitude le tampon. On applique la règle précédente avec
  322.    strncpy(). Le traitement est relativement long, mais le temps ne joue pas 
  323.    un rôle majeur dans la plupart des processus de saisie.
  324.   Chapitre 10: Des chaînes de caractères.                           page 6
  325.                                                       
  326.  
  327.  
  328.  
  329.       4.3. copie d'une chaîne à la suite d'une autre: strcat(), strncat(). 
  330.       ---------------------------------------------------------------------
  331.  
  332.    =>   char *strcat( char *cible, const char *source);
  333.    La longueur de la chaîne cible après l'opération sera égale à: 
  334.      
  335.         strlen( cible avant l'appel de la fonction)+ strlen( source).
  336.  
  337.    La fonction renvoie un pointeur sur la chaîne cible.
  338.  
  339.    => char *strncat( char *cible, const char *source, unsigned int longmax );
  340.  
  341.    La fonction recopie au plus "longmax" caractères et ajoute un \0 en fin de
  342.    chaîne. La longueur de la chaîne après l'exécution de la fonction est de
  343.    strlen( cible)+ longmax.
  344.  
  345.                                                                 ************
  346.                 Comment utiliser strncat() sans "déborder":       CH10_09.C
  347.                                                                 ************
  348.  
  349.    Nous avons choisi pour cet exemple une longueur de dim= 13 pour chaine0. 
  350.    Le nouvel enregistrement est limité à dim, moins la longueur déjà utilisée 
  351.    dans la chaîne cible, moins 1, pour le \0 de fin de chaîne.
  352.    Le mot qui a été ajouté est tronqué mais cela est bien préférable à un 
  353.    débordement dont les conséquences sont imprévisibles.
  354.  
  355.    Notez, que dans ces conditions, la fin de la chaîne n'est pourvue du 
  356.    symbole \0 que s'il y était déjà. Vous pourrez le constater en mettant 
  357.    dim= 13 caractères dans la chaîne cible. 
  358.    Si on raisonne en termes de sécurité il faut l'ajouter systématiquement. 
  359.    Nous avons mis en commentaires dans le code une ligne qui fait cet ajout.
  360.  
  361.  
  362.                 4.4. Les autres fonctions. 
  363.                 --------------------------
  364.  
  365.       Nous ne ferons ici que les mentionner. La plupart des compilateurs C
  366.    sont dotés d'une aide qui donne une liste des fonctions, leur définition 
  367.    et souvent même un exemple d'utilisation.
  368.  
  369.         => strlwr() et strupr() convertissent majuscules en minuscules et 
  370.            inversement.
  371.         => strrev() inverse les caractères d'une chaîne sauf le \0 final.
  372.            memcpy() copie de n octets.
  373.         => strchr(), strrchr(), strstr(), strpbrk() recherchent des éléments 
  374.            de chaînes ou des caractères.
  375.         => strcmp(), strncmp(), stricmp(), strnicmp() comparent des chaînes.
  376.   Chapitre 10: Des chaînes de caractères.                           page 7
  377.                                                       
  378.  
  379.  
  380.  
  381.                 5. TABLEAUX DE POINTEURS ET CHAINES DE CARACTERES.               
  382.                 ==================================================
  383.  
  384.                                                                 ************
  385.     Chaînes de longueurs différentes (ou tableaux incomplets):   CH10_10.C
  386.                                                                 ************
  387.    On associe dans ce programme le nom d'un jour de la semaine avec le nombre  
  388.    qui lui correspond. 
  389.    Le tableau de pointeurs est initialisé directement sans mention de taille.
  390.    C'est intéressant parce que cela permet d'utiliser des chaînes de longueurs 
  391.    différentes. On manipulera chacune avec le pointeur qui lui correspond.
  392.    On pourra toujours par la suite lui affecter d'autres chaînes. Mais il 
  393.    faudra alors respecter la dimension initiale de chacune sous peine de 
  394.    débordements faciles à imaginer.
  395.  
  396.    Nous avons déjà vu la manière de déclarer un tableau de pointeurs. Nous
  397.    avons déclaré un pointeur du nom de jours. Il pointe sur les lignes d'un 
  398.    tableau que nous repérons avec un indice entre crochets.
  399.    Examinez le mécanisme d'utilisation. Dans la dernière ligne du code, nous 
  400.    aurions pu remplacer la notation "tableau", jours[n- 1], par la notation 
  401.    "pointeur", *( jours+ n- 1).
  402.  
  403.    Nous pourrions accéder au troisième caractère de la cinquième chaîne, si 
  404.    ce caractère existe, en écrivant: 
  405.    
  406.                 *( jours[ 5-1] + (3- 1) )   ou bien si vous préférez
  407.                 *( *(jours+ 5-1) + (3- 1) ).
  408.  
  409.                                                                 ************
  410.                     Saisie et trie de chaînes de même longueur:   CH10_11.C
  411.                                                                 ************
  412.    Ceci est l'adaptation d'un programme classique. Nous utilisons un tableau
  413.    de pointeurs pour saisir et trier des chaînes ayant une dimension maximum
  414.    définie initialement. 
  415.    
  416.    1° Nous avons besoin en chemin d'une fonction de comparaison strcmp() qui 
  417.    compare deux chaînes et renvoie zéro quand elles sont égales.
  418.    La fonction de trie agit en fonction de la longueur de la chaîne et elle
  419.    peut être facilement adaptée pour trier selon d'autres critères.
  420.    Examinez surtout la manière d'initialiser "dynamiquement" les lignes d'un 
  421.    tableau de pointeurs déclaré au début du programme, cela mérite un instant
  422.    de réflexion.
  423.  
  424.    2° La fonction LitChaine() commence par créer "dynamiquement" une chaîne 
  425.    de longueur 256* 2 en utilisant la fonction malloc(). La fonction free() 
  426.    permettra de libérer l'espace mémoire utilisé par cette chaîne à la 
  427.    clôture de la fonction. 
  428.   Chapitre 10: Des chaînes de caractères.                           page 8
  429.                                                       
  430.  
  431.    
  432.    Pourquoi créer cette chaîne dynamiquement? 
  433.  
  434.    => Un simple pointeur char aurait pu suffire pour assurer le "portage" de 
  435.    la chaîne saisie. Mais la déclaration du pointeur n'assure pas, par elle 
  436.    même, la réservation d'une zone de mémoire suffisante pour stocker cette 
  437.    chaîne. 
  438.    => Si la chaîne cible est elle même crée dynamiquement, la fonction de
  439.    copie pourra lui affecter sans restrictions la chaîne saisie. 
  440.    Ces restrictions tiennent au "modèle de mémoire" et au type de pointeur
  441.    utilisé. Nous en parlerons dans le chapitre consacré à la gestion de la
  442.    mémoire.
  443.    
  444.    Pourquoi une chaîne de longueur 256* 2 octets? 
  445.    
  446.    Ce n'est qu'un bricolage, fait uniquement pour éviter un débordement dans 
  447.    une zone incontrôlée de la mémoire. Il est donc préférable de créer un 
  448.    tableau, et de lui donner une dimension a priori suffisante. 
  449.    La fonction scanf() est utilisée avec une limitation à 255 du nombre de 
  450.    caractères qui peuvent être saisis. 
  451.  
  452.  
  453.                            ============================
  454.  
  455.  
  456.    Nous en avons terminé avec la partie traditionnelle de la programmation. 
  457.    La notion de structure, que nous allons étudier, marque déjà une évolution 
  458.    majeure du langage. C'est un pas de plus vers la programmation "objet".
  459.         
  460.         Parmi les grands développeurs américains certains semblent regretter 
  461.         cette évolution. Pour ces programmeurs d'élite, elle limite la 
  462.         liberté d'écriture que donnait l'absence de règles contraîgnantes.
  463.         
  464.         On peut admirer et préférer pour des raisons esthétiques ou autres, 
  465.         ces maîtres japonais du tir à l'arc, dont le geste presque immatériel 
  466.         atteint une espèce de perfection. Mais nos règles collectivistes de 
  467.         productivité ne font pas partie de l'univers de ces maîtres du Zen.
  468.   Fin du chapitre 10: Des chaînes de caractères.                    page 9
  469.