Pasando por un archivo de texto línea por línea en C

He estado trabajando en un ejercicio pequeño para mi clase de CIS y estoy muy confundido por los métodos que C usa para leer de un archivo. Todo lo que realmente necesito hacer es leer un archivo línea por línea y usar la información obtenida de cada línea para hacer algunas manipulaciones. Intenté usar el método getline y otros sin suerte. Mi código es actualmente el siguiente:

int main(char *argc, char* argv[]){ const char *filename = argv[0]; FILE *file = fopen(filename, "r"); char *line = NULL; while(!feof(file)){ sscanf(line, filename, "%s"); printf("%s\n", line); } return 1; } 

En este momento estoy obteniendo un error seg con el método sscanf y no estoy seguro de por qué. Soy un novato total de C y me pregunto si había algo importante que me faltaba. Gracias

Tantos problemas en tan pocas líneas. Probablemente me olvide algo:

  • argv [0] es el nombre del progtwig, no el primer argumento;
  • si quieres leer en una variable, debes asignar su memoria
  • uno nunca se mueve en bucle, uno realiza un bucle en una función IO hasta que falla, entonces sirve para determinar el motivo de la falla,
  • sscanf está ahí para analizar una línea, si quiere analizar un archivo, use fscanf,
  • “% s” se detendrá en el primer espacio como formato para la familia? scanf
  • para leer una línea, la función estándar es fgets,
  • regresando 1 de la falla del medio principal

Asi que

 #include  int main(int argc, char* argv[]) { char const* const fileName = argv[1]; /* should check that argc > 1 */ FILE* file = fopen(fileName, "r"); /* should check the result */ char line[256]; while (fgets(line, sizeof(line), file)) { /* note that fgets don't strip the terminating \n, checking its presence would allow to handle lines longer that sizeof(line) */ printf("%s", line); } /* may check feof here to make a difference between eof and io failure -- network timeout for instance */ fclose(file); return 0; } 

Para leer una línea de un archivo, debe usar la función fgets : lee una cadena del archivo especificado hasta un carácter de línea nueva o EOF .

El uso de sscanf en su código no funcionaría en absoluto, ya que utiliza filename como su cadena de formato para leer de la line en una cadena constante literal %s .

El motivo de SEGV es que escribe en la memoria no asignada apuntada por line .

Supongamos que está tratando con algún otro delimitador, como una pestaña \t , en lugar de una \n nueva línea.

Un enfoque más general de los delimitadores es el uso de getc() , que toma un carácter a la vez.

Tenga en cuenta que getc() devuelve un int , por lo que podemos probar la igualdad con EOF .

En segundo lugar, definimos una line[BUFFER_MAX_LENGTH] matriz line[BUFFER_MAX_LENGTH] de tipo char , para almacenar hasta BUFFER_MAX_LENGTH-1 caracteres en la stack (tenemos que guardar ese último carácter para un carácter terminador \0 ).

El uso de una matriz evita la necesidad de utilizar malloc y crea un puntero de carácter de la longitud correcta en el montón.

 #define BUFFER_MAX_LENGTH 1024 int main(int argc, char* argv[]) { FILE *file = NULL; char line[BUFFER_MAX_LENGTH]; int tempChar; unsigned int tempCharIdx = 0U; if (argc == 2) file = fopen(argv[1], "r"); else { fprintf(stderr, "error: wrong number of arguments\n" "usage: %s textfile\n", argv[0]); return EXIT_FAILURE; } if (!file) { fprintf(stderr, "error: could not open textfile: %s\n", argv[1]); return EXIT_FAILURE; } /* get a character from the file pointer */ while(tempChar = fgetc(file)) { /* avoid buffer overflow error */ if (tempCharIdx == BUFFER_MAX_LENGTH) { fprintf(stderr, "error: line is too long. increase BUFFER_MAX_LENGTH.\n"); return EXIT_FAILURE; } /* test character value */ if (tempChar == EOF) { line[tempCharIdx] = '\0'; fprintf(stdout, "%s\n", line); break; } else if (tempChar == '\n') { line[tempCharIdx] = '\0'; tempCharIdx = 0U; fprintf(stdout, "%s\n", line); continue; } else line[tempCharIdx++] = (char)tempChar; } return EXIT_SUCCESS; } 

Si debe usar un char * , puede seguir usando este código, pero strdup() la matriz de line[] , una vez que se completa con la entrada de una línea. Debe free esta cadena duplicada una vez que haya terminado con ella, o obtendrá una pérdida de memoria:

 #define BUFFER_MAX_LENGTH 1024 int main(int argc, char* argv[]) { FILE *file = NULL; char line[BUFFER_MAX_LENGTH]; int tempChar; unsigned int tempCharIdx = 0U; char *dynamicLine = NULL; if (argc == 2) file = fopen(argv[1], "r"); else { fprintf(stderr, "error: wrong number of arguments\n" "usage: %s textfile\n", argv[0]); return EXIT_FAILURE; } if (!file) { fprintf(stderr, "error: could not open textfile: %s\n", argv[1]); return EXIT_FAILURE; } while(tempChar = fgetc(file)) { /* avoid buffer overflow error */ if (tempCharIdx == BUFFER_MAX_LENGTH) { fprintf(stderr, "error: line is too long. increase BUFFER_MAX_LENGTH.\n"); return EXIT_FAILURE; } /* test character value */ if (tempChar == EOF) { line[tempCharIdx] = '\0'; dynamicLine = strdup(line); fprintf(stdout, "%s\n", dynamicLine); free(dynamicLine); dynamicLine = NULL; break; } else if (tempChar == '\n') { line[tempCharIdx] = '\0'; tempCharIdx = 0U; dynamicLine = strdup(line); fprintf(stdout, "%s\n", dynamicLine); free(dynamicLine); dynamicLine = NULL; continue; } else line[tempCharIdx++] = (char)tempChar; } return EXIT_SUCCESS; } 

Además de las otras respuestas, en una biblioteca C reciente (compatible con Posix 2008), puede usar getline . Vea esta respuesta (a una pregunta relacionada).