2009-08-07 7 views
6
#include <stdio.h> 
#define MAXLEN 256 

int main() { 
    int n; 
    char buf[MAXLEN]; 
    while((n = read(0,buf,sizeof(buf))) != 0){ 
    printf("n: %d:",n); 
    write(1,buf,n); 
    } 
    return 1; 
} 

La salida del programa (donde la primera read y primera write se introducidas por el usuario y se hizo eco por el terminal) es:write() para la salida stdout y printf no intercalada?

read 
read 
write 
write 
n: 5:n: 6: 

La salida de printf viene después de pulsar Ctrl + D en el entrada estándar y no junto con las lecturas posteriores. ¿Por qué pasó esto?

Respuesta

18

Printf se almacena en el búfer.

Puede forzar a printf 'ras' su memoria intermedia utilizando la llamada fflush:

#include <stdio.h> 
#define MAXLEN 256 

int main() { 
    int n; 
    char buf[MAXLEN]; 
    while((n = read(0,buf,sizeof(buf))) != 0){ 
    printf("n: %d:",n); 
    fflush(stdout); /* force it to go out */ 
    write(1,buf,n); 
    } 
    return 1; 
} 

En general, printf() siendo amortiguada es una buena cosa. La salida sin búfer, particularmente para las consolas visibles que requieren actualizaciones de pantalla, etc., es lenta. Lo suficientemente lento como para que una aplicación que está imprimiendo mucho se ralentice directamente (especialmente en la plataforma de Windows, Linux y Unixes suelen tener un impacto menor).

Sin embargo, printf() siendo amortiguada hace morder si también fprintf(stderr,) - stderr es deliberadamente sin búfer. Como consecuencia, puede recibir sus mensajes con algunos printf() faltantes; si escribe en otro identificador FILE que también está asociado con el terminal y podría estar sin búfer, asegúrese de que primero explícitamente fflush(stdout).

+5

También puede cambiar el modo de almacenamiento en búfer con setvbuf() antes de hacer cualquier IO. – AProgrammer

+0

¿Qué significa "' printf() 'es [buffer] (http://en.wikipedia.org/wiki/Data_buffer)"? – ma11hew28

+0

http://stackoverflow.com/a/17552608/242933 – ma11hew28

1

Printf usa stdio y está almacenado en el búfer. Elimínelo enviando un cambio a "n:% d: \ n"

+0

O eso, o no mezclar los canales de salida - es decir, utilizar una y la misma función de salida en todos los contenidos. –

+1

\ n no está garantizado para vaciarlo. – EFraim

+1

stdout está almacenado en línea a menos que esté dirigido a un dispositivo no interactivo. – AProgrammer

2

La página del manual de fgets me dice:

No es recomendable mezclar llamadas a funciones de entrada de la biblioteca stdio con llamadas de bajo nivel para leer (2) para el descriptor de archivo aso- ado con la corriente de entrada; los resultados serán indefinidos y muy probablemente no es lo que quiere.

Por lo que la mejor solución sería no utilizar escribir y imprimir en el mismo descriptor.

+0

POSIX especifica con mucho cuidado cuando los resultados no están definidos y están bien definidos en base a una noción abstracta del "identificador activo". Ver http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 –

0

Utilice fwrite (versión de secuencias) en lugar de escribir.

Tenga en cuenta que, si bien está asociado con el archivo número 1, no es lo mismo.

1

Puede utilizar la función std fflush() para enjuagar el búfer estándar o puede usar \ n adicional al final de la cadena de control dentro de la impresión. Algo como esto

printf("\n :%d:\n",n); 

Siempre es mejor utilizar la escritura() funciones & lectura() en C en lugar de printf() y scanf(). Printf y scanf tienen algunos problemas, como printf almacena el parámetro de cadena en el búfer stdout. Por lo tanto, se requiere una descarga manual que se realiza a través de la función fflush o mediante \ n. En un pequeño programa de impresión hello world no encontrará un problema ya que el buffer de stdout se vacía al final de la ejecución del programa. Mejor uso write() que funciona bien. scanf también tiene el problema de leer espacios y muchos otros problemas relacionados con el buffer stdin.

Por ejemplo, en el código de abajo:

main() { char a; int i=0,c; for(;i<2;i++) { scanf("%d",&c); scanf("%c",&a);} } 

El programa anterior que tiene el problema de la lectura \ n en la entrada estándar en presionar enter. Podríamos resolver esto, pero sin descargar el búfer stdin ni hacer uso del carácter \ n. Siempre es mejor usar las funciones de lectura() y escritura().

Espero que ayude ....

Cuestiones relacionadas