2011-11-23 26 views
38

Tôi đang tìm kiếm triển khai std::ostream hoạt động như /dev/null. Nó sẽ bỏ qua bất cứ thứ gì được truyền đến nó. Có một thứ như vậy tồn tại trong thư viện chuẩn hoặc Boost không? Hay tôi phải tự mình cuộn?Có một std null :: ostream thực hiện trong C + + hoặc thư viện?

+2

Bạn có thể mở '/ dev/null' thành' std :: ofstream' –

+3

Cần thứ gì đó di động, @Alexandre – paperjam

+0

Tôi đã tìm ra (nếu không thì đây sẽ là câu trả lời) http://stackoverflow.com/questions/ 313111/dev-null-in-windows nên bao gồm đủ trường hợp tuy nhiên. –

Trả lời

18

Nếu bạn có tăng cường, thì có một luồng không rỗng & triển khai istream có sẵn trong boost/iostreams/device/null.hpp. Các ý chính của nó:

#include "boost/iostreams/stream.hpp" 
#include "boost/iostreams/device/null.hpp" 
... 
boost::iostreams::stream<boost::iostreams::null_sink> nullOstream((boost::iostreams::null_sink())); 
... 
+6

Xem ra để phân tích cú pháp gây tranh cãi nhất nếu sử dụng ... – paperjam

+1

@paperjam, bạn có thể vui lòng xây dựng không? –

+0

@ user1229080 http://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work – boycy

15

Nếu bạn đặt badbit trên một dòng nó sẽ không ra bất cứ điều gì:

#include <iostream> 

int main() { 
    std::cout << "a\n"; 

    std::cout.setstate(std::ios_base::badbit); 
    std::cout << "b\n"; 

    std::cout.clear(); 
    std::cout << "c\n"; 
} 

Đầu ra:

a 
c 
+11

Rõ ràng, đó là sửa đổi một biến toàn cục ... –

+2

@MatthieuM. Sử dụng 'std :: cout << std :: boolalpha' cũng là một biến đổi của một biến toàn cầu. Sử dụng 'std :: cout << anything' cũng được. Tôi không hiểu ý của bạn. – Notinlist

+0

Mặc dù bạn đúng về điều đó trong một trường hợp chung có một vụ va chạm giữa các phần của cùng một chương trình nếu một hoặc cả hai thay đổi cấu hình của 'std :: cout'. Nhưng tại sao nó có thể cấu hình được? Nếu tôi đã ở trong quá khứ và tôi sẽ thiết kế C++, tôi sẽ tách lọc đầu ra khỏi luồng đầu ra, một cái gì đó như 'std :: out_filter của; của << std :: boolalpha << std :: whatever_option; std :: out_proxy (std :: cout, of) << "cái gì đó"; '. – Notinlist

19

Giải pháp đơn giản nhất là chỉ để sử dụng một chưa mở std::ofstream. Điều này sẽ dẫn đến trạng thái lỗi trong luồng nhưng hầu hết các lần xuất hiện sẽ không kiểm tra điều này; các thành ngữ thông thường là để lại kiểm tra đến cùng, sau khi các đóng (mà sẽ đặt nó trong mã bạn đã viết, nơi bạn biết rằng các dòng nên không hợp lệ).

Nếu không, nó khá thẳng về phía trước để thực hiện: chỉ cần tạo một streambuf trong đó có một bộ đệm nhỏ, và đặt nó lên trong overflow (luôn luôn trở thành công). Lưu ý rằng điều này sẽ chậm hơn so với tệp chưa mở, tuy nhiên; các toán tử >> khác nhau sẽ vẫn còn cho tất cả các chuyển đổi (mà chúng không thực hiện nếu luồng có trạng thái lỗi).

EDIT:

class NulStreambuf : public std::streambuf 
{ 
    char    dummyBuffer[ 64 ]; 
protected: 
    virtual int   overflow(int c) 
    { 
     setp(dummyBuffer, dummyBuffer + sizeof(dummyBuffer)); 
     return (c == traits_type::eof()) ? '\0' : c; 
    } 
}; 

Đó là bình thường để cung cấp một lớp tiện có nguồn gốc từ istream hoặc ostream là tốt, mà sẽ chứa một thể hiện của đệm này mà nó sử dụng. Một cái gì đó dọc theo dòng:

class NulOStream : private NulStreambuf, public std::ostream 
{ 
public: 
    NulOStream() : std::ostream(this) {} 
    NulStreambuf* rdbuf() const { return this; } 
}; 

Hoặc bạn chỉ có thể sử dụng một std::ostream, đi qua địa chỉ của các streambuf với nó.

+0

Bạn có thể cung cấp mã không? – einpoklum

+1

Ý tưởng ban đầu (chưa mở 'std :: ofstream') hoạt động thực sự tuyệt vời. Nó có đáng tin cậy/tuân thủ tiêu chuẩn và không có khả năng gây ra vấn đề (ngoại lệ?) Trong tương lai? Tôi hơi lo lắng về hiệu suất, nhưng tôi đoán chất thải duy nhất là các toán tử '<<' được gọi, kiểm tra một 'if' và quay trở lại? –

3

Tôi biết đây là chủ đề rất cũ, nhưng tôi muốn để thêm video này cho bất cứ ai đang tìm kiếm các giải pháp tương tự mà không tăng và và nhanh nhất.

tôi kết hợp ba đề xuất khác nhau ở trên và một văn bản trực tiếp đến/dev/null (vì vậy nó liên quan đến hạt nhân.)

Đáng ngạc nhiên là các NullStream rằng có nhiều phiếu nhất thực hiện điều tồi tệ nhất.

Dưới đây là kết quả cho 100.000.000 viết:

a) /dev/null : 30 seconds 
b) NullStream: 50 seconds 
c) badbit : 16 seconds (the winner in speed, but cannot test for errors!) 
d) boost  : 25 seconds (the ultimate winner) 

Đây là mã kiểm tra

#include <iostream> 
#include <fstream> 
#include <time.h> 
#include <boost/iostreams/stream.hpp> 

class NullStream : public std::ostream { 
    class NullBuffer : public std::streambuf { 
    public: 
     int overflow(int c) { return c; } 
    } m_nb; 
public: 
    NullStream() : std::ostream(&m_nb) {} 
}; 

int test(std::ostream& ofs, const char* who) { 
    const time_t t = time(NULL); 
    for (int i = 0 ; i < 1000000000 ; i++) 
     ofs << "Say the same" ; 
    std::cout << who << ": " << time(NULL) - t << std::endl; 
} 

void devnull() { 
    std::ofstream ofs; 
    ofs.open("/dev/null", std::ofstream::out | std::ofstream::app); 
    test(ofs, __FUNCTION__); 
    ofs.close(); 
} 

void nullstream() { 
    NullStream ofs; 
    test(ofs, __FUNCTION__); 
} 

void badbit() { 
    std::ofstream ofs; 
    ofs.setstate(std::ios_base::badbit); 
    test(ofs, __FUNCTION__); 
} 

void boostnull() { 
    boost::iostreams::stream<boost::iostreams::null_sink> nullOstream((boost::iostreams::null_sink())); 
    test(nullOstream, __FUNCTION__); 
} 

int main() { 
    devnull(); 
    nullstream(); 
    badbit(); 
    boostnull(); 
    return 0; 
} 

EDIT

Giải pháp nhanh nhất - nơi mà chúng tôi sử dụng badbit - có một nhược điểm. Nếu chương trình kiểm tra nếu đầu ra được viết thành công - và tôi không biết tại sao chương trình không nên làm điều đó - thì nó sẽ thất bại vì badbit này. Vì vậy, người chạy lên - bost - là người chiến thắng.