“ String ” contient une fonction en C

Cette fonction vérifie si une sous-chaîne needle existe ou non dans une autre chaîne haystack et renvoie la position si oui ou 0 si ce n’est pas le cas, sauf si le la position est 0, auquel cas il ne sera pas localisé.

Recherche de moyens daméliorer ce code, en particulier une meilleure gestion des erreurs.

#include <stdio.h> #include <stdlib.h> #include <string.h> size_t contains(const char * needle, const char *haystack); int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; printf("Position: %lu", contains(needle, haystack)); return EXIT_SUCCESS; } size_t contains(const char * needle, const char *haystack) { if(needle == NULL || haystack == NULL) { return 0; } long int first_char_pos = -1; size_t len_h = strlen(haystack); size_t len_n = strlen(needle); size_t i, j; size_t exist_count = 0; // Find the first character. If it doesn"t exist, we"re done. for(i = 0; i < len_h; i++) { if((haystack[i] == needle[0]) && (first_char_pos == -1)) { first_char_pos = i; exist_count++; } } if(first_char_pos == -1) { return 0; } printf("First char match index: %li\n", first_char_pos); printf("Char: %c\n", haystack[first_char_pos]); size_t current_index = (size_t) first_char_pos; for(i = first_char_pos; i < len_h; i++) { if(haystack[i] == needle[exist_count] && (i == (current_index + 1))) { current_index = i; exist_count++; } printf("Exist count: %lu\n", exist_count); //<--Debugging if(exist_count == len_n) { return first_char_pos; } } return 0; } 

Commentaires

  • Veuillez ajouter quelques exemples pour montrer exactement ce que vous entendez en disant  » contient « . Je doute que votre code fonctionne comme prévu.
  • Cela existe déjà: strstr(). Il existe ‘ une version plus sûre appelée strnstr(). Vous pouvez trouver une implémentation ici: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: pourquoi, pouvez-vous expliquer?
  • Est-ce que contains("tt", "test") renvoie true?
  • @ CacahueteFrito Donc, vous payez un coût non négligeable en convivialité et pour masquer la corruption des données dans de rares circonstances, au lieu de vous fier aux invariants de vos programmes, de corriger les données ou de signaler lerreur? Cela semble une mauvaise idée.

Réponse

Juste quelques remarques:

  • Vous devriez ajouter une nouvelle ligne après la dernière ligne:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Je ne sais pas quoi compilateur que vous utilisez mais avec une fois compilé avec gcc et -Wall -Wextra -pedantic vous obtenez:

    gcc -O2 nh.c -lm -o nh -Wall -Wextra -pedantic nh.c: In function ‘contains’: nh.c:25:15: warning: unused variable ‘j’ [-Wunused-variable] size_t i, j; ^ 
  • La mise en forme du code doit être plus cohérente. Par exemple, dans cette ligne, vous mettez un espace avant needle mais ne mettez pas despace avant haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu nest pas un spécificateur portable pour le type size_t, vous devez utiliser %zu introduit dans C99.

  • Vous avez dit:

renvoie la position si cest le cas ou 0 si ce nest pas le cas, sauf si le la position est 0, auquel cas, il « ne sera pas localisé.

Ce nest vraiment pas bon. Par exemple, avec ceci, il renvoie 0:

char *needle = "This"; char *haystack = "This is a dinosaurtest."; 

Avec ceci, il renvoie également zéro:

char *needle = "non-existent"; char *haystack = "This is a dinosaurtest."; 

Vous ne pouvez « pas faire la différence entre le succès et léchec dans ces deux exemples. En fait, atoi() a le même problème. Je ne sais pas quel système dexploitation vous utilisez mais peut-être que vous pourriez utiliser ssize_t comme type de retour sil est disponible et renvoyer -1 en cas déchec.

Réponse

Pour compléter la réponse précédente de @Arkadiusz Drabczyk:

Une implémentation simple et triviale de contains pourrait être fait comme ceci:

ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } 

Ensuite, ce programme (avec quelques changements comme mentionné ci-dessus) devrait fonctionner:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; char *haystack2 = "This does not contain the string."; printf("Position: %zd\n", contains(needle, haystack)); printf("Position: %zd\n", contains(needle, haystack2)); return EXIT_SUCCESS; } 

Résultat:

Position: 18
Position: -1

Commentaires

  • Je supprimerais la vérification que lentrée nest pas NULL, et ju st utiliser une extension de langue pour cela (__attribute__((nonnull)) dans GCC). NULL est quelque chose auquel vous ne vous attendriez jamais comme entrée pour cette fonction, et il ajoute une ou deux lignes de code inutiles. Je préférerais écrire dans la documentation de la fonction quelque chose comme:  » Si lentrée de cette fonction est un pointeur NULL, le comportement nest pas défini. « .
  • @CacahueteFrito Le code dorigine la fait, et je veux rechercher la compatibilité (qui sait comment lOP lutilisait?).
  • Inclusion manquante pour ssize_t: #include <sys/types.h>. Une autre option serait dutiliser à la place ptrdiff_t, de #include <stddef.h>; vous renvoyez en fait une différence de pointeur: ? needle_in_haystack - haystack :

Answer

Votre code ne fonctionne pas. Il renvoie 0 pour haystack "abbc" et needle "bc", même si haystack contient needle .

Réponse

Vous navez pas besoin de la première boucle et de tous les calculs de longueur. Btw., La fonction ne réussit pas, si le premier caractère est trouvé, mais seule la deuxième occurrence du premier caractère correspond à laiguille.

La tâche peut être réduite à quelques lignes:

int contains(char *buf, char *needle) { char *src, *srch, *srcp; for(src=buf; *src; src++) { for(srch = needle, srcp = src; *srch && *srcp && *srch == *srcp; srch++, srcp++); if(!*srch) return src - buf; } return -1; } 

Commentaires

  • Quel est un bon moyen daméliorer lécriture de code C plus compact et efficace comme celui-ci ?Cela me rappelle K & R C.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *