Leer la línea del archivo sin conocer la longitud de la línea

Quiero leer en un archivo línea por línea, sin saber la longitud de línea antes. Esto es lo que obtuve hasta ahora:

int ch = getc(file); int length = 0; char buffer[4095]; while (ch != '\n' && ch != EOF) { ch = getc(file); buffer[length] = ch; length++; } printf("Line length: %d characters.", length); char newbuffer[length + 1]; for (int i = 0; i < length; i++) newbuffer[i] = buffer[i]; newbuffer[length] = '\0'; // newbuffer now contains the line. 

Ahora puedo calcular la longitud de la línea, pero solo para las líneas que tienen menos de 4095 caracteres, además de las dos matrices de caracteres que parecen una forma incómoda de hacer la tarea. ¿Hay una mejor manera de hacerlo (ya he usado Fgets () pero me dijeron que no era la mejor manera)?

–Ry

Puede comenzar con un tamaño adecuado de su elección y luego usar realloc mitad de camino si necesita más espacio ya que:

 int CUR_MAX = 4095; char *buffer = (char*) malloc(sizeof(char) * CUR_MAX); // allocate buffer. int length = 0; while ( (ch != '\n') && (ch != EOF) ) { if(length ==CUR_MAX) { // time to expand ? CUR_MAX *= 2; // expand to double the current size of anything similar. buffer = realloc(buffer, CUR_MAX); // re allocate memory. } ch = getc(file); // read from stream. buffer[length] = ch; // stuff in buffer. length++; } . . free(buffer); 

Deberá verificar los errores de asignación después de las llamadas a malloc y realloc .

Es posible que desee examinar la biblioteca de ggets dominio público de Chuck B. Falconer . Si estás en un sistema con glibc, probablemente tengas una función getline (no estándar) disponible para ti.

Estás cerca. Básicamente, quiere leer fragmentos de datos y verificarlos para \n caracteres. Si encuentras uno, bien, tienes un final de línea. Si no lo hace, tiene que boost su búfer (es decir, asignar un nuevo búfer dos veces el tamaño del primero y copiar los datos del primero en el nuevo, luego eliminar el búfer antiguo y cambiar el nombre de su nuevo búfer como el viejo – o simplemente realloc si estás en C) luego lee un poco más hasta que encuentres un final.

Una vez que tenga su final, el texto desde el principio del búfer al carácter \n es su línea. Cópielo en un búfer o trabaje en él en su lugar, depende de usted.

Después de que esté listo para la siguiente línea, puede copiar el “rest” de la entrada sobre la línea actual (básicamente un desplazamiento hacia la izquierda) y completar el rest del búfer con los datos de la entrada. Luego vuelve otra vez hasta que te quedes sin datos.

Esto, por supuesto, se puede optimizar, con un búfer circular, por ejemplo, pero esto debería ser más que suficiente para cualquier algoritmo de io limitado razonable.

Así es como lo hice para stdin, si lo llamas como readLine(NULL, 0) la función asigna un buffer para ti con el tamaño de 1024 y lo deja crecer en pasos de 1024. Si llamas a la función con readLine(NULL, 10) obtienes un buffer con pasos de 10. Si tienes un buffer puedes suministrarlo con su tamaño.

 #include  #include  #include  #include  char *readLine(char **line, size_t *length) { assert(line != NULL); assert(length != NULL); size_t count = 0; *length = *length > 0 ? *length : 1024; if (!*line) { *line = calloc(*length, sizeof(**line)); if (!*line) { return NULL; } } else { memset(*line, 0, *length); } for (int ch = getc(stdin); ch != '\n' && ch != EOF; ch = getc(stdin)) { if (count == *length) { *length += 2; *line = realloc(*line, *length); if (!*line) { return NULL; } } (*line)[count] = (char)ch; ++count; } return *line; }