Tengo un archivo de texto llamado test.txt
Quiero escribir un programa en C que pueda leer este archivo e imprimir el contenido en la consola (suponga que el archivo contiene solo texto ASCII).
No sé cómo obtener el tamaño de mi variable de cadena. Me gusta esto:
char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
while (fscanf(file, "%s", str)!=EOF)
printf("%s",str);
fclose(file);
}
El tamaño 999
no funciona porque la cadena devuelta por fscanf
puede ser más grande que eso. ¿Como puedo resolver esto?
fuente
stdout
.c
es int, y C garantizará queEOF
no es igual a ningún carácter válido.Aquí hay muchas buenas respuestas sobre cómo leerlo en partes, solo te mostraré un pequeño truco que lee todo el contenido a la vez en un búfer y lo imprime.
No digo que sea mejor. No lo es, y como Ricardo, a veces puede ser malo, pero encuentro que es una buena solución para los casos simples.
Lo espolvoreé con comentarios porque están pasando muchas cosas.
#include <stdio.h> #include <stdlib.h> char* ReadFile(char *filename) { char *buffer = NULL; int string_size, read_size; FILE *handler = fopen(filename, "r"); if (handler) { // Seek the last byte of the file fseek(handler, 0, SEEK_END); // Offset from the first to the last byte, or in other words, filesize string_size = ftell(handler); // go back to the start of the file rewind(handler); // Allocate a string that can hold it all buffer = (char*) malloc(sizeof(char) * (string_size + 1) ); // Read it all in one operation read_size = fread(buffer, sizeof(char), string_size, handler); // fread doesn't set it so put a \0 in the last position // and buffer is now officially a string buffer[string_size] = '\0'; if (string_size != read_size) { // Something went wrong, throw away the memory and set // the buffer to NULL free(buffer); buffer = NULL; } // Always remember to close the file. fclose(handler); } return buffer; } int main() { char *string = ReadFile("yourfile.txt"); if (string) { puts(string); free(string); } return 0; }
Déjame saber si es útil o podrías aprender algo de él :)
fuente
buffer[string_size] = '\0';
lugar destring_size+1
? Afaik, la cadena real va de0
astring_size-1
y, por lo\0
tanto, el personaje debe estar enstring_size
, ¿verdad?ftell
yfseek
para encontrar el tamaño de un archivo no es seguro: securecoding.cert.org/confluence/display/seccode/…fclose(handle)
calloc(2)
lugar demalloc(1)
omitir tener que configurar el terminador nulo.En su lugar, imprima directamente los caracteres en la consola porque el archivo de texto puede ser muy grande y es posible que necesite mucha memoria.
#include <stdio.h> #include <stdlib.h> int main() { FILE *f; char c; f=fopen("test.txt","rt"); while((c=fgetc(f))!=EOF){ printf("%c",c); } fclose(f); return 0; }
fuente
Utilice "read ()" en lugar de fscanf:
ssize_t read(int fildes, void *buf, size_t nbyte);
Aquí hay un ejemplo:
http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html
Parte de trabajo de ese ejemplo:
f=open(argv[1],O_RDONLY); while ((n=read(f,l,80)) > 0) write(1,l,n);
Un enfoque alternativo es usar
getc
/putc
para leer / escribir 1 carácter a la vez. Mucho menos eficiente. Un buen ejemplo: http://www.eskimo.com/~scs/cclass/notes/sx13.htmlfuente
read
le permitirá leer una cierta cantidad de caracteres. Lea lo suficiente para llenar su búfer, luego descargue su búfer en la pantalla, bórrelo y repita hasta que llegue al final del archivo.Me vienen a la mente dos enfoques.
Primero, no lo use
scanf
. Utilice elfgets()
que toma un parámetro para especificar el tamaño del búfer y que deja intactos los caracteres de nueva línea. Un simple bucle sobre el archivo que imprime el contenido del búfer naturalmente debería copiar el archivo intacto.En segundo lugar, use
fread()
o el modismo común de C confgetc()
. Estos procesarían el archivo en trozos de tamaño fijo o un solo carácter a la vez.Si debe procesar el archivo sobre cadenas delimitadas por espacios en blanco, utilice
fgets
ofread
para leer el archivo y algo comostrtok
dividir el búfer en espacios en blanco. No olvide manejar la transición de un búfer al siguiente, ya que es probable que sus cadenas de destino abarquen el límite del búfer.Si hay un requisito externo para usar
scanf
para realizar la lectura, limite la longitud de la cadena que podría leer con un campo de precisión en el especificador de formato. En su caso con un búfer de 999 bytes, entonces digascanf("%998s", str);
cuál escribirá como máximo 998 caracteres en el búfer dejando espacio para el terminador nulo. Si se permiten cadenas individuales más largas que su búfer, deberá procesarlas en dos partes. De lo contrario, tiene la oportunidad de informar al usuario sobre un error cortésmente sin crear un agujero de seguridad de desbordamiento del búfer.Independientemente, siempre valide los valores devueltos y piense en cómo manejar la entrada incorrecta, maliciosa o simplemente mal formada.
fuente
Puedes usar
fgets
y limitar el tamaño de la cadena de lectura.char *fgets(char *str, int num, FILE *stream);
Puede cambiar el
while
en su código a:while (fgets(str, 100, file)) /* printf("%s", str) */;
fuente
Puede leer el archivo completo con asignación de memoria dinámica, pero no es una buena idea porque si el archivo es demasiado grande, podría tener problemas de memoria.
Por lo tanto, es mejor leer partes cortas del archivo e imprimirlo.
#include <stdio.h> #define BLOCK 1000 int main() { FILE *f=fopen("teste.txt","r"); int size; char buffer[BLOCK]; // ... while((size=fread(buffer,BLOCK,sizeof(char),f)>0) fwrite(buffer,size,sizeof(char),stdout); fclose(f); // ... return 0; }
fuente