2009-08-07 13 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; 
} 

L'output del programma (dove il primo read e primo write è tipizzato dall'utente e eco dal terminale) è:write() su stdout e output printf non interlacciato?

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

L'output di printf arriva dopo aver premuto Ctrl + D alla input standard e non insieme alle letture successive. Perché succede?

risposta

18

Printf è memorizzato nel buffer.

È possibile forzare printf per 'filo' il suo buffer utilizzando la chiamata 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; 
} 

In generale, printf() essere tamponata è una buona cosa. L'output non bufferizzato, in particolare sulle console visibili che richiedono aggiornamenti dello schermo e così via, è lento. È abbastanza lento che un'applicazione che sta stampando molto può essere rallentata direttamente da esso (specialmente sulla piattaforma Windows, in genere Linux e Unix hanno un impatto minore).

Tuttavia, printf() essere tamponata fa morderà se anche fprintf(stderr,) - stderr è volutamente senza buffer. Di conseguenza, potresti ricevere i tuoi messaggi con alcuni printf() mancanti; se scrivi su un altro handle FILE che è anche associato al terminale e potrebbe non essere bloccato, assicurati di essere il primo esplicitamente fflush(stdout).

+5

È inoltre possibile modificare la modalità di buffering con setvbuf() prima di eseguire qualsiasi IO. – AProgrammer

+0

Che cosa significa "printf()' è [bufferizzato] (http://en.wikipedia.org/wiki/Data_buffer) "significa? – ma11hew28

+0

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

1

Printf sta utilizzando stdio ed è bufferizzato. Spingilo inviando una modifica a "n:% d: \ n"

+0

O che, o non mescolare canali di uscita - cioè, utilizzare uno e la stessa funzione per emettere tutti i contenuti. –

+1

\ n non è garantito per lo scarico. – EFraim

+1

stdout è in modalità bufferizzata a meno che non sia indirizzato a un dispositivo non interattivo. – AProgrammer

2

La pagina di manuale per fgets mi dice:

Non è consigliabile mischiare chiamate a funzioni di ingresso dalla libreria stdio con basso livello di chiamate di leggere (2) per il descrittore di file asso- ated con il flusso di input; i risultati saranno indefiniti e molto probabilmente non è quello che vuoi.

Quindi la soluzione migliore sarebbe non utilizzare write e printf sullo stesso descrittore.

+0

POSIX specifica molto attentamente quando i risultati non sono definiti e quando sono ben definiti sulla base di una nozione astratta di "handle attivo". Vedi http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 –

0

Utilizzare fwrite (versione per flussi) anziché scrivere.

Si noti che, mentre è associato al file numero 1, non è la stessa cosa.

1

È possibile utilizzare la funzione std fflush() per svuotare il buffer di std out oppure è possibile utilizzare un \ n aggiuntivo alla fine della stringa di controllo all'interno di printf. Qualcosa di simile

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

sua sempre meglio usare il write() funzioni & read() in C invece di printf() e scanf(). Printf e scanf hanno alcuni problemi come printf memorizza il parametro stringa nel buffer stdout. Quindi è richiesto un flush manuale che viene eseguito tramite la funzione fflush o mediante \ n. In un piccolo programma di stampa mondiale Hello non troverete un problema come il buffer stdout è svuotato alla fine dell'esecuzione del programma. Meglio usare write() che funziona bene. scanf ha anche il problema di leggere gli spazi e molti altri problemi relativi al buffer di stdin.

Ad esempio, nel codice qui sotto:

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

Il programma di cui sopra come ha ottenuto il problema della lettura \ n in stdin premendo enter. Potremmo risolvere questo problema, ma non lavare il buffer stdin o utilizzare il carattere \ n. Sempre meglio usare le funzioni read() e write().

speranza che aiuta ....