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

wyjście z programu (w którym pierwsze read i pierwszy write jest podane przez użytkownika i echem przez terminal) jest:write() do wyjścia stdout i printf nie są przeplatane?

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

Wyjście printf jest po naciśnięciu klawiszy Ctrl + D na standardowe wejście, a nie wraz z kolejnymi odczytami. Dlaczego to się dzieje?

Odpowiedz

18

Printf jest buforowany.

Można wymusić printf do spłukiwania „” bufora używając połączenia 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; 
} 

Ogólnie printf() są buforowane jest dobrą rzeczą. Wyjścia niebuforowane, szczególnie widoczne konsole wymagające aktualizacji ekranu itp., Są powolne. Na tyle wolno, że aplikacja, która jest dużo drukowana, może być bezpośrednio spowolniona przez nią (szczególnie na platformie Windows, Linux i Uniksy są zwykle mniej dotknięte).

Jednak buforowanie printf() Cię ugryzie, jeśli również zostanie celowo niebuforowany. W rezultacie możesz otrzymać wiadomości z brakującym numerem printf(); jeśli napiszesz do innego uchwytu, który jest również powiązany z terminalem i może być niebuforowany, upewnij się, że najpierw jawnie .

+5

Możesz także zmienić tryb buforowania za pomocą setvbuf() przed wykonaniem dowolnej operacji wejścia/wyjścia. – AProgrammer

+0

Co oznacza "printf()' jest [buforowane] (http://en.wikipedia.org/wiki/Data_buffer) "? – ma11hew28

+0

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

1

Printf używa stdio i jest buforowany. Wypchnij, wysyłając zmianę na "n:% d: \ n"

+0

Albo, albo nie mieszaj kanałów wyjściowych - to znaczy użyj jednej i tej samej funkcji do wyprowadzenia całej treści. –

+1

\ n nie jest gwarantowane, aby go opróżnić. – EFraim

+1

stdout jest buforowany liniowo, chyba że jest skierowany do urządzenia nieinterakcyjnego. – AProgrammer

2

manpage dla fgets mówi mi:

Nie jest zalecane mieszanie wywołań funkcji wejściowych z biblioteki stdio z niskim poziomem wzywa do czytania (2) dla deskryptora pliku stowarzyszeniem przyklejając z strumień wejściowy; wyniki będą niezdefiniowane i prawdopodobnie nie będzie to, co chcesz.

Najlepszym rozwiązaniem byłoby nie używanie zapisu i printf na tym samym deskryptorze.

+0

POSIX określa bardzo ostrożnie, gdy wyniki są niezdefiniowane i gdy są dobrze zdefiniowane w oparciu o abstrakcyjne pojęcie "aktywnego uchwytu". Zobacz http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 –

0

Używaj fwrite (wersji streams) zamiast pisać.

Należy pamiętać, że chociaż jest powiązany z numerem pliku 1, nie jest to to samo.

1

Możesz użyć funkcji std fflush(), aby opróżnić bufor standardowego wyjścia lub możesz użyć dodatkowego \ n na końcu ciągu kontrolnego wewnątrz printf. Coś takiego

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

jej zawsze lepiej używać write() & read() funkcji w C zamiast printf() i scanf(). Printf i scanf mają pewne problemy, takie jak printf przechowuje parametr string w buforze standardowym. Dlatego wymagane jest ręczne spłukanie, które odbywa się za pomocą funkcji fflush lub za pomocą \ n. W małym programie do drukowania "cześć świat" nie znajdziesz takiego problemu, jak bufor stdout jest przepłukiwany pod koniec wykonywania programu. Lepiej użyj funkcji write(), która działa poprawnie. scanf ma również problem z czytaniem spacji i wieloma innymi problemami związanymi z buforem stdin.

na przykład w kodzie poniżej:

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

Powyższy program jako drogę problem odczytu \ n do standardowego wejścia na wciśnięcie ENTER. Możemy rozwiązać ten problem, ale nie spłukać bufora stdin lub użyć znaku \ n. Zawsze lepiej korzystać z funkcji read() i write().

Nadzieję, że pomaga ....