V. c_memcmp▲
V-A. Prototype▲
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 :
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▲
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▲
#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 :
Test 1 : 0
Test 2 : -1
Test 3 : 1
Process returned 0 (0x0) execution time : 0.015 s
Press any key to continue.