“ String ” bevat functie in C

Deze functie controleert of een deelstring needle bestaat in een andere tekenreeks haystack en de positie retourneert als dit het geval is of 0 als dit niet het geval is, tenzij de positie is 0, in welk geval het “niet wordt gelokaliseerd.

Op zoek naar manieren om deze code te verbeteren, met name een betere foutafhandeling.

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

Reacties

  • Voeg enkele voorbeelden toe om precies te laten zien wat je bedoelt door te zeggen dat ” . Ik betwijfel of uw code werkt zoals bedoeld.
  • Deze bestaat al: strstr(). Er is ‘ een veiligere versie genaamd strnstr(). U kunt hier een implementatie vinden: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: waarom, kun je het uitleggen?
  • Moet contains("tt", "test") true retourneren?
  • @ CacahueteFrito Dus je betaalt een niet onaanzienlijke prijs in bruikbaarheid en prestaties om datacorruptie in sommige zeldzame omstandigheden te maskeren, in plaats van te vertrouwen op de invarianten van je programma, de data te patchen of de fout te rapporteren? Dat lijkt overal een slecht idee.

Antwoord

Slechts een paar opmerkingen:

  • Je moet een nieuwe regel toevoegen na de laatste regel:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Ik weet niet wat compiler die je gebruikt maar waarmee je compileert met gcc en -Wall -Wextra -pedantic krijg je:

    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; ^ 
  • Code-opmaak zou meer consistent moeten zijn. In deze regel zet je bijvoorbeeld een witruimte voor needle maar zet je geen witruimte ervoor haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu is geen draagbare specificatie voor size_t type, je zou %zu geïntroduceerd in C99 moeten gebruiken.

  • U zei:

geeft de positie terug als dit het geval is of 0 als dit niet het geval is, tenzij de positie is 0, in welk geval het “niet wordt gelokaliseerd.

Dit is echt niet goed. Hiermee wordt bijvoorbeeld 0 geretourneerd:

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

Hiermee wordt ook nul geretourneerd:

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

U kunt in deze twee voorbeelden “geen verschil zien tussen succes en mislukking. In feite heeft atoi() hetzelfde probleem. Ik weet niet welk besturingssysteem u gebruikt maar misschien kun je ssize_t gebruiken als het retourtype als het beschikbaar is en -1 retourneren in geval van een fout.

Antwoord

Toevoegen aan het vorige antwoord door @Arkadiusz Drabczyk:

Een eenvoudige, triviale implementatie van contains zou kunnen zijn doe je als volgt:

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

Dan zou dit programma (met een paar wijzigingen zoals hierboven vermeld) moeten werken:

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

Uitvoer:

Positie: 18
Positie: -1

Reacties

  • Ik zou het vinkje verwijderen dat de invoer niet NULL is, en ju Gebruik daarvoor een taalextensie (__attribute__((nonnull)) in GCC). NULL is iets dat je nooit zou verwachten als invoer voor deze functie, en het voegt een of twee onnodige regels code toe. Ik zou liever in de documentatie van de functie iets schrijven als: ” Als de invoer voor deze functie een NULL-pointer is, is het gedrag ongedefinieerd. “.
  • @CacahueteFrito De originele code deed het, en ik wil streven naar compatibiliteit (wie weet hoe het OP het gebruikte?).
  • Ontbrekende include voor ssize_t: #include <sys/types.h>. Een andere optie zou zijn om in plaats daarvan ptrdiff_t te gebruiken, van #include <stddef.h>; je geeft eigenlijk een pointer-verschil terug: ? needle_in_haystack - haystack :

Answer

Uw code werkt niet. Het retourneert 0 voor haystack "abbc" en needle "bc", ook al bevat haystack needle .

Antwoord

Je hebt de eerste lus en alle lengteberekeningen niet nodig. Trouwens, de functie slaagt niet als het eerste teken wordt gevonden, maar alleen het tweede voorkomen van het eerste teken past met de naald.

De taak kan worden teruggebracht tot een paar regels:

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

Reacties

  • Wat is een goede manier om beter te worden in het schrijven van compactere, efficiëntere C-code zoals deze ?Dit soort doet me denken aan K & R C.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *