“ Stringa ” contiene una funzione in C

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

  • Aggiungi alcuni esempi per mostrare esattamente cosa intendi dicendo che ” contiene “. Dubito che il tuo codice funzioni come previsto.
  • Questo esiste già: strstr(). Esiste ‘ una versione più sicura chiamata strnstr(). Puoi trovare unimplementazione qui: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: perché, puoi spiegare?
  • contains("tt", "test") restituire true?
  • @ CacahueteFrito Quindi, paghi un costo non trascurabile in usabilità e prestazioni per mascherare il danneggiamento dei dati in alcune rare circostanze, invece di fare affidamento sulle invarianti dei tuoi programmi, patchare i dati o segnalare lerrore? Sembra una cattiva idea.

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 prima haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu non è uno specificatore portabile per il tipo size_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 utilizzare ptrdiff_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.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *