Różnica między fprintf, printf i sprintf?


233

Czy ktoś może wyjaśnić prostym językiem o różnicach między printf, fprintforaz sprintfz przykładami?

W jakim to jest strumieniu?

Jestem bardzo zdezorientowany między tymi trzema, czytając o „Obsługa plików w C”.


4
Eksperymentuj z nimi, pisząc przykładowy kod. To bardzo łatwy sposób, aby jasno zrozumieć różnicę między nimi.
Nawaz

14
Preferuj snprintf () niż sprintf (), aby uniknąć głupich przepełnień bufora.
Maxim Egorushkin

3
Wolę strumieni lub zwiększyć formatek, aby uniknąć przepełnienia bufora głupie i paskudne robaki typu-unsafety
John Dibling

7
@Maxim, podczas gdy podnosisz poprawny punkt, wezmę bezpieczeństwo, wiedząc, że moje bufory nie przepełnią się i nie rozłożę mojej aplikacji na kawałki. Spojrzałbym na te funkcje tylko wtedy, gdyby okazało się, że formatory strumieni / boostów powodują zauważalne wąskie gardła. :)
Moo-Juice,

1
@ Maxim: Chodzi o to, że nie ma takiej potrzeby. Mój kod nie jest wąskim gardłem. 5 m / s to liczba wiadomości wysyłanych przez centralę, a nie tyle, ile jesteśmy w stanie przetworzyć. Dlaczego więc przedwcześnie optymalizować?
John Dibling,

Odpowiedzi:


237

W C „strumień” jest abstrakcją; z perspektywy programu jest to po prostu producent (strumień wejściowy) lub konsument (strumień wyjściowy) bajtów. Może odpowiadać plikowi na dysku, potoku, terminalowi lub innemu urządzeniu, np. Drukarce lub tty. FILETypu zawiera informacje o strumieniu. Zwykle nie zadzierasz FILEbezpośrednio z treścią obiektu, po prostu przekazujesz do niego wskaźnik do różnych procedur we / wy.

Istnieją trzy standardowe strumienie: stdinwskaźnik do standardowego strumienia wejściowego, stdoutwskaźnik do standardowego strumienia wyjściowego i stderrwskaźnik do standardowego strumienia wyjściowego błędu. W sesji interaktywnej trzy zazwyczaj odnoszą się do konsoli, chociaż można je przekierować, aby wskazać inne pliki lub urządzenia:

$ myprog < inputfile.dat > output.txt 2> errors.txt

W tym przykładzie stdinteraz wskazuje na inputfile.dat, stdoutwskazuje na output.txti stderrwskazuje na errors.txt.

fprintf zapisuje sformatowany tekst w określonym strumieniu wyjściowym.

printfodpowiada zapisywaniu fprintf(stdout, ...)i zapisywaniu sformatowanego tekstu wszędzie tam, gdzie obecnie wskazuje standardowy strumień wyjściowy.

sprintfzapisuje sformatowany tekst w tablicy char, w przeciwieństwie do strumienia.


4
„to po prostu producent (strumień wejściowy) lub konsument (strumień wyjściowy) bajtów”. Czy są to zacofane? Czy producent nie stworzyłby (wytworzyłby) czegoś? Pytanie, bo naprawdę nie wiem.
Dave Voyles,

6
@DaveVoyles: Są z perspektywy twojego programu. Strumień wejściowy wytwarza bajty do odczytania przez program; strumień wyjściowy zużywa bajty wyprodukowane z twojego programu.
John Bode,

153

printfwyjścia do standardowego strumienia wyjściowego ( stdout)

fprintfprzechodzi do uchwytu pliku ( FILE*)

sprintfprzechodzi do przydzielonego bufora. ( char*)


39

printf („format”, args) służy do drukowania danych na standardowym wyjściu, którym często jest monitor komputera.

sprintf (char *, „format”, args) jest jak printf. Zamiast wyświetlać sformatowany ciąg znaków na standardowym wyjściu, tj. Na monitorze, przechowuje sformatowane dane w ciągu wskazanym przez wskaźnik char (pierwszy parametr). Lokalizacja ciągu jest jedyną różnicą między składnią printf a sprintem.

fprintf (PLIK * fp, „format”, argumenty) znów przypomina printf. Tutaj zamiast wyświetlać dane na monitorze lub zapisywać je w jakimś ciągu, sformatowane dane są zapisywane w pliku wskazywanym przez wskaźnik pliku, który jest używany jako pierwszy parametr fprintf. Wskaźnik pliku jest jedynym dodatkiem do składni printf.

Jeśli plik stdout jest używany jako pierwszy parametr w fprintf, jego działanie jest następnie uważane za równoważne działaniu printf.


24

printf(...)jest równoważne z fprintf(stdout,...).

fprintf służy do wyświetlania strumienia.

sprintf(buffer,...) służy do formatowania ciągu do bufora.

Uwaga jest również vsprintf, vfprintfivprintf


Te vsmaki są niestandardowe wierzę
John Dibling

8
Te vsmaki są bardzo pewno w standardzie C.
Fred Foo,

@larsmans: ah, ok. Dziękuję za poprawienie mnie. To pytanie w pewnym momencie było oznaczone [c ++]
John Dibling,

2

Możesz także robić bardzo przydatne rzeczy za pomocą funkcji vsnprintf ():

$ cat test.cc
#include <exception>
#include <stdarg.h>
#include <stdio.h>

struct exception_fmt : std::exception
{
    exception_fmt(char const* fmt, ...) __attribute__ ((format(printf,2,3)));
    char const* what() const throw() { return msg_; }
    char msg_[0x800];
};

exception_fmt::exception_fmt(char const* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(msg_, sizeof msg_, fmt, ap);
    va_end(ap);
}

int main(int ac, char** av)
{
    throw exception_fmt("%s: bad number of arguments %d", *av, ac);
}

$ g++ -Wall -o test test.cc

$ ./test
terminate called after throwing an instance of 'exception_fmt'
  what():  ./test: bad number of arguments 1
Aborted (core dumped)

+1 rzeczywiście jest użyteczne, ale należy pamiętać, że vsnprintfjest to funkcja niestandardowa. Większość implementacji, które widziałem, implementuje to lub coś podobnego, ale jest ono specyficzne dla implementacji.
John Dibling,

1
@larsmans wspomina powyżej, że w rzeczywistości jest to część standardu C, więc cofam to
John Dibling

2
Co to ma wspólnego z C?
onemasse

2

printf

  1. printf służy do wykonywania wydruków na ekranie.
  2. składnia = printf("control string ", argument );
  3. Nie jest powiązany z wejściem / wyjściem pliku

fprintf

  1. Plik fprintf użyty do wykonania operacji zapisu w pliku wskazywanym przez uchwyt PLIKU.
  2. Składnia jest następująca fprintf (filename, "control string ", argument );
  3. Jest to związane z wejściem / wyjściem pliku

Jeśli jest to cytowane gdzie indziej, najlepiej zacytować źródło linkiem, ale zdecydowanie zachowaj cytowany tutaj tekst.
SuperBiasedMan

0

fprintfJest to związane ze strumieniami, gdzie podobnie jak printfinstrukcja podobna fprintfdo strumieni, ale niezwiązana z nimi, to znaczy fprintfjest związana z plikiem


0

sprintf: Zapisuje sformatowane dane do ciągu znaków w pamięci zamiast standardowego wyjścia

Składnia sprintf to:

#include <stdio.h>
int sprintf (char *string, const char *format
[,item [,item]…]);

Tutaj,

Łańcuch odnosi się do wskaźnika do bufora w pamięci, w którym dane mają zostać zapisane.

Format odnosi się do wskaźnika do łańcucha znaków określającego format.

Każdy element jest zmienną lub wyrażeniem określającym dane do zapisania.

Wartość zwrócona przez sprintf jest większa lub równa zero, jeśli operacja zakończy się powodzeniem lub innymi słowy, liczba zapisanych znaków, nie licząc kończącego znaku zerowego, jest zwracana i zwraca wartość mniejszą od zera, jeśli wystąpił błąd.

printf: Drukuje na standardowe wyjście

Składnia dla printf to:

printf format [argument]…

Jedyna różnica między sprintf () a printf () polega na tym, że sprintf () zapisuje dane w tablicy znaków, podczas gdy printf () zapisuje dane na standardowe wyjście, standardowe wyjście.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.