Questa funzione controlla se una sottostringa needle
esiste o meno in unaltra stringa haystack
e restituisce la posizione se lo fa o 0 se non “t, a meno che il la posizione è 0, nel qual caso non verrà individuata.
Alla ricerca di modi per migliorare questo codice, in particolare una migliore gestione degli errori.
#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; }
Commenti
Risposta
Solo un paio di osservazioni:
-
Dovresti aggiungere una nuova riga dopo lultima riga:
$ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $
-
Non so cosa compilatore che utilizzi ma con quando compilato con
gcc
e-Wall -Wextra -pedantic
ottieni: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; ^
-
La formattazione del codice dovrebbe essere più coerente. Ad esempio, in questa riga inserisci uno spazio bianco prima di
needle
ma non inserire uno spazio bianco primahaystack
:size_t contains(const char * needle, const char *haystack);
-
%lu
non è uno specificatore portabile per il tiposize_t
, dovresti utilizzare%zu
introdotto in C99. -
Hai detto:
restituisce la posizione se lo fa o 0 se non lo fa “t, a meno che il la posizione è 0, nel qual caso non verrà “individuata”.
Questo non è davvero buono. Ad esempio, con questo restituisce 0:
char *needle = "This"; char *haystack = "This is a dinosaurtest.";
Con questo, restituisce anche zero:
char *needle = "non-existent"; char *haystack = "This is a dinosaurtest.";
Non puoi dire la differenza tra successo e fallimento in questi due esempi. In realtà, atoi()
ha lo stesso problema. Non so quale sistema operativo utilizzi ma forse potresti usare ssize_t
come tipo di ritorno se è disponibile e restituire -1 in caso di errore.
Risposta
Aggiungendo alla risposta precedente di @Arkadiusz Drabczyk:
Una semplice, banale implementazione di contains
potrebbe essere fatto in questo modo:
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; }
Quindi, questo programma (con alcune modifiche come menzionato sopra) dovrebbe funzionare:
#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; }
Risultato:
Posizione: 18
Posizione: -1
Commenti
- Rimuoverei il controllo che linput non sia NULL e ju st usa unestensione del linguaggio per questo (
__attribute__((nonnull))
in GCC).NULL
è qualcosa che non ti aspetteresti mai come input per questa funzione e aggiunge una o due righe di codice non necessarie. Preferirei scrivere nella documentazione della funzione qualcosa del tipo: ” Se linput di questa funzione è un puntatore NULL, il comportamento è indefinito. “. - @CacahueteFrito Il codice originale lo ha fatto e voglio lottare per la compatibilità (chissà come lo stava usando lOP?).
- Manca include per
ssize_t
:#include <sys/types.h>
. Unaltra opzione potrebbe essere quella di utilizzareptrdiff_t
da#include <stddef.h>
; stai effettivamente restituendo una differenza di puntatore:? needle_in_haystack - haystack :
Risposta
Il codice non “funziona. Restituisce 0
per haystack
"abbc"
e needle
"bc"
, anche se haystack
contiene needle
.
Risposta
Non hai bisogno del primo ciclo e di tutti i calcoli della lunghezza. A proposito, la funzione non riesce, se viene trovato il primo carattere, ma solo la seconda occorrenza del primo carattere si adatta allago.
Lattività può essere ridotta a poche righe:
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; }
Commenti
- Qual è un buon modo per migliorare nella scrittura di codice C più compatto ed efficiente come questo ?Questo mi ricorda una specie di K & R C.
strstr()
. Esiste ‘ una versione più sicura chiamatastrnstr()
. Puoi trovare unimplementazione qui: github.com/lattera/freebsd/blob/master/lib/libc/string/…contains("tt", "test")
restituire true?