Apa perbedaan antara cout, cerr, clog of iostream header di c ++? Kapan menggunakan yang mana?

100

Saya mencoba meneliti perbedaan antara cout, cerrdan clogdi internet tetapi tidak dapat menemukan jawaban yang sempurna. Saya masih belum jelas kapan harus menggunakan yang mana. Adakah yang bisa menjelaskan kepada saya, melalui program sederhana dan menggambarkan situasi yang sempurna kapan harus menggunakan yang mana?

Saya mengunjungi situs ini yang menunjukkan program kecil di cerrdan clog, tetapi hasil yang diperoleh di sana juga dapat diperoleh dengan menggunakan cout. Jadi, saya bingung tentang penggunaan persis masing-masing.

Arlene Batada
sumber
6
Masing-masing memiliki aliran yang dikenali komputer stdout,, stdin(untuk cin), dan stderryang digunakan secara default. Saya percaya cloghanya cerrdengan perubahan buffering.
chris

Jawaban:

49

stdoutdan stderrmerupakan aliran yang berbeda, meskipun keduanya merujuk ke keluaran konsol secara default. Pengalihan (piping) salah satunya (mis. program.exe >out.txt) Tidak akan memengaruhi yang lain.

Umumnya, stdoutharus digunakan untuk keluaran program yang sebenarnya, sementara semua informasi dan pesan kesalahan harus dicetak ke stderr, sehingga jika pengguna mengarahkan keluaran ke file, pesan informasi masih dicetak di layar dan bukan ke file keluaran.

riv
sumber
132

Umumnya Anda menggunakan std::coutuntuk keluaran normal, std::cerruntuk kesalahan, dan std::cloguntuk "logging" (yang bisa berarti apa pun yang Anda inginkan).

Perbedaan utamanya std::cerradalah tidak buffer seperti dua lainnya.


Dalam kaitannya dengan C lama stdoutdan stderr, std::coutsesuai dengan stdout, sementara std::cerrdan std::clogkeduanya sesuai dengan stderr(kecuali yang di std::clog-buffer).

Beberapa programmer
sumber
Saya telah membaca bahwa clogjuga menghasilkan cerr. Jadi berdasarkan itu, mana yang kamu pilih? Jika clogbiasanya untuk "logging", mengapa saya ingin itu masuk ke aliran kesalahan? Log tampak lebih seperti "log normal" (alias cout) daripada kesalahan.
void.pointer
@ void.pointer Seperti yang saya katakan dalam jawaban saya, keduanya cerrdan clogmenggunakan output "error" standar, tetapi clogbuffered yang mungkin mengapa tampaknya lebih seperti itu cout. Yang mana yang dipilih untuk keluaran kesalahan? Tergantung saya kira, pada lebih banyak alasan daripada yang bisa saya sebutkan dan itu harus diputuskan dari kasus ke kasus.
Beberapa programmer dude
3
apa yang Anda maksud dengan "buffered"?
simplename
5
@simplename Output tidak ditulis secara langsung, ia disimpan dalam buffer sampai buffer tersebut dihapus . Output ke file atau terminal secara historis lambat (terminal atau konsol masih lambat), penulisan karakter demi karakter tidak efektif, penulisan potongan byte jauh lebih efektif.
Beberapa programmer dude
15

Aliran keluaran standar (cout): cout adalah turunan dari ostreamkelas. coutdigunakan untuk menghasilkan keluaran pada perangkat keluaran standar yang biasanya merupakan layar tampilan. Data yang diperlukan untuk ditampilkan di layar disisipkan dalam aliran keluaran standar ( cout) menggunakan operator penyisipan ( <<).

Aliran kesalahan standar tanpa buffer (cerr): cerr adalah aliran kesalahan standar yang digunakan untuk mengeluarkan kesalahan. Ini juga merupakan turunan dari ostreamkelas. Seperti cerradalah un-buffered sehingga digunakan ketika kita perlu untuk menampilkan pesan kesalahan segera. Itu tidak memiliki buffer untuk menyimpan pesan kesalahan dan ditampilkan nanti.

Buffered standard error stream (clog): Ini juga merupakan turunan dari ostreamkelas dan digunakan untuk menampilkan kesalahan tetapi tidak seperti cerrkesalahan yang pertama kali dimasukkan ke dalam buffer dan disimpan dalam buffer sampai tidak terisi penuh.

bacaan lebih lanjut: basic-input-output-c

roottraveller.dll
sumber
11

Perbedaan dari 3 aliran ini adalah buffering.

  1. Dengan cerr, keluarannya mengalir
    • segera (karena cerr tidak menggunakan buffer).
  2. Dengan penyumbatan, keluarannya memerah
    • setelah Anda menyelesaikan fungsi Anda saat ini.
    • secara eksplisit memanggil fungsi flush.
  3. Dengan cout, outputnya rata
    • setelah Anda memiliki panggilan ke aliran keluaran (cout, cerr, clog).
    • setelah Anda menyelesaikan fungsi Anda saat ini.
    • secara eksplisit memanggil fungsi flush.

Silakan periksa kode berikut, dan jalankan DEBUG melalui 3 baris: f (std :: clog), f (std :: cerr), f (std :: out), kemudian buka 3 file keluaran untuk melihat apa yang terjadi. Anda dapat menukar 3 baris ini untuk melihat apa yang akan terjadi.

#include <iostream>
#include <fstream>
#include <string>

void f(std::ostream &os)
{
    std::cin.clear(); // clear EOF flags
    std::cin.seekg(0, std::cin.beg); // seek to begin

    std::string line;
    while(std::getline(std::cin, line))   //input from the file in.txt
        os << line << "\n";   //output to the file out.txt
}

void test()
{
    std::ifstream in("in.txt");
    std::ofstream out("out.txt"), err("err.txt"), log("log.txt");
    std::streambuf *cinbuf = std::cin.rdbuf(), *coutbuf = std::cout.rdbuf(), *cerrbuf = std::cerr.rdbuf(),
                    *clogbuf = std::clog.rdbuf();

    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!
    std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!
    std::cerr.rdbuf(err.rdbuf());
    std::clog.rdbuf(log.rdbuf());


    f(std::clog);
    f(std::cerr);
    f(std::cout);

    std::cin.rdbuf(cinbuf);
    std::cout.rdbuf(coutbuf);
    std::cerr.rdbuf(cerrbuf);
    std::clog.rdbuf(clogbuf);
}

int main()
{
    test();
    std::cout << "123";
}
Duc-Viet Ha
sumber
10
  • Gunakan cout untuk output standar.
  • Gunakan cerr untuk menunjukkan kesalahan.
  • Gunakan clog untuk logging.
David Vargas
sumber
6
Salah, cerr lebih lambat dari cout karena non-buffer! Sama seperti write vs printf
陳 力
4

Dari draf dokumen standar C ++ 17:

30.4.3 Objek aliran sempit [narrow.stream.objects]

istream cin;

1 Objek cinmengontrol input dari buffer aliran yang terkait dengan objek stdin, dideklarasikan dalam <cstdio>(30.11.1).

2 Setelah objek cindiinisialisasi, cin.tie()kembali &cout. basic_ios<char>::initStatusnya sama dengan yang disyaratkan untuk (30.5.5.2).

ostream cout;

3 Objek coutmengontrol output ke buffer aliran yang terkait dengan objek stdout, dideklarasikan dalam <cstdio>(30.11.1).

ostream cerr;

4 Objek cerrmengontrol output ke buffer aliran yang terkait dengan objek stderr, dideklarasikan dalam <cstdio>(30.11.1).

5 Setelah objek cerrdiinisialisasi, cerr.flags() & unitbufbukan nol dan cerr.tie()kembali &cout. basic_ios<char>::initStatusnya sama dengan yang disyaratkan untuk (30.5.5.2).

ostream clog;

6 Objek clogmengontrol output ke buffer aliran yang terkait dengan objek stderr, dideklarasikan dalam <cstdio>(30.11.1).

Diskusi...

coutmenulis ke stdout; cerrdan cloguntukstderr

Standard Out ( stdout) dimaksudkan untuk menerima output non-error, non-diagnostik dari program, seperti output dari pemrosesan yang berhasil yang dapat ditampilkan ke pengguna akhir atau dialirkan ke beberapa tahap pemrosesan lebih lanjut.

Kesalahan Standar ( stderr) dimaksudkan untuk keluaran diagnostik, seperti peringatan dan pesan kesalahan yang menunjukkan bahwa program belum atau mungkin tidak menghasilkan keluaran yang diharapkan pengguna. Masukan ini dapat ditampilkan ke pengguna akhir meskipun data keluaran disalurkan ke tahap pemrosesan lebih lanjut.

cindan cerrterikatcout

Keduanya membilas coutsebelum menangani sendiri operasi I / O. Ini memastikan prompt yang dikirim ke coutterlihat sebelum blok program untuk membaca input cin, dan bahwa output sebelumnya ke coutdihapus sebelum menulis kesalahan cerr, yang membuat pesan dalam urutan kronologis pembuatannya ketika keduanya diarahkan ke terminal / file / yang sama dll ..

Ini kontras dengan clog- jika Anda menulis di sana, itu tidak akan di-buffer dan tidak terikat pada apa pun, jadi itu akan menyangga logging dalam jumlah yang layak sebelum dibilas. Ini menghasilkan throughput pesan tertinggi, tetapi berarti pesan mungkin tidak segera terlihat oleh calon konsumen yang membaca terminal atau mengikuti log.

Tony Delroy
sumber
1

Baik cout dan clog di -buffer tetapi cerr tidak di-buffer dan semua ini adalah objek yang telah ditentukan sebelumnya yang merupakan instance dari kelas ostream. Penggunaan dasar dari ketiganya adalah cout digunakan untuk input standar sedangkan clog dan cerr digunakan untuk menunjukkan kesalahan. Poin utama mengapa cerr adalah un-buffered adalah mungkin karena misalkan Anda memiliki beberapa output dalam buffer dan pengecualian kesalahan disebutkan dalam kode maka Anda perlu menampilkan kesalahan itu segera yang dapat dilakukan oleh cerr secara efektif.

Tolong koreksi saya jika saya salah.

Kashif Faraz Shamsi
sumber