¿Cómo verificar si una cadena comienza con otra cadena en C?

¿Hay algo así como startsWith(str_a, str_b) en la biblioteca C estándar?

Debería tomar punteros a dos cadenas que terminan con nullbytes, y decirme si la primera también aparece completamente al comienzo de la segunda.

Ejemplos:

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

Aparentemente no hay una función C estándar para esto. Asi que:

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

Tenga en cuenta que lo anterior es agradable y claro, pero si lo hace en un bucle cerrado o si trabaja con cadenas muy grandes, es posible que no ofrezca el mejor rendimiento, ya que escanea la longitud total de ambas cadenas al frente ( strlen ). Las soluciones como wj32 o Christoph's pueden ofrecer un mejor rendimiento (aunque este comentario sobre la vectorización está más allá de mi conocimiento de C). También tenga en cuenta la solución de Fred Foo que evita strlen en str (tiene razón, es innecesario). Solo importa para cuerdas (muy) grandes o uso repetido en bucles apretados, pero cuando importa, importa.

No hay una función estándar para esto, pero puede definir

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

No tenemos que preocuparnos de que str sea ​​más corto que el pre porque de acuerdo con el estándar C (7.21.4.4/2):

La función strncmp no compara más de n caracteres (los caracteres que siguen a un carácter nulo no se comparan) de la matriz apuntada por s1 a la matriz apuntada por s2 . ”

Probablemente vaya con strncmp() , pero solo por diversión una implementación sin strncmp() :

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

No soy un experto en escribir código elegante, pero …

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

Use la función strstr() . Stra == strstr(stra, strb)

Debido a que ejecuté la versión aceptada y tuve un problema con una versión muy larga, tuve que agregar la siguiente lógica:

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

Optimizado (v.2. – corregido):

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

Optimizado:

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