“ Řetězec ” obsahuje funkci v C

Tato funkce kontroluje bez ohledu na to, zda podřetězec needle existuje v jiném řetězci haystack a vrátí pozici, pokud ano, nebo 0, pokud ne, pokud pozice je 0, v takovém případě nebude nalezena.

Hledá způsoby, jak vylepšit tento kód, konkrétně lepší zpracování chyb.

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

Komentáře

  • Přidejte několik příkladů, abyste přesně ukázali, co máte na mysli, když řeknete, že " obsahuje ". Pochybuji, že váš kód funguje, jak bylo zamýšleno.
  • Toto již existuje: strstr(). ' Existuje bezpečnější verze s názvem strnstr(). Implementaci najdete zde: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: proč, můžete to vysvětlit?
  • Mělo by contains("tt", "test") vrátit true?
  • @ CacahueteFrito Takže platíte nezanedbatelné náklady na použitelnost a výkonu za maskování poškození dat za výjimečných okolností, místo abyste se spoléhali na invarianty svých programů, opravovali data nebo hlásili chybu? To se zdá být všude špatný nápad.

Odpověď

Několik poznámek:

  • Za poslední řádek byste měli přidat nový řádek:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Nevím, co kompilátor, který používáte, ale při kompilaci s gcc a -Wall -Wextra -pedantic získáte:

    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; ^ 
  • Formátování kódu by mělo být konzistentnější. Například v tomto řádku vložíte mezery před needle, ale mezery před nimi nevložíte haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu není přenosný specifikátor pro typ size_t, měli byste použít %zu zavedený v C99.

  • Řekli jste:

vrátí pozici, pokud ano, nebo 0, pokud ne, pokud pozice je 0, v takovém případě nebude nalezena.

To opravdu není dobré. Například s tímto vrátí 0:

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

S tímto také vrátí nulu:

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

V těchto dvou příkladech nerozeznáte rozdíl mezi úspěchem a neúspěchem. Ve skutečnosti má atoi() stejný problém. Nevím, jaký operační systém používáte ale možná byste mohli použít ssize_t jako návratový typ, pokud je k dispozici, a návrat -1 v případě selhání.

Odpověď

Přidání k předchozí odpovědi od @Arkadiusze Drabczyka:

Může být jednoduchá, triviální implementace contains provedeno takto:

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

Poté by tento program (s několika výše uvedenými změnami) měl fungovat:

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

Výstup:

Pozice: 18
Pozice: -1

Komentáře

  • Odstranil bych kontrolu, zda vstup nemá NULL, a ju k tomu použijte jazykovou příponu (__attribute__((nonnull)) v GCC). NULL je něco, co byste jako vstup pro tuto funkci nikdy nečekali, a přidává jeden nebo dva zbytečné řádky kódu. Raději bych do dokumentace funkce napsal něco jako: " Pokud je vstupem této funkce ukazatel NULL, chování není definováno. ".
  • @CacahueteFrito Původní kód to udělal a já chci usilovat o kompatibilitu (kdo ví, jak jej OP používal?).
  • Chybějící zahrnutí pro ssize_t: #include <sys/types.h>. Další možností by bylo použít ptrdiff_t místo z #include <stddef.h>; ve skutečnosti vracíte rozdíl ukazatele: ? needle_in_haystack - haystack :

odpověď

Váš kód nefunguje. Vrací 0 pro haystack "abbc" a needle "bc", přestože haystack obsahuje needle .

Odpověď

Nepotřebujete první smyčku a všechny výpočty délky. Btw., Funkce není úspěšná, pokud je nalezen první znak, ale pouze druhý výskyt prvního znaku zapadá do jehly.

Úkol lze zredukovat na několik řádků:

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

Komentáře

  • Jaký je dobrý způsob, jak se zlepšit při psaní kompaktnějšího a efektivnějšího C kódu, jako je tento ?Toto třídění mi připomíná K & R C.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *