una txt por palabras linea lenguaje leer guardarlo guardar especifica ejercicios datos binarios arreglo archivos archivo c file-io line std

txt - leer un archivo y guardarlo en un arreglo c



C leer archivo línea por línea (14)

Escribí esta función para leer una línea de un archivo:

const char *readLine(FILE *file) { if (file == NULL) { printf("Error: file pointer is null."); exit(1); } int maximumLineLength = 128; char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength); if (lineBuffer == NULL) { printf("Error allocating memory for line buffer."); exit(1); } char ch = getc(file); int count = 0; while ((ch != ''/n'') && (ch != EOF)) { if (count == maximumLineLength) { maximumLineLength += 128; lineBuffer = realloc(lineBuffer, maximumLineLength); if (lineBuffer == NULL) { printf("Error reallocating space for line buffer."); exit(1); } } lineBuffer[count] = ch; count++; ch = getc(file); } lineBuffer[count] = ''/0''; char line[count + 1]; strncpy(line, lineBuffer, (count + 1)); free(lineBuffer); const char *constLine = line; return constLine; }

La función lee el archivo correctamente y con printf veo que la cadena constLine también se leyó correctamente.

Sin embargo, si uso la función por ejemplo de esta manera:

while (!feof(myFile)) { const char *line = readLine(myFile); printf("%s/n", line); }

printf produce galimatías. ¿Por qué?


Algunas cosas mal con el ejemplo:

  • olvidó agregar / n a sus printfs. También los mensajes de error deberían ir a stderr, es decir, fprintf(stderr, ....
  • (no es un biggy sino) considere usar fgetc() lugar de getc() . getc() es una macro, fgetc() es una función adecuada
  • getc() devuelve un int para que ch se declare como un int . Esto es importante ya que la comparación con EOF se manejará correctamente. Algunos juegos de caracteres de 8 bits usan 0xFF como un carácter válido (ISO-LATIN-1 sería un ejemplo) y EOF que es -1, será 0xFF si se asigna a un char .
  • Existe un potencial desbordamiento de búfer en la línea

    lineBuffer[count] = ''/0'';

    Si la línea tiene exactamente 128 caracteres, el count es 128 en el punto que se ejecuta.

  • Como otros han señalado, la line es una matriz declarada localmente. No puedes devolver un puntero a él.

  • strncpy(count + 1) copiará a lo sumo count + 1 caracteres pero terminará si golpea ''/0'' Debido a que configura lineBuffer[count] a ''/0'' usted sabe que nunca count + 1 . Sin embargo, si lo hiciera, no pondría un ''/0'' terminación, por lo que debe hacerlo. A menudo ves algo como lo siguiente:

    char buffer [BUFFER_SIZE]; strncpy(buffer, sourceString, BUFFER_SIZE - 1); buffer[BUFFER_SIZE - 1] = ''/0'';

  • si malloc() una línea para devolver (en lugar de su matriz de caracteres local), su tipo de devolución debe ser char* - soltar la const .


Aquí están mis muchas horas ... Leyendo todo el archivo línea por línea.

char * readline(FILE *fp, char *buffer) { int ch; int i = 0; size_t buff_len = 0; buffer = malloc(buff_len + 1); if (!buffer) return NULL; // Out of memory while ((ch = fgetc(fp)) != ''/n'' && ch != EOF) { buff_len++; void *tmp = realloc(buffer, buff_len + 1); if (tmp == NULL) { free(buffer); return NULL; // Out of memory } buffer = tmp; buffer[i] = (char) ch; i++; } buffer[i] = ''/0''; // Detect end if (ch == EOF && (i == 0 || ferror(fp))) { free(buffer); return NULL; } return buffer; } void lineByline(FILE * file){ char *s; while ((s = readline(file, 0)) != NULL) { puts(s); free(s); printf("/n"); } } int main() { char *fileName = "input-1.txt"; FILE* file = fopen(fileName, "r"); lineByline(file); return 0; }


Comete el error de devolver un puntero a una variable automática. La línea variable se asigna en la pila y solo vive mientras viva la función. No se le permite devolver un puntero, ya que tan pronto como regrese la memoria se dará en otro lugar.

const char* func x(){ char line[100]; return (const char*) line; //illegal }

Para evitar esto, devuelve un puntero a la memoria que reside en el montón, por ejemplo. lineBuffer y debe ser responsabilidad del usuario llamar a free () cuando haya terminado con él. Alternativamente, puede pedirle al usuario que le transmita como argumento una dirección de memoria en la que escribir el contenido de la línea.


Debe usar las funciones de ANSI para leer una línea, ej. Fgets. Después de llamar, necesita el contexto de llamada gratuita (), por ejemplo:

... const char *entirecontent=readLine(myFile); puts(entirecontent); free(entirecontent); ... const char *readLine(FILE *file) { char *lineBuffer=calloc(1,1), line[128]; if ( !file || !lineBuffer ) { fprintf(stderr,"an ErrorNo 1: ..."); exit(1); } for(; fgets(line,sizeof line,file) ; strcat(lineBuffer,line) ) { if( strchr(line,''/n'') ) *strchr(line,''/n'')=0; lineBuffer=realloc(lineBuffer,strlen(lineBuffer)+strlen(line)+1); if( !lineBuffer ) { fprintf(stderr,"an ErrorNo 2: ..."); exit(2); } } return lineBuffer; }


En su función readLine , devuelve un puntero a la matriz line (Estrictamente hablando, un puntero a su primer carácter, pero la diferencia es irrelevante aquí). Como es una variable automática (es decir, está "en la pila"), la memoria se recupera cuando la función vuelve. Ves galimatías porque printf ha puesto sus propias cosas en la pila.

Debe devolver un búfer dinámicamente asignado de la función. Ya tienes uno, es lineBuffer ; todo lo que tienes que hacer es truncarlo a la longitud deseada.

lineBuffer[count] = ''/0''; realloc(lineBuffer, count + 1); return lineBuffer; }

AGREGADO (respuesta a la pregunta de seguimiento en comentario): readLine devuelve un puntero a los caracteres que componen la línea. Este puntero es lo que necesita para trabajar con los contenidos de la línea. También es lo que debe pasar a free cuando haya terminado de usar la memoria tomada por estos personajes. A continuación, le mostramos cómo puede usar la función readLine :

char *line = readLine(file); printf("LOG: read a line: %s/n", line); if (strchr(line, ''a'')) { puts("The line contains an a"); } /* etc. */ free(line); /* After this point, the memory allocated for the line has been reclaimed. You can''t use the value of `line` again (though you can assign a new value to the `line` variable if you want). */


Implementar método para leer y obtener contenido de un archivo (input1.txt)

#include <stdio.h> #include <stdlib.h> void testGetFile() { // open file FILE *fp = fopen("input1.txt", "r"); size_t len = 255; // need malloc memory for line, if not, segmentation fault error will occurred. char *line = malloc(sizeof(char) * len); // check if file exist (and you can open it) or not if (fp == NULL) { printf("can open file input1.txt!"); return; } while(fgets(line, len, fp) != NULL) { printf("%s/n", line); } free(line); }

Espero que esto ayude. Feliz codificación!


Quiero un código de la base 0 así que hice esto para leer el contenido de la palabra del diccionario línea por línea.

char temp_str [20]; // puede cambiar el tamaño del búfer según sus requisitos Y la longitud de una sola línea en un archivo.

Tenga en cuenta que he inicializado el búfer con carácter nulo cada vez que leo una línea. Esta función puede automatizarse, pero dado que necesito una prueba de concepto y quiero diseñar un programa, Byte Byte

#include<stdio.h> int main() { int i; char temp_ch; FILE *fp=fopen("data.txt","r"); while(temp_ch!=EOF) { i=0; char temp_str[20]={''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0'',''/0''}; while(temp_ch!=''/n'') { temp_ch=fgetc(fp); temp_str[i]=temp_ch; i++; } if(temp_ch==''/n'') { temp_ch=fgetc(fp); temp_str[i]=temp_ch; } printf("%s",temp_str); } return 0; }


Si su tarea no es inventar la función de lectura línea por línea, sino simplemente leer el archivo línea por línea, puede usar un fragmento de código típico que involucre la función getline() (consulte la página del manual here ):

#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> int main(void) { FILE * fp; char * line = NULL; size_t len = 0; ssize_t read; fp = fopen("/etc/motd", "r"); if (fp == NULL) exit(EXIT_FAILURE); while ((read = getline(&line, &len, fp)) != -1) { printf("Retrieved line of length %zu :/n", read); printf("%s", line); } fclose(fp); if (line) free(line); exit(EXIT_SUCCESS); }


Use fgets() para leer una línea de un manejador de archivo.


readLine() devuelve el puntero a la variable local, lo que causa un comportamiento indefinido.

Para moverte, puedes:

  1. Crear variable en la función de llamada y pasar su dirección a readLine()
  2. Asignar memoria para la line usando malloc() - en este caso la line será persistente
  3. Usar variable global, aunque generalmente es una mala práctica

//open and get the file handle FILE* fh; fopen_s(&fh, filename, "r"); //check if file exists if (fh == NULL){ printf("file does not exists %s", filename); return 0; } //read line by line const size_t line_size = 300; char* line = malloc(line_size); while (fgets(line, line_size, fh) != NULL) { printf(line); } free(line); // dont forget to free heap memory


FILE* fp; char buffer[255]; fp = fopen("file.txt", "r"); while(fgets(buffer, 255, (FILE*) fp)) { printf("%s/n", buffer); } fclose(fp);


const char *readLine(FILE *file, char* line) { if (file == NULL) { printf("Error: file pointer is null."); exit(1); } int maximumLineLength = 128; char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength); if (lineBuffer == NULL) { printf("Error allocating memory for line buffer."); exit(1); } char ch = getc(file); int count = 0; while ((ch != ''/n'') && (ch != EOF)) { if (count == maximumLineLength) { maximumLineLength += 128; lineBuffer = realloc(lineBuffer, maximumLineLength); if (lineBuffer == NULL) { printf("Error reallocating space for line buffer."); exit(1); } } lineBuffer[count] = ch; count++; ch = getc(file); } lineBuffer[count] = ''/0''; char line[count + 1]; strncpy(line, lineBuffer, (count + 1)); free(lineBuffer); return line; } char linebuffer[256]; while (!feof(myFile)) { const char *line = readLine(myFile, linebuffer); printf("%s/n", line); }

tenga en cuenta que la variable ''line'' se declara en la función de llamada y luego se pasa, por lo que su función readLine llena el buffer predefinido y simplemente lo devuelve. Esta es la forma en que funcionan la mayoría de las bibliotecas C

Hay otras formas, que yo conozco:

  • definiendo la char line[] como estática ( static char line[MAX_LINE_LENGTH] -> mantendrá su valor DESPUÉS de regresar de la función). -> malo, la función no es reentrante, y la condición de carrera puede ocurrir -> si la llamas dos veces desde dos hilos, sobrescribirá los resultados
  • malloc() ing la línea de caracteres [], y la liberación en funciones de llamada -> demasiados costosos malloc y, delegando la responsabilidad de liberar el búfer a otra función (la solución más elegante es llamar a malloc y free en cualquier búfer en la misma función)

Por cierto, la conversión ''explícita'' de char* a const char* es redundante.

btw2, no es necesario malloc() el lineBuffer, simplemente char lineBuffer[128] como char lineBuffer[128] , por lo que no necesita liberarlo

btw3 no use "matrices de pila de tamaño dinámico" (que define la matriz como char arrayName[some_nonconstant_variable] ), si no sabe exactamente qué está haciendo, solo funciona en C99.


void readLine(FILE* file, char* line, int limit) { int i; int read; read = fread(line, sizeof(char), limit, file); line[read] = ''/0''; for(i = 0; i <= read;i++) { if(''/0'' == line[i] || ''/n'' == line[i] || ''/r'' == line[i]) { line[i] = ''/0''; break; } } if(i != read) { fseek(file, i - read + 1, SEEK_CUR); } }

¿Qué hay de este?