Leyendo de archivos de texto en C

Una pequeña pregunta realmente. ¿Qué sería lo mejor para leer un archivo de texto que contenga X palabras y agregar cada palabra, una por una, a una lista vinculada? Es decir, la rana es vieja.

Por lo tanto, The, Frog, Is y Old se pondrían en un ListNode, todos leídos de un archivo.

Realmente me pregunto cuál es la mejor función para usar junto con fscanf, si fscanf es incluso la mejor opción. ¡Todos los consejos son geniales!

Aclamaciones.

EDITAR: Mi consulta es realmente, si quisiera analizar un archivo de texto grande, ¿sería mejor convertir cada palabra en una matriz una por una, agregar a la lista, liberar la matriz y repetir? ¿O hay una manera más eficiente

El especificador de conversión “% s” coincidirá con caracteres que no sean espacios en blanco.

 #define QUOTE(s) #s #define STR(s) QUOTE(s) #ifndef BUFSIZE # define BUFSIZE 255 #endif char buf[BUFSIZE+1]; while (fscanf(fin, "%" STR(BUFSIZE) "s", buf)) { /* buf holds next word. Todo: + allocate space for word + copy word to newly allocated space + add to linked list */ } 

Alternativamente, strtok se puede usar para tokenizar (separar) una cadena en subcadenas, usando un conjunto de caracteres (como una matriz de caracteres) que especifique. Su sistema también puede tener strsep , que está destinado a reemplazar a strtok . Tanto strsep como strsep modifican la matriz que usted pasa, así que tenga cuidado de que esto no cause problemas con otras partes del código que accede a los datos. strsep no es seguro para subprocesos; Si tiene varios subprocesos que acceden a la cadena que se va a analizar, utilice strsep o strtok_r .

 #ifndef BUFSIZE # define BUFSIZE 256 #endif const char separators[] = "\t\n\v\r\f !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~"; char buf[BUFSIZE], *line, *word, *rest; while (fgets(buf, BUFSIZE+1, fin)) { rest = line = buf; while ((word = strtok_r(line, separators, &rest))) { /* Todo: + allocate space for word + copy word to newly allocated space + add to linked list */ line=rest; } } 

Como el segundo ejemplo lee una línea a la vez desde el archivo para que funcione strtok_r , si alguna línea del archivo tiene más de BUFSIZE-1 de caracteres y BUFSIZE-1 st y BUFSIZE th en una línea son letras, el El segundo ejemplo dividirá las palabras en dos. Una solución para esto sería crear un flujo de cadena con búfer, de modo que cuando se llegue al final del búfer, todo lo que quede en el búfer se desplace hacia el frente y el rest del búfer se llene con más datos del archivo (solo tenga cuidado con las palabras más largas que el búfer; en el código de producción, es una vulnerabilidad de seguridad potencial que podría provocar ataques de denegación de servicio).

Un problema con todas las funciones anteriores es que no manejan caracteres nulos en la entrada. Si desea analizar datos que pueden contener caracteres nulos, deberá utilizar una función no estándar, que incluye escribir la suya propia.

En cuanto a la eficiencia, cualquier algoritmo que use deberá leer el archivo (que es O (n) en complejidad y requerirá I / O, ralentizar el progtwig) y asignar memoria para almacenar las palabras. Ya sea que use fscanf , strtok o algún otro método, es probable que la complejidad de tiempo y espacio no varíe mucho; sobre lo único que podría ser cuántos buffers intermedios se asignan. Su mejor apuesta para encontrar la implementación más eficiente es probar un par y hacer un perfil de ellos.

No debe buscar “una forma más eficiente” hasta que tenga “una forma que no sea lo suficientemente eficiente”.

Pero algo como strtok podría adaptarse a sus necesidades sin tanto malloc . Te permite cortar la cuerda en su lugar . (Usar con precaución!)

Si buscas alta velocidad, en una computadora de escritorio moderna … Puedes ir a múltiples hilos.

  • Un hilo llena un búfer de caracteres, digamos 4Ko, y solo hace esto
  • Un hilo lee el búfer, analiza las palabras y las agrega a la lista
  • Un hilo hace lo que creas que debes hacer en la lista, si no necesitas la lista en su totalidad

La idea es que el proceso no se duerma mientras se espera la E / S. Para una velocidad adicional si tiene muchos núcleos de CPU, es cortar el archivo en grandes partes, y un núcleo procesa una parte. Muchas oportunidades para códigos y bugs complejos, pero bueno, la velocidad no es barata …