“ String ” contiene la función en C

Esta función comprueba si existe o no una subcadena needle en otra cadena haystack y devuelve la posición si lo hace o 0 si no lo hace, a menos que el la posición es 0, en cuyo caso, no será localizado.

Buscando formas de mejorar este código, específicamente un mejor manejo de errores.

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

Comentarios

  • Agrega algunos ejemplos para mostrar exactamente lo que quieres decir al decir » contiene «. Dudo que su código funcione según lo previsto.
  • Esto ya existe: strstr(). Existe ‘ una versión más segura llamada strnstr(). Puede encontrar una implementación aquí: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: ¿por qué, puedes explicarlo?
  • ¿Debería contains("tt", "test") devolver verdadero?
  • @ CacahueteFrito Entonces, ¿paga un costo nada despreciable en usabilidad y rendimiento para enmascarar la corrupción de datos en algunas circunstancias raras, en lugar de depender de los invariantes de sus programas, parchear los datos o informar el error? Parece una mala idea en general.

Respuesta

Solo un par de comentarios:

  • Debe agregar una nueva línea después de la última línea:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • No sé qué compilador que usa pero con cuando se compila con gcc y -Wall -Wextra -pedantic obtiene:

    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; ^ 
  • El formato del código debe ser más coherente. Por ejemplo, en esta línea, coloca un espacio en blanco antes de needle pero no ponga un espacio en blanco antes haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu no es un especificador portátil para el tipo size_t, debe usar %zu introducido en C99.

  • Dijiste:

devuelve la posición si lo hace o 0 si no lo hace, a menos que el la posición es 0, en cuyo caso, no se localizará.

Esto realmente no es bueno. Por ejemplo, con esto devuelve 0:

char *needle = "This"; char *haystack = "This is a dinosaurtest."; 

Con esto, también devuelve cero:

char *needle = "non-existent"; char *haystack = "This is a dinosaurtest."; 

No se puede diferenciar entre el éxito y el fracaso en estos dos ejemplos. En realidad, atoi() tiene el mismo problema. No sé qué sistema operativo utiliza pero tal vez pueda usar ssize_t como tipo de retorno si está disponible y devolver -1 en caso de falla.

Respuesta

Agregando a la respuesta anterior de @Arkadiusz Drabczyk:

Una implementación simple y trivial de contains podría ser hecho así:

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

Entonces, este programa (con algunos cambios como se mencionó anteriormente) debería funcionar:

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

Resultado:

Posición: 18
Posición: -1

Comentarios

  • Quitaría la marca de que la entrada no es NULL, y ju st use una extensión de idioma para eso (__attribute__((nonnull)) en GCC). NULL es algo que nunca esperaría como entrada para esta función, y agrega una o dos líneas de código innecesarias. Preferiría escribir en la documentación de la función algo como: » Si la entrada a esta función es un puntero NULL, el comportamiento no está definido. «.
  • @CacahueteFrito El código original lo hizo, y quiero luchar por la compatibilidad (¿quién sabe cómo lo estaba usando el OP?).
  • Falta incluir para ssize_t: #include <sys/types.h>. Otra opción sería usar ptrdiff_t en su lugar, de #include <stddef.h>; en realidad, está devolviendo una diferencia de puntero: ? needle_in_haystack - haystack :

Respuesta

Su código no funciona. Devuelve 0 para haystack "abbc" y needle "bc", aunque haystack contiene needle .

Respuesta

No necesita el primer ciclo y todos los cálculos de longitud. Por cierto, la función no tiene éxito si se encuentra el primer carácter, pero solo la segunda aparición del primer carácter encaja con la aguja.

La tarea se puede reducir a unas pocas líneas:

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

Comentarios

  • ¿Cuál es una buena manera de mejorar la escritura de código C más compacto y eficiente como este? ?Esto me recuerda a K & R C.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *