Oui, votre enregistrement est correct, mais il n'est certainement pas le plus efficace (si par "efficacité" tu veux dire que le calcul de l'efficacité). L'évidence intuitive de l'inefficacité de la mise en œuvre est basée sur le fait que lorsque les chaînes en fait se chevauchent, l' strlen
appels itérer sur leur partie commune à deux reprises.
Pour l'amour de la formelle de l'efficacité, on peut utiliser une approche légèrement différente
int are_overlapping(const char *a, const char *b)
{
if (a > b) /* or `(uintptr_t) a > (uintptr_t) b`, see note below! */
{
const char *t = a;
a = b;
b = t;
}
while (a != b && *a != '\0')
++a;
return a == b;
}
Une remarque importante à propos de cette version est qu'elle effectue relationnel comparaison de deux pointeurs qui ne sont pas garantis pour pointer vers le même tableau, qui a officiellement conduit à un comportement indéfini. Il fonctionnera dans la pratique, sur un système de modèle de mémoire fixe, mais pourrait attirer les critiques de pédant code examinateur. Officiellement contourner ce problème, on pourrait convertir les pointeurs pour uintptr_t
avant d'effectuer relationnelle des comparaisons. De cette façon, le comportement indéfini est converti à la mise en œuvre définies par le comportement avec une bonne sémantique pour nos fins, dans la plupart (si pas tous) des implémentations traditionnelles avec le plat de la mémoire de modèle.
Cette approche est libre à partir du "double comptage" problème: il analyse seulement le non-cumul partie de la chaîne qui se trouve "plus haut" dans la mémoire. Bien sûr, dans la pratique, les avantages de cette approche pourrait s'avérer être inexistante. Elle dépendra à la fois de la qualité de votre strlen
de la mise en œuvre et l'une des propriétés de l'entrée effective.
Par exemple, dans cette situation
const char *str = "Very very very long string, say 64K characters long......";
are_overlapped(str, str + 1);
ma version de détecter le chevauchement beaucoup plus rapide que la vôtre. Ma version fera dans 1 itération du cycle, tandis que votre version passerons 2 * 64 K itérations (en supposant une implémentation naïve de l' strlen
).
Si vous décidez de plonger dans le domaine de l'discutable pointeur de comparaison, l'idée ci-dessus peut également être réimplémentée comme
int are_overlapping(const char *a, const char *b)
{
if (a > b)
{
const char *t = a;
a = b;
b = t;
}
return b <= a + strlen(a);
}
Cette mise en œuvre ne permet pas de réaliser un supplément de pointeur de la comparaison de chaque itération. Le prix que nous payons pour cela, c'est qu'il a toujours itère jusqu'à la fin de l'une des chaînes au lieu de s'arrêter au début. Pourtant, il est encore plus efficace que votre mise en œuvre, étant donné qu'elle exige strlen
qu'une seule fois.