Sự khác biệt giữa cout, cerr, clog của tiêu đề iostream trong c ++ là gì? Khi nào sử dụng cái nào?


97

Tôi đã cố gắng nghiên cứu sự khác biệt giữa cout, cerrclogtrên internet nhưng không thể tìm thấy một câu trả lời hoàn hảo. Tôi vẫn chưa rõ khi nào sử dụng cái nào. Bất cứ ai có thể giải thích cho tôi, thông qua các chương trình đơn giản và minh họa một tình huống hoàn hảo về thời điểm sử dụng cái nào không?

Tôi đã truy cập trang web này hiển thị một chương trình nhỏ trên cerrclog, nhưng kết quả thu được trên đó cũng có thể được lấy bằng cách sử dụng cout. Vì vậy, tôi bối rối về cách sử dụng chính xác của mỗi người.


6
Mỗi luồng có một luồng được máy tính nhận dạng stdout, stdin(cho cin) và luồng stderrđó sử dụng theo mặc định. Tôi tin rằng clogchỉ cerrvới một thay đổi đệm.
chris

Câu trả lời:


48

stdoutstderrlà các luồng khác nhau, mặc dù cả hai đều tham chiếu đến đầu ra bảng điều khiển theo mặc định. Việc chuyển hướng (đường ống) một trong số chúng (ví dụ program.exe >out.txt) sẽ không ảnh hưởng đến cái còn lại.

Nói chung, stdoutnên được sử dụng cho đầu ra chương trình thực tế, trong khi tất cả thông tin và thông báo lỗi phải được in ra stderr, để nếu người dùng chuyển hướng đầu ra đến một tệp, thông báo thông tin vẫn được in trên màn hình chứ không phải tệp đầu ra.


131

Nói chung, bạn sử dụng std::coutcho đầu ra bình thường, std::cerrcho các lỗi và std::clogcho "ghi nhật ký" (có thể có nghĩa là bất cứ điều gì bạn muốn).

Sự khác biệt chính là nó std::cerrkhông được đệm như hai cái kia.


Trong mối quan hệ với C cũ stdoutstderr, std::couttương ứng với stdout, trong khi std::cerrstd::clogcả hai tương ứng với stderr(ngoại trừ điều đó std::clogđược đệm).


Tôi đã đọc nó clogcũng có kết quả cerr. Vậy dựa vào đó, bạn chọn cái nào? Nếu clogbình thường là để "ghi nhật ký", tại sao tôi lại muốn nó chuyển đến luồng lỗi? Nhật ký có vẻ giống "nhật ký bình thường" (hay còn gọi là cout) hơn là lỗi.
void.pointer

@ void.pointer Như tôi đã nói trong câu trả lời của mình, cả hai cerrclogsử dụng đầu ra "lỗi" tiêu chuẩn, nhưng clogđược lưu vào bộ đệm, đó có thể là lý do tại sao nó có vẻ giống hơn cout. Chọn cái nào cho đầu ra lỗi? Tôi đoán, phụ thuộc vào nhiều lý do hơn tôi có thể liệt kê và nó phải được quyết định theo từng trường hợp.
Một số lập trình viên dude

3
bạn có nghĩa là gì bởi "đệm"?
simplename

5
@simplename Đầu ra không được ghi trực tiếp, nó được lưu trữ trong bộ đệm cho đến khi bộ đệm được xóa . Đầu ra cho một tệp hoặc thiết bị đầu cuối chậm về mặt lịch sử (thiết bị đầu cuối hoặc bảng điều khiển vẫn còn chậm), việc viết từng ký tự là không hiệu quả, viết một đoạn byte hiệu quả hơn nhiều.
Một số lập trình viên dude

14

Luồng xuất chuẩn (cout): cout là thể hiện của ostreamlớp. coutđược sử dụng để tạo ra đầu ra trên thiết bị đầu ra tiêu chuẩn thường là màn hình hiển thị. Dữ liệu cần thiết để hiển thị trên màn hình được chèn vào luồng đầu ra tiêu chuẩn ( cout) bằng toán tử chèn ( <<).

Luồng lỗi tiêu chuẩn không được đệm (cerr): cerr là luồng lỗi tiêu chuẩn được sử dụng để xuất ra các lỗi. Đây cũng là một thể hiện của ostreamlớp. Như cerrun-đệm vì vậy nó được sử dụng khi chúng ta cần để hiển thị các thông báo lỗi ngay lập tức. Nó không có bất kỳ bộ đệm nào để lưu thông báo lỗi và hiển thị sau này.

Luồng lỗi chuẩn được đệm (clog): Đây cũng là một thể hiện của ostreamlớp và được sử dụng để hiển thị lỗi nhưng không giống như cerrlỗi được chèn lần đầu vào bộ đệm và được lưu trữ trong bộ đệm cho đến khi nó không được lấp đầy.

đọc thêm: basic-input-output-c


11

Sự khác biệt của 3 luồng này là bộ đệm.

  1. Với cerr, đầu ra sẽ tuôn ra
    • ngay lập tức (vì cerr không sử dụng bộ đệm).
  2. Với tắc nghẽn, đầu ra tuôn ra
    • sau khi bạn hoàn thành chức năng hiện tại của mình.
    • gọi hàm flush một cách rõ ràng.
  3. Với cout, đầu ra tuôn ra
    • sau khi bạn có lệnh gọi đến bất kỳ luồng đầu ra nào (cout, cerr, clog).
    • sau khi bạn hoàn thành chức năng hiện tại của mình.
    • gọi hàm flush một cách rõ ràng.

Vui lòng kiểm tra đoạn mã sau và chạy DEBUG qua 3 dòng: f (std :: clog), f (std :: cerr), f (std :: out), sau đó mở 3 tệp đầu ra để xem điều gì đã xảy ra. Bạn có thể hoán đổi 3 dòng này để xem điều gì sẽ xảy ra.

#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";
}

10
  • Sử dụng cout cho đầu ra tiêu chuẩn.
  • Sử dụng cerr để hiển thị lỗi.
  • Sử dụng tắc để ghi nhật ký.

6
Sai, cerr chậm hơn cout vì không có bộ đệm! Giống như write vs printf
陳 力

4

Từ bản nháp tài liệu chuẩn C ++ 17:

30.4.3 Đối tượng luồng hẹp [hẹp.stream.objects]

istream cin;

1 Đối tượng cinkiểm soát đầu vào từ bộ đệm luồng liên kết với đối tượng stdin, được khai báo trong <cstdio>(30.11.1).

2 Sau khi đối tượng cinđược khởi tạo, cin.tie()trả về &cout. Mặt khác, trạng thái của nó giống như yêu cầu đối với basic_ios<char>::init(30.5.5.2).

ostream cout;

3 Đối tượng coutđiều khiển đầu ra tới bộ đệm luồng liên kết với đối tượng stdout, được khai báo trong <cstdio>(30.11.1).

ostream cerr;

4 Đối tượng cerrđiều khiển đầu ra tới bộ đệm luồng liên kết với đối tượng stderr, được khai báo trong <cstdio>(30.11.1).

5 Sau khi đối tượng cerrđược khởi tạo, cerr.flags() & unitbuflà khác không và cerr.tie()trả về &cout. Mặt khác, trạng thái của nó giống như yêu cầu đối với basic_ios<char>::init(30.5.5.2).

ostream clog;

6 Đối tượng clogđiều khiển đầu ra tới bộ đệm luồng liên kết với đối tượng stderr, được khai báo trong <cstdio>(30.11.1).

Thảo luận...

coutviết cho stdout; cerrclogđểstderr

Standard Out ( stdout) nhằm mục đích nhận đầu ra không lỗi, không chẩn đoán từ chương trình, chẳng hạn như đầu ra từ quá trình xử lý thành công có thể được hiển thị cho người dùng cuối hoặc truyền trực tiếp vào một số giai đoạn xử lý tiếp theo.

Lỗi Chuẩn ( stderr) dành cho đầu ra chẩn đoán, chẳng hạn như cảnh báo và thông báo lỗi cho biết chương trình không hoặc có thể không tạo ra đầu ra mà người dùng có thể mong đợi. Đầu vào này có thể được hiển thị cho người dùng cuối ngay cả khi dữ liệu đầu ra được chuyển đến giai đoạn xử lý tiếp theo.

cincerrbị ràng buộc vớicout

Cả hai đều xả nước couttrước khi tự xử lý các hoạt động I / O. Điều này đảm bảo các lời nhắc được gửi đến coutđược hiển thị trước khi chương trình chặn đọc đầu vào từ cinđó và đầu ra trước đó tới coutđược xóa trước khi ghi lỗi cerr, điều này giữ cho các thông báo theo thứ tự thời gian của quá trình tạo ra chúng khi cả hai đều được chuyển hướng đến cùng một thiết bị đầu cuối / tệp / Vân vân..

Điều này trái ngược với clog- nếu bạn viết ở đó, nó sẽ không được lưu vào bộ đệm và không bị ràng buộc với bất cứ thứ gì, vì vậy nó sẽ đệm số lượng nhật ký có kích thước phù hợp trước khi xả. Điều này mang lại thông lượng tin nhắn cao nhất, nhưng có nghĩa là các tin nhắn có thể không được hiển thị nhanh chóng cho người tiêu dùng đang đọc thiết bị đầu cuối hoặc theo dõi nhật ký.


1

Cả coutclog đều được đệm nhưng cerr không được đệm và tất cả chúng đều là các đối tượng được xác định trước là các thể hiện của lớp ostream. Việc sử dụng cơ bản của ba đang cout được sử dụng cho đầu vào tiêu chuẩn trong khi làm tắc nghẽncerr được sử dụng để hiển thị lỗi. Điểm chính tại sao cerr không được lưu vào bộ đệm có thể là do giả sử bạn có một số đầu ra trong bộ đệm và một ngoại lệ lỗi được đề cập trong mã thì bạn cần hiển thị lỗi đó ngay lập tức, điều này có thể được thực hiện bởi cerr một cách hiệu quả.

Xin vui lòng sửa cho tôi nếu tôi sai.


-3

cout thường được sử dụng để hiển thị một số câu lệnh trên màn hình người dùng. ex-: cout << "Arlene Batada";

đầu ra:

Arlene Batada


Điều này chỉ đề cập đến cout và không cố gắng so sánh nó với cerr hoặc clog. OP biết cout làm gì.
JPhi1618

Điều này không cung cấp câu trả lời cho câu hỏi. Khi bạn có đủ danh tiếng, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào ; thay vào đó, cung cấp câu trả lời không yêu cầu người hỏi làm rõ . - Từ đánh giá
kometen

@kometen này cố gắng trả lời câu hỏi, ngay cả khi đó là một câu trả lời được viết kém. Thay vào đó, nên bỏ phiếu từ chối, phiếu phản đối phù hợp hơn cho những sai sót kỹ thuật.
Cristik
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.