programming limpiar libreria basura c file-io

limpiar - ¿Por qué mi simple programa C muestra la basura a stdout?



stdin stdout stderr (5)

Puede usar calloc lugar de malloc para asignar memoria que ya está inicializada. calloc adquiere un argumento extra. Es útil para asignar matrices; El primer parámetro de calloc indica la cantidad de elementos en la matriz a la que le gustaría asignar memoria, y el segundo argumento es el tamaño de cada elemento. Como el tamaño de un char es siempre 1, podemos pasar 1 como segundo argumento:

buffer = calloc (fileLen + 1, 1);

En C, no hay necesidad de lanzar el valor de retorno de malloc o calloc . Lo anterior asegurará que la cadena terminará nula incluso si la lectura del archivo finalizó prematuramente por cualquier razón. calloc tarda más tiempo que malloc porque tiene que poner a cero toda la memoria que pediste antes de dártela.

Considere el siguiente programa simple de C que lee un archivo en un búfer y muestra ese búfer a la consola:

#include<stdio.h> main() { FILE *file; char *buffer; unsigned long fileLen; //Open file file = fopen("HelloWorld.txt", "rb"); if (!file) { fprintf(stderr, "Unable to open file %s", "HelloWorld.txt"); return; } //Get file length fseek(file, 0, SEEK_END); fileLen=ftell(file); fseek(file, 0, SEEK_SET); //Allocate memory buffer=(char *)malloc(fileLen+1); if (!buffer) { fprintf(stderr, "Memory error!"); fclose(file); return; } //Read file contents into buffer fread(buffer, fileLen, 1, file); //Send buffer contents to stdout printf("%s/n",buffer); fclose(file); }

El archivo que leerá simplemente contiene:

Hola Mundo!

El resultado es:

¡Hola mundo! ²²²²▌▌▌▌▌▌▌↔☺

Ha pasado un tiempo desde que hice algo significativo en C / C ++, pero normalmente asumiría que el búfer se estaba asignando más grande de lo necesario, pero este no parece ser el caso.

fileLen termina siendo 12, que es preciso.

Ahora estoy pensando que debo mostrar el búfer equivocado, pero no estoy seguro de lo que estoy haciendo mal.

¿Puede alguien darme una pista de lo que estoy haciendo mal?


El enfoque de JesperE funcionará, pero puede interesarte saber que hay una forma alternativa de manejar esto.

Siempre puede imprimir una cadena de longitud conocida, incluso cuando no hay terminador NUL, al proporcionar la longitud para printf como la precisión para el campo de cadena:

printf("%.*s/n", fileLen, buffer);

Esto le permite imprimir la cadena sin modificar el búfer.


JesperE tiene razón con respecto al problema de nul-terminación en su ejemplo, solo agregaré que si está procesando archivos de texto, sería mejor usar fgets () o algo similar, ya que manejará adecuadamente las secuencias de nueva línea en diferentes plataformas y siempre nul-termina la cadena por ti. Si realmente está trabajando con datos binarios, entonces no desea usar printf () para generar los datos ya que las funciones de impresión esperan cadenas y un byte nulo en los datos causará el truncamiento de la salida.


Necesitas terminar NUL tu cadena. Añadir

buffer[fileLen] = 0;

antes de imprimirlo


Su enfoque para determinar el tamaño del archivo buscando hasta el final del archivo y luego usando ftell() es incorrecto:

  • Si se trata de un archivo de texto, abierto sin "b" en el segundo parámetro de la llamada fopen() , entonces ftell() puede no decirle la cantidad de caracteres que puede leer del archivo. Por ejemplo, Windows usa dos bytes para el final de la línea, pero cuando se lee, es un char . De hecho, el valor de retorno de ftell() para las transmisiones abiertas en modo texto es útil solo en las llamadas a fseek() , y no para determinar el tamaño del archivo.
  • Si se trata de un archivo binario, abierto con "b" en el segundo parámetro para fopen() , entonces el estándar C tiene esto que decir:

    Establecer el indicador de posición del archivo al final del archivo, como con fseek(file, 0, SEEK_END) , tiene un comportamiento indefinido para una secuencia binaria (debido a posibles caracteres nulos finales) o para cualquier transmisión con codificación dependiente del estado que no funciona Con seguridad termina en el estado de cambio inicial.

Por lo tanto, lo que está haciendo no necesariamente va a funcionar en la norma C. Su mejor fread() es usar fread() para leer, y si necesita más memoria, use realloc() . Su sistema puede proporcionar mmap() , o puede hacer garantías acerca de cómo configurar el indicador de posición del archivo al final del archivo para transmisiones binarias, pero depender de ellas no es portátil.

Ver también este C-FAQ: ¿Cuál es la diferencia entre el texto y la E / S binaria? .