Exercices Pratiques : Manipulation de chaînes et de pointeurs en C

Questions à compléter

Dans un programme 64 bits :

  • La valeur de sizeof("\num\\\t") est de 6.
  • La valeur de strlen("\num\\\t") est de 5.
  • La valeur de sizeof("\num\\\t" + 1) est de 8 (car c'est la taille d'un pointeur en 64 bits).
  • La valeur de strlen("\num\\\t" + 1) est de 4.

Questions à choix multiples

Lors du tri de {4, 5, 6, 3, 2, 1} par ordre croissant en utilisant le tri à bulles, quel est l'état du tableau après la troisième passe ?

Le tableau initial est : 4, 5, 6, 3, 2, 1

Première passe :

  • Comparaison 4 et 5 : 4, 5, 6, 3, 2, 1
  • Comparaison 5 et 6 : 4, 5, 6, 3, 2, 1
  • Comparaison 6 et 3 : 4, 5, 3, 6, 2, 1
  • Comparaison 6 et 2 : 4, 5, 3, 2, 6, 1
  • Comparaison 6 et 1 : 4, 5, 3, 2, 1, 6 (Le plus grand élément est à sa place)

Deuxième passe :

  • Comparaison 4 et 5 : 4, 5, 3, 2, 1, 6
  • Comparaison 5 et 3 : 4, 3, 5, 2, 1, 6
  • Comparaison 5 et 2 : 4, 3, 2, 5, 1, 6
  • Comparaison 5 et 1 : 4, 3, 2, 1, 5, 6 (Le deuxième plus grand élément est à sa place)

Troisième passe :

  • Comparaison 4 et 3 : 3, 4, 2, 1, 5, 6
  • Comparaison 4 et 2 : 3, 2, 4, 1, 5, 6
  • Comparaison 4 et 1 : 3, 2, 1, 4, 5, 6 (Le troisième plus grand élément est à sa place)

La réponse correcte est : C. 3 2 1 4 5 6

Questions Vrai ou Faux

  1. Le tri à bulles est très efficace car il ne nécessite qu'environ $\frac{n^2}{2}$ comparaiosns.

    Faux. Le tri à bulles a une complexité temporelle de $O(n^2)$, ce qui est considéré comme peu efficace pour de grands ensembles de données. Des algorithmes comme le tri rapide ($O(n \log n)$) sont nettement plus performants.

  2. Après l'exécution du code suivant, la valeur de x est 042, celle de y est 87, et celle de z est 0x4e.

    
    int data[10] = { '\012', 34, '\x56', 78, 0x910 }, *ptr = data + 1;
    int x = *ptr++;
    int y = ++*ptr;
    int z = *++ptr;
    
    

    Vrai. Analysons étape par étape :

    • ptr pointe initialement vers data[1] (qui contient la valeur 34).
    • x = *ptr++; : La valeur pointée par ptr (qui est 34) est assignée à x. Ensuite, ptr est incrémenté pour pointer vers data[2]. Donc, x = 34 (qui est 042 en octal). ptr pointe maintenant vers data[2].
    • y = ++*ptr; : La valeur à laquelle ptr pointe (data[2], qui est '\x56' soit 86 en décimal) est d'abord incrémentée. Donc, data[2] devient 87. Cette nouvelle valeur est ensuite assignée à y. Ainsi, y = 87. Notez que ptr ne bouge pas dans cette opération, il pointe toujours vers data[2].
    • z = *++ptr; : ptr est d'abord incrémenté pour pointer vers data[3]. Ensuite, la valeur pointée par ptr (qui est 78) est assignée à z. Donc, z = 78 (qui est 0x4e en hexadécimal).

    Les valeurs sont donc : x = 34 (042), y = 87, z = 78 (0x4e).

  3. Pour un tableau déclaré comme int arr[10];, l'expression (int)(&arr + 1) - (int)&arr vaut 4.

    Faux. L'expression &arr représente l'adresse du tableau entier. L'addition &arr + 1 incrémente cette adresse de la taille totale du tableau. La taille d'un tableau d'entiers de 10 éléments sur une architecture où un int fait 4 octets est de 40 octets. Donc, (int)(&arr + 1) - (int)&arr calcule la différence en octets, qui est égale à la taille du tableau, soit 40.

  4. Dans le code void zip(char *p) { char *q = p; ... }, l'instruction char *q = p; copie l'adresse du premier caractère de la chaîne pointée par p dans la variable pointeur *q.

    Faux. L'instruction char *q = p; copie la valeur du pointeur p (qui est l'adresse du premier caractère de la chaîne) dans le pointeur q. q devient donc un pointeur vers le même endroit que p. *q ferait référence au caractère lui-même, pas à un pointeur.

  5. Lors de la saisie dans un tableau char s[128]; en utilisant scanf("%127s", s);, 127 caractères seront lus et le caractère nul \0 sera ajouté, prévenant ainsi un dépassement de tampon.

    Faux. scanf("%127s", s); lira au maximum 127 caractères pour éviter de dépasser la taille du tampon alloué (128 octets). Le caractère nul \0 sera ajouté si moins de 127 caractères sont lus (ou après le 127ème caractère s'il est lu). La formulation "sera ajouté" est correcte, mais "127 caractères seront lus" pourrait être trompeur car il est possible qu'moins de 127 caractères soient lus si le séparateur (espace, retour chariot, etc.) est rencontré avant.

  6. La fonction int sprintf(char *string, char *format [,argument,...]) est une fonction de formatage de chaînes qui écrit des données formatées dans une chaîne. Par exemple, pour char str[128]; int pos = sprintf(str, "%d-%.2f-%s", 123, 3.14159, "abc");, le contenu de la chaîne str sera "123-3.14-abc" et la valeur de pos sera 12.

    Vrai. La fonction sprintf écrit la chaîne formatée dans le tampon spécifié par le premier argument. Elle retourne le nombre de caractères écrits (sans compter le caractère nul final). Dans cet exemple, 123 (3 caractères), - (1 caractère), 3.14 (4 caractères), - (1 caractère), abc (3 caractères) font un total de 12 caractères. Le caractère nul \0 est automatiquement ajouté à la fin par sprintf.

  7. La fonction mystrlen implémente le calcul de la longueur effective d'une chaîne.

    
    int mystrlen(char *s)
    {
       char *p = s;
       while (*++p) ;
       return p - s;
    }
    
    

    Faux. Cette implémentation de mystrlen a deux problèmes :

    • Pour une chaîne vide (""), p est initialisé à l'adresse de s. *++p tente d'accéder à s[1] avant même de vérifier si la chaîne est vide. Cela peut entraîner un comportement indéfini ou une erreur de segmnetation si la chaîne est effectivement vide.
    • Si l'on ignore le problème potentiel de la chaîne vide, le pointeur p est incrémenté *avant* la déréférencement dans la boucle while (*++p). Cela signifie que le premier caractère est sauté dans le calcul final de la différence des pointeurs. La fonction retourne effectivement la longueur de la chaîne à partir du deuxième caractère, ou une valeur incorrecte.

    Une implémentation correcte ressemblerait plutôt à :

    
    int correct_strlen(char *s)
    {
       char *start = s;
       while (*s) {
           s++;
       }
       return s - start;
    }
    
    

Étiquettes: C pointeurs tableaux manipulation de chaînes tri à bulles

Publié le 9 juin à 22h02