“ Streng ” inneholder funksjon i C

Denne funksjonen sjekker hvorvidt en understreng needle eksisterer i en annen streng haystack og returnerer posisjonen hvis den gjør det eller 0 hvis den ikke gjør det, med mindre posisjon er 0, i så fall vil den ikke bli lokalisert.

Leter du etter måter å forbedre denne koden, spesielt bedre feilhå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

  • Legg til noen eksempler for å vise nøyaktig hva du mener ved å si » inneholder «. Jeg tviler på at koden din fungerer etter hensikten.
  • Dette eksisterer allerede: strstr(). Der er ‘ en tryggere versjon kalt strnstr(). Du finner en implementering her: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: hvorfor, kan du forklare?
  • Skal contains("tt", "test") bli sant?
  • @ CacahueteFrito Så, du betaler en ikke ubetydelig kostnad i brukervennlighet og ytelse for å maskere datakorrupsjon i noen sjeldne tilfeller, i stedet for å stole på programmene dine, lappe dataene eller rapportere feilen? Det virker som en dårlig idé rundt.

Svar

Bare et par bemerkninger:

  • Du bør legge til en ny linje etter siste linje:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Jeg vet ikke hva kompilator du bruker, men med når du 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 bør være mer konsistent. For eksempel, i denne linjen setter du et mellomrom før needle men ikke legger et mellomrom før haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu er ikke en bærbar spesifikator for size_t -type, du bør bruke %zu introdusert i C99.

  • Du sa:

returnerer posisjonen hvis den gjør det eller 0 hvis den ikke gjør det, med mindre posisjon er 0, i så fall vil den ikke bli lokalisert.

Dette er virkelig ikke bra. For eksempel returnerer den 0:

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

Med dette returnerer den også null:

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

Du kan ikke se forskjellen mellom suksess og fiasko i disse to eksemplene. Egentlig har atoi() det samme problemet. Jeg vet ikke hvilket operativsystem du bruker men kanskje du kan bruke ssize_t som returtype hvis den er tilgjengelig og returnere -1 i tilfelle feil.

Svar

Legge til i forrige svar av @Arkadiusz Drabczyk:

En enkel, triviell implementering av contains gjort slik:

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

Dette programmet (med noen få endringer som nevnt ovenfor) skal 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; } 

Utgang:

Posisjon: 18
Posisjon: -1

Kommentarer

  • Jeg fjerner sjekken om at inngangen ikke er NULL, og ju st bruk et språkutvidelse for det (__attribute__((nonnull)) i GCC). NULL er noe du aldri forventer som input for denne funksjonen, og den legger til en eller to unødvendige kodelinjer. Jeg foretrekker å skrive i dokumentasjonen til funksjonen omtrent som: » Hvis inngangen til denne funksjonen er en NULL-peker, er oppførselen udefinert. «.
  • @CacahueteFrito Den opprinnelige koden gjorde det, og jeg vil streve for kompatibilitet (hvem vet hvordan OPEN brukte den?).
  • Mangler inkluderer for ssize_t: #include <sys/types.h>. Et annet alternativ ville være å bruke ptrdiff_t i stedet, fra #include <stddef.h>; du returnerer faktisk en pekeforskjell: ? needle_in_haystack - haystack :

Svar

Koden din fungerer ikke. Den returnerer 0 for haystack "abbc" og needle "bc", selv om haystack inneholder needle .

Svar

Du trenger ikke den første sløyfen og alle lengdeberegningene. Btw., Funksjonen lykkes ikke hvis den første røya blir funnet, men bare den andre forekomsten av den første røya passer med nål.

Oppgaven kan reduseres til noen få 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

  • Hva er en god måte å bli bedre på å skrive mer kompakt, effektiv C-kode som denne ?Denne sorta minner meg om K & R C.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *