“ Șirul ” conține funcția în C

Această funcție verifică dacă există sau nu un subșir needle există într-un alt șir haystack și returnează poziția dacă există sau 0 dacă nu „t, cu excepția cazului în care poziția este 0, caz în care nu va fi localizat.

Căutați modalități de a îmbunătăți acest cod, în special o mai bună gestionare a erorilor.

#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; } 

Comentarii

  • Vă rugăm să adăugați câteva exemple pentru a arăta exact ce vreți să spuneți ” conține „. Mă îndoiesc că codul dvs. funcționează conform intenției.
  • Acest lucru există deja: strstr(). Există ‘ o versiune mai sigură numită strnstr(). Puteți găsi o implementare aici: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: de ce, puteți explica?
  • Ar trebui ca contains("tt", "test") să revină adevărat?
  • @ CacahueteFrito Deci, veți plăti un cost deloc de neglijat în ceea ce privește utilizabilitatea și performanța pentru a masca corupția datelor în unele circumstanțe rare, în loc să vă bazați pe invarianții programelor dvs., corecția datelor sau raportarea erorii? Pare o idee proastă în jur.

Răspuns

Doar câteva observații:

  • Ar trebui să adăugați o linie nouă după ultima linie:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Nu știu ce compilator pe care îl utilizați, dar când este compilat cu gcc și -Wall -Wextra -pedantic veți obține:

    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; ^ 
  • Formatarea codului ar trebui să fie mai consistentă. De exemplu, în această linie puneți un spațiu înainte de needle, dar nu puneți un spațiu înainte haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu nu este un specificator portabil pentru tipul size_t, ar trebui să utilizați %zu introdus în C99.

  • Ați spus:

returnează poziția dacă o face sau 0 dacă nu, cu excepția cazului în care poziția este 0, caz în care nu va fi localizat.

Acest lucru nu este chiar bun. De exemplu, cu aceasta returnează 0:

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

Cu aceasta, returnează și zero:

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

Nu puteți face diferența dintre succes și eșec în aceste două exemple. De fapt, atoi() are aceeași problemă. Nu știu ce sistem de operare utilizați dar poate ați putea folosi ssize_t ca tip de returnare dacă este disponibil și returnează -1 în caz de eșec.

Răspuns

Adăugarea la răspunsul anterior de către @Arkadiusz Drabczyk:

O implementare simplă și banală a contains realizat astfel:

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; } 

Apoi, acest program (cu câteva modificări menționate mai sus) ar trebui să funcționeze:

#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; } 

Ieșire:

Poziție: 18
Poziție: -1

Comentarii

  • Aș elimina verificarea dacă intrarea nu este NULĂ și ju Folosiți o extensie de limbă pentru aceasta (__attribute__((nonnull)) în GCC). NULL este ceva la care nu v-ați aștepta niciodată ca intrare pentru această funcție și adaugă una sau două linii de cod inutile. Aș prefera să scriu în documentația funcției ceva de genul: ” Dacă intrarea pentru această funcție este un pointer NULL, comportamentul este nedefinit. „.
  • @CacahueteFrito Codul original a făcut-o și vreau să mă străduiesc pentru compatibilitate (cine știe cum îl folosea OP?).
  • Lipsește includerea pentru ssize_t: #include <sys/types.h>. O altă opțiune ar fi să folosiți ptrdiff_t în schimb, din #include <stddef.h>; întoarceți de fapt o diferență de pointer: ? needle_in_haystack - haystack :

Răspuns

Codul dvs. nu funcționează. Returnează 0 pentru haystack "abbc" și needle "bc", chiar dacă haystack conține needle .

Răspuns

Nu aveți nevoie de prima buclă și de toate calculele de lungime. De altfel, funcția nu reușește, dacă se găsește primul caracter, dar numai al doilea ocurență al primului caracter se potrivește cu acul.

Sarcina poate fi redusă la câteva linii:

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; } 

Comentarii

  • Ce este o modalitate bună de a obține mai bine la scrierea unui cod C mai compact și mai eficient ca acesta ?Această sortă îmi amintește de K & R C.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *