Come verificare se una stringa inizia con un’altra stringa in C?

C’è qualcosa come startsWith(str_a, str_b) nella libreria C standard?

Dovrebbe portare i puntatori a due stringhe che terminano con nullbyte e dirmi se anche il primo appare completamente all’inizio del secondo.

Esempi:

 "abc", "abcdef" -> true "abcdef", "abc" -> false "abd", "abdcef" -> true "abc", "abc" -> true 

Apparentemente non esiste una funzione C standard per questo. Così:

 bool startsWith(const char *pre, const char *str) { size_t lenpre = strlen(pre), lenstr = strlen(str); return lenstr < lenpre ? false : strncmp(pre, str, lenpre) == 0; } 

Nota che quanto sopra è bello e chiaro, ma se lo stai facendo in un loop stretto o lavorando con stringhe molto grandi, potrebbe non offrire le migliori prestazioni, poiché analizza l'intera lunghezza di entrambe le stringhe in primo piano ( strlen ). Soluzioni come wj32 o Christoph possono offrire prestazioni migliori (anche se questo commento sulla vettorizzazione è al di là della mia comprensione di C). Nota anche la soluzione di Fred Foo che evita strlen on str (ha ragione, non è necessario). Importa solo stringhe (molto) grandi o uso ripetuto in cicli stretti, ma quando è importante, conta.

Non esiste una funzione standard per questo, ma puoi definire

 bool prefix(const char *pre, const char *str) { return strncmp(pre, str, strlen(pre)) == 0; } 

Non dobbiamo preoccuparci che str sia più corto del pre perché secondo lo standard C (7.21.4.4/2):

La funzione strncmp confronta non più di n caratteri (i caratteri che seguono un carattere nullo non vengono confrontati) dalla matrice puntata da s1 alla matrice puntata da s2 . ”

Probabilmente andrei con strncmp() , ma solo per divertirmi con un’implementazione grezza:

 _Bool starts_with(const char *restrict string, const char *restrict prefix) { while(*prefix) { if(*prefix++ != *string++) return 0; } return 1; } 

Non sono esperto nella scrittura di codice elegante, ma …

 int prefix(const char *pre, const char *str) { char cp; char cs; if (!*pre) return 1; while ((cp = *pre++) && (cs = *str++)) { if (cp != cs) return 0; } if (!cs) return 0; return 1; } 

Usa la funzione strstr() . Stra == strstr(stra, strb)

Perché ho eseguito la versione accettata e ho avuto un problema con un lunghissimo str, ho dovuto aggiungere la seguente logica:

 bool longEnough(const char *str, int min_length) { int length = 0; while (str[length] && length < min_length) length++; if (length == min_length) return true; return false; } bool startsWith(const char *pre, const char *str) { size_t lenpre = strlen(pre); return longEnough(str, lenpre) ? strncmp(str, pre, lenpre) == 0 : false; } 

Ottimizzato (v.2. Corretto):

 uint32 startsWith( const void* prefix_, const void* str_ ) { uint8 _cp, _cs; const uint8* _pr = (uint8*) prefix_; const uint8* _str = (uint8*) str_; while ( ( _cs = *_str++ ) & ( _cp = *_pr++ ) ) { if ( _cp != _cs ) return 0; } return !_cp; } 

ottimizzata:

 boolean StartsWith(char *s1, char *s2) { while (*s1++ == *s2++) { } return *s2 == 0; }