IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Étude détaillée du module String de la libc


précédentsommairesuivant

V. c_memcmp

V-A. Prototype

 
Sélectionnez
int c_memcmp (const void * s1, const void * s2, c_size_t n);

V-B. Description et comportement

La fonction c_memcmp compare chaque octet des deux blocs mémoire s1 et s2 sur une longueur n. Il faut également noter que le caractère nul participe totalement à la comparaison et par conséquent, une adresse possédant ce caractère sera donc inférieure à l'autre !

La fonction renvoie trois valeurs suivant des cas précis :

  • Valeur négative si le bloc d'adresse s1 est inférieur au bloc d'adresse s2 dans les n premiers octets ;
  • Zéro si les deux blocs mémoire contiennent les mêmes octets sur les n premiers octets ;
  • Valeur positive si le bloc d'adresse s1 est supérieur au bloc d'adresse s2 dans les n premiers octets.

La norme du C ne précise cependant pas quelle est la valeur renvoyée. Dans certaines implémentations comme sur Linux et Windows par exemple, cette fonction renvoie les valeurs -1, 0, 1, mais dans d'autres implémentations cette fonction peut directement retourner le résultat de la soustraction des deux octets différents !

La comparaison des octets se fait par conversion du type void * en un type unsigned char * !

V-C. Algorithme

Voici un algorithme possible pour la fonction c_memcmp :

 
Sélectionnez
algorithme
   fonction c_memcmp (s1:générique, s2:générique, n:entier):entier
      début
         i <- 0
 
         tant que n <- n - 1 faire
            si s1[i] différent de s2[i] alors
               si s1[i] inférieur à s2[i]
                  alors retourne -1
                  sinon retourne 1
               fsi
            fsi
 
            i <- i + 1
         ftant
 
         retourne 0
      fin
 
lexique
   s1 : Zone mémoire quelconque.
   s2 : Zone mémoire quelconque.
   n  : Longueur de la comparaison.
   i  : Variable d'incrémentation pour le parcours des adresses mémoire.

La boucle part du début des adresses s1 et s2, et avance de n cases mémoire. Dans la première condition, nous testons si les deux octets courants sont différents. Si les deux octets courants sont différents, nous testons leur différence et nous retournons la valeur adéquate.

Nous pouvons voir qu'ici je n'ai pas choisi de retourner comme valeur le résultat d'une soustraction entre les deux octets, mais uniquement une valeur relative au bit du signe du résultat comme le font la plupart des implémentations ! Si l'octet pointé par l'adresse s1[i] est inférieur à celui de l'adresse s2[i] nous retournons la valeur -1, 1 sinon.

Si la boucle se termine, c'est la valeur 0 qui est retournée, car dans ce cas le contenu des deux adresses est identique !

Complexité temporelle dans le pire des cas :

Parcours simple de la boucle n fois: complexité en O(n)

V-D. Implémentation

 
Sélectionnez
int c_memcmp (const void * s1, const void * s2, c_size_t n)
{
   const unsigned char * p_s1 = s1;
   const unsigned char * p_s2 = s2;
 
   while (n--)
   {
      if (*p_s1 != *p_s2)
      {
         return *p_s1 < *p_s2 ? -1 : 1;
      }
 
      p_s1++;
      p_s2++;
   }
 
   return 0;
}

Comme précisé dans la description de la fonction, la comparaison se fait par conversion du type void * en type unsigned char *, c'est ce que nous faisons dans cette implémentation en faisant pointer les deux adresses par des pointeurs de ce dernier type !

Dans la condition, nous utilisons l'opérateur ternaire en lieu et place d'une simple condition if…else comme il est décrit dans l'algorithme !

À chaque tour de boucle, nous incrémentons également les deux pointeurs p_s1 et p_s2 pour avancer sur l'octet suivant !

V-E. Tests

 
Sélectionnez
#include "c_string.h"
#include <stdio.h>
 
 
#define TAB_SIZE 4
 
 
int main (void)
{
   unsigned char tab1 [TAB_SIZE] = { 'a', 'b', '\0', 'c' };
   unsigned char tab2 [TAB_SIZE] = { 'a', 'b', '\0', 'c' };
   unsigned char tab3 [TAB_SIZE] = { 'a', 'b', 'c', 'h' };
   unsigned char tab4 [TAB_SIZE] = { 'a', 'b', 'a', 'h' };
 
   printf ("Test 1 : %d\n", c_memcmp (tab1, tab2, TAB_SIZE));
   printf ("Test 2 : %d\n", c_memcmp (tab2, tab3, TAB_SIZE));
   printf ("Test 3 : %d\n", c_memcmp (tab3, tab4, TAB_SIZE));
 
   return 0;
}

Dans ce programme de test, nous faisons trois comparaisons pour vérifier tous les points de la fonction c_memcmp. Nous commençons par un test d'égalité, un test d'infériorité puis pour finir un test de supériorité ! Voici ce que cela donne en sortie sur la console :

 
Sélectionnez
Test 1 : 0
Test 2 : -1
Test 3 : 1
 
Process returned 0 (0x0)   execution time : 0.015 s
Press any key to continue.

précédentsommairesuivant

Copyright © 2007 Franck Hecht. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.