“ Streng ” indeholder funktion i C

Denne funktion kontrollerer om der findes en understreng needle i en anden streng haystack eller returnerer positionen, hvis den gør det, eller 0, hvis den ikke gør det, medmindre position er 0, i hvilket tilfælde den ikke bliver placeret.

På udkig efter måder at forbedre denne kode på, specifikt bedre fejlhåndtering.

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

Kommentarer

  • Tilføj venligst nogle eksempler for at vise nøjagtigt hvad du mener ved at sige ” indeholder “. Jeg tvivler på, at din kode fungerer efter hensigten.
  • Dette findes allerede: strstr(). Der ‘ er en sikrere version kaldet strnstr(). Du kan finde en implementering her: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: hvorfor, kan du forklare?
  • Skal contains("tt", "test") returnere sandt?
  • @ CacahueteFrito Så betaler du en ikke ubetydelig pris i brugbarhed og ydeevne for at maskere datakorruption under nogle sjældne omstændigheder i stedet for at stole på dine programmer invariantere, lappe dataene eller rapportere fejlen? Det virker som en dårlig idé rundt omkring.

Svar

Bare et par bemærkninger:

  • Du skal tilføje en ny linje efter den sidste linje:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Jeg ved ikke hvad kompilator, du bruger, men med når den kompileres med gcc og -Wall -Wextra -pedantic får du:

    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; ^ 
  • Kodeformatering skal være mere ensartet. For eksempel sætter du i dette felt et mellemrum før needle men sætter ikke et mellemrum før haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu er ikke en bærbar specifikator for size_t type, skal du bruge %zu introduceret i C99.

  • Du sagde:

returnerer positionen, hvis den gør det, eller 0 hvis den ikke gør det, medmindre position er 0, i hvilket tilfælde den ikke bliver placeret.

Dette er virkelig ikke godt. For eksempel returnerer dette 0:

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

Med dette returnerer det også nul:

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

Du kan ikke se forskellen mellem succes og fiasko i disse to eksempler. Faktisk har atoi() det samme problem. Jeg ved ikke, hvilket operativsystem du bruger men måske kan du bruge ssize_t som returtype, hvis den er tilgængelig, og returnere -1 i tilfælde af fejl.

Svar

Tilføjelse til det forrige svar af @Arkadiusz Drabczyk:

En enkel, triviel implementering af contains gjort sådan:

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

Derefter skal dette program (med et par ændringer som nævnt ovenfor) fungere:

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

Output:

Position: 18
Position: -1

Kommentarer

  • Jeg fjerner afkrydsningen af, at input ikke er NULL, og ju brug en sprogudvidelse til det (__attribute__((nonnull)) i GCC). NULL er noget, du aldrig ville forvente som input til denne funktion, og det tilføjer en eller to unødvendige kodelinjer. Jeg foretrækker at skrive i dokumentationen til funktionen sådan: ” Hvis input til denne funktion er en NULL-markør, er adfærden udefineret. “.
  • @CacahueteFrito Den oprindelige kode gjorde det, og jeg vil stræbe efter kompatibilitet (hvem ved, hvordan OPen brugte den?).
  • Mangler inkluderer for ssize_t: #include <sys/types.h>. En anden mulighed ville være at bruge ptrdiff_t i stedet fra #include <stddef.h>; du returnerer faktisk en markørforskel: ? needle_in_haystack - haystack :

Svar

Din kode fungerer ikke. Den returnerer 0 til haystack "abbc" og needle "bc", selvom haystack indeholder needle .

Svar

Du behøver ikke den første sløjfe og alle længdeberegningerne. Btw., Funktionen lykkes ikke, hvis den første char findes, men kun den anden forekomst af den første char passer med nålen.

Opgaven kan reduceres til et par linjer:

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

Kommentarer

  • Hvad er en god måde at blive bedre til at skrive mere kompakt, effektiv C-kode som denne ?Denne slags minder mig om K & R C.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *