2011-12-21 15 views
20

Come faccio il sul posto equivalente di strstr() per un contato stringa (cioè non terminazione null) in C?strstr() una stringa che non è terminazione Null

+3

Dovrai scrivere la tua versione. –

+0

Quale stringa non è terminata con null? La stringa ricercata o la sottostringa? –

+0

@TimCooper: quello cercato (pagliaio). – Mehrdad

risposta

5

Se avete paura di O (m * n) il comportamento - in fondo, non è necessario, tali casi non si verificano in natura - ecco un'implementazione KMP che avevo in giro che ho modificato per prendi la lunghezza del pagliaio. Anche un involucro. Se si desidera effettuare ricerche ripetute, scrivere le proprie e riutilizzare l'array borders.

Nessuna garanzia di bug-freeness, ma sembra che funzioni ancora.

int *kmp_borders(char *needle, size_t nlen){ 
    if (!needle) return NULL; 
    int i, j, *borders = malloc((nlen+1)*sizeof(*borders)); 
    if (!borders) return NULL; 
    i = 0; 
    j = -1; 
    borders[i] = j; 
    while((size_t)i < nlen){ 
     while(j >= 0 && needle[i] != needle[j]){ 
      j = borders[j]; 
     } 
     ++i; 
     ++j; 
     borders[i] = j; 
    } 
    return borders; 
} 

char *kmp_search(char *haystack, size_t haylen, char *needle, size_t nlen, int *borders){ 
    size_t max_index = haylen-nlen, i = 0, j = 0; 
    while(i <= max_index){ 
     while(j < nlen && *haystack && needle[j] == *haystack){ 
      ++j; 
      ++haystack; 
     } 
     if (j == nlen){ 
      return haystack-nlen; 
     } 
     if (!(*haystack)){ 
      return NULL; 
     } 
     if (j == 0){ 
      ++haystack; 
      ++i; 
     } else { 
      do{ 
       i += j - (size_t)borders[j]; 
       j = borders[j]; 
      }while(j > 0 && needle[j] != *haystack); 
     } 
    } 
    return NULL; 
} 

char *sstrnstr(char *haystack, char *needle, size_t haylen){ 
    if (!haystack || !needle){ 
     return NULL; 
    } 
    size_t nlen = strlen(needle); 
    if (haylen < nlen){ 
     return NULL; 
    } 
    int *borders = kmp_borders(needle, nlen); 
    if (!borders){ 
     return NULL; 
    } 
    char *match = kmp_search(haystack, haylen, needle, nlen, borders); 
    free(borders); 
    return match; 
} 
+0

: Oh Oh wow, lo proverò sicuramente! Grazie! :) – Mehrdad

5

Verificare se la funzione seguente funziona correttamente. Non l'ho testato a fondo, quindi ti suggerisco di farlo.

char *sstrstr(char *haystack, char *needle, size_t length) 
{ 
    size_t needle_length = strlen(needle); 
    size_t i; 

    for (i = 0; i < length; i++) 
    { 
     if (i + needle_length > length) 
     { 
      return NULL; 
     } 

     if (strncmp(&haystack[i], needle, needle_length) == 0) 
     { 
      return &haystack[i]; 
     } 
    } 
    return NULL; 
} 
+0

Questo è in realtà simile a quello che sto attualmente usando, ma è O (mn), mentre (sto assumendo) 'strstr' è O (m + n). Quindi sto cercando qualcosa che non sia ridicolmente lento come la mia versione. :-) Ma +1 comunque, dato che l'idea funziona. – Mehrdad

+0

@Mehrdad: Potrebbe valerne la pena dare un'occhiata a questa implementazione: http://src.gnu-darwin.org/src/lib/libc/string/strnstr.c.html –

+0

Wow, immagino di aver sbagliato allora ... quindi 'strstr' è tipicamente definito come un'operazione di O (mn) ?? Grazie per averlo sottolineato ... allora probabilmente accetterò questo entro un po ', poiché è l'esatto sostituto della domanda. – Mehrdad

2

Mi sono appena imbattuto in questo e mi piacerebbe condividere la mia implementazione. Penso che sia abbastanza veloce a non ho alcun sottolivello.

Restituisce l'indice nel pagliaio dove viene trovato l'ago o -1 se non è stato trovato.

+1

Dovresti andare avanti e farlo Boyer-Moore mentre eri lì;) –

Problemi correlati