Fprintf, printf ve sprintf arasındaki fark nedir?


233

Herkes arasındaki farklar hakkında basit İngilizce olarak açıklayabilir printf, fprintfve sprintförneklerle?

Hangi akışta?

"C Dosya İşleme" hakkında okurken bunların üçü arasında gerçekten kafam karıştı.


4
Bazı örnek kodlar yazarak onlarla denemeler yapın. Aralarındaki farkı açıkça anlamanın çok kolay bir yolu .
Nawaz

14
Aptal arabellek taşmalarını önlemek için snprintf () 'i sprintf ()' ye tercih edin.
Maxim Egorushkin

3
Aptal arabellek taşmalarını ve kötü tip
güvensizlik

7
@Maxim, geçerli bir noktayı yükseltirken, tamponlarımın taşmayacağı ve uygulamamı parçalara ayıramayacağı bilgisini alacağım. Bu işlevlere yalnızca akış / yükseltme biçimlendiricilerinin gözle görülür darboğazlara neden olduğu gösterildiyse bakarım. :)
Moo-Juice

1
@Maxim: Nokta, gerek yok. Kodum bir darboğaz değil. 5m / sn, santralın kaç mesaj gönderebileceğidir, kaç tanesini işleyebileceğimiz değil. Öyleyse neden erken optimizasyon?
John Dibling

Yanıtlar:


238

C'de, bir "akım" bir soyutlamadır; program açısından bakıldığında, sadece bayt üreticisi (girdi akışı) veya tüketicisidir (çıktı akışı). Diskteki bir dosyaya, bir boruya, terminalinize veya yazıcı veya tty gibi başka bir aygıta karşılık gelebilir. FILETip akışında hakkında bilgi içerir. Normalde, bir FILEnesnenin içeriğini doğrudan karıştırmazsınız, sadece çeşitli I / O rutinlerine bir işaretçi iletirsiniz.

Üç standart akış vardır: stdinstandart giriş akışına stdoutbir işaretçi, standart çıkış akışına stderrbir işaretçi ve standart hata çıkış akışına bir işaretçi. Etkileşimli bir oturumda, üçü genellikle konsolunuza başvurur, ancak bunları diğer dosyalara veya cihazlara işaret edecek şekilde yönlendirebilirsiniz:

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

Bu örnekte, stdinşimdi işaret eder inputfile.dat, stdoutişaret eder output.txtve stderrişaret eder errors.txt.

fprintf biçimlendirilmiş metni belirttiğiniz çıkış akışına yazar.

printfyazmaya eşdeğerdir fprintf(stdout, ...)ve biçimlendirilmiş metni standart çıktı akışının işaret ettiği yere yazar.

sprintfcharbir akışın aksine bir diziye biçimlendirilmiş metin yazar .


4
"bu sadece bir bayt üreticisi (girdi akışı) veya tüketicisidir (çıktı akışı)." Bunlar geriye mi? Bir yapımcı bir şey yaratmaz mı (çıktı verir)? Soruyorum çünkü gerçekten bilmiyorum.
Dave Voyles

6
@DaveVoyles: Bunlar programınızın bakış açısından. Bir giriş akışı, programınızın okuması için bayt üretir; bir çıktı akışı programınızdan üretilen baytları tüketir.
John Bode

153

printfstandart çıkış akışına çıkışlar ( stdout)

fprintfbir dosya tanıtıcısına ( FILE*) gider

sprintfayırdığınız bir arabelleğe gider. ( char*)


40

printf ("format", args), verileri genellikle bilgisayar monitörü olan standart çıktıya yazdırmak için kullanılır.

sprintf (char *, "format", args) printf gibidir. Biçimlendirilmiş dizeyi standart çıktıda, yani bir monitörde görüntülemek yerine, biçimlendirilmiş verileri karakter işaretçisi (ilk parametre) ile gösterilen bir dizede saklar. Dize konumu printf ve sprint sözdizimi arasındaki tek farktır.

fprintf (DOSYA * fp, "biçim", argümanlar) tekrar printf gibidir. Burada bunun yerine, verileri monitörde görüntülerken veya bir dizeye kaydederken, oluşturulan veriler fprintf'in ilk parametresi olarak kullanılan dosya işaretçisi tarafından işaret edilen bir dosyaya kaydedilir. Dosya tanıtıcısı printf sözdiziminin tek ekidir.

Eğer stdout dosyası fprintf'de ilk parametre olarak kullanılırsa, çalışması printf'inkine eşdeğer kabul edilir.


24

printf(...)eşittir fprintf(stdout,...).

fprintf akışı çıktı almak için kullanılır.

sprintf(buffer,...) bir dizeyi arabelleğe biçimlendirmek için kullanılır.

Not orada da vsprintf, vfprintfvevprintf


vTatlar inanıyorum standart dışı olan
John Dibling

8
vTatlar C standardında çok kesinlikle vardır.
Fred Foo

@larsmans: ah, tamam. düzeltme için teşekkürler. Bu soru bir noktada bulundu [c ++]
John Dibling

2

Vsnprintf () işleviyle de çok faydalı şeyler yapabilirsiniz:

$ 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 gerçekten yararlı, ancak bunun vsnprintfStandart dışı bir işlev olduğunu unutmayın. Gördüğüm çoğu uygulama bunu ya da buna benzer bir şeyi uyguluyor, ancak uygulamaya özel.
John Dibling

1
@larsmans, bunun aslında C standardının bir parçası olduğunu belirtiyor, bu yüzden onu geri
alıyorum

2
Bunun C ile ne ilgisi var?
onemasse

2

printf

  1. printf ekranda çıktı almak için kullanılır.
  2. sözdizimi = printf("control string ", argument );
  3. Dosya giriş / çıkışıyla ilişkili değil

fprintf

  1. DOSYA tanıtıcısının işaret ettiği dosyada yazma işlemi gerçekleştirmek için kullandığı fprintf.
  2. Sözdizimi fprintf (filename, "control string ", argument );
  3. Dosya giriş / çıkışıyla ilişkilidir

Bu başka bir yerden alıntı yapılıyorsa, bir bağlantıyla kaynağı belirtmek en iyisidir, ancak kesinlikle burada alıntıladığınız metni saklayın.
SuperBiasedMan

0

fprintfBu, akışlara printfbenzer, fprintfancak akışlarla ilgili olmayan bir ifadenin , yani fprintfdosyayla ilgili olduğu akışlarla ilgilidir.


0

sprintf: Biçimlendirilmiş verileri stdout yerine bellekteki bir karakter dizesine yazar

Sprintf sözdizimi:

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

Buraya,

Dize, verilerin yazılacağı bellekteki bir arabellek işaretçisini belirtir.

Biçim, biçimi tanımlayan bir karakter dizesine işaret eder.

Her öğe, yazılacak verileri belirten bir değişken veya ifadedir.

İşlem başarılı olursa sprintf tarafından döndürülen değer sıfırdan büyük veya ona eşittir, başka bir deyişle, sonlanan boş karakteri saymamak için yazılan karakter sayısı döndürülür ve bir hata oluşursa sıfırdan küçük bir değer döndürür.

printf: Stdout'a yazdırır

Printf için sözdizimi:

printf format [argument]…

Sprintf () ve printf () arasındaki tek fark sprintf () 'nin bir karakter dizisine veri yazması, printf () ise standart çıkış aygıtı olan stdout'a veri yazmasıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.