【发布时间】:2011-12-10 17:28:20
【问题描述】:
我想将数据发送到任何地方,我的意思是我不想在控制台或文件中打印数据,但我需要一些std::ostream 对象。该怎么做?
【问题讨论】:
-
我很确定这是一个骗子,但无法在 atm 上搜索它,因为我在 iPhone 上。
我想将数据发送到任何地方,我的意思是我不想在控制台或文件中打印数据,但我需要一些std::ostream 对象。该怎么做?
【问题讨论】:
我用过:
std::ostream bitBucket(0);
最近没有问题,尽管如果您从某个角度观察它会被标记为存在一些潜在问题(请参阅下面的链接)。
除此之外:据我了解(我也不是完全确定这一点),上面的调用最终会调用
basic_ios::init(0)并且,因为那是传入 NULL 指针,它将rdstate()函数返回的流状态设置为badbit值。这反过来会阻止流输出更多信息,而只是将其丢弃。
下面的程序展示了它的实际效果:
#include <iostream>
int main (void) {
std::ostream bitBucket(0);
bitBucket << "Hello, there!" << std::endl;
return 0;
}
The page where I got it from 也将此作为可能更清洁的解决方案(稍作修改以删除我上面第一个解决方案的重复):
#include <iostream>
class null_out_buf : public std::streambuf {
public:
virtual std::streamsize xsputn (const char * s, std::streamsize n) {
return n;
}
virtual int overflow (int c) {
return 1;
}
};
class null_out_stream : public std::ostream {
public:
null_out_stream() : std::ostream (&buf) {}
private:
null_out_buf buf;
};
null_out_stream cnul; // My null stream.
int main (void) {
std::cout << std::boolalpha;
//testing nul
std::cout << "Nul stream before: " << cnul.fail() << std::endl;
cnul << "Goodbye World!" << std::endl;
std::cout << "Nul stream after: " << cnul.fail() << std::endl;
}
【讨论】:
init),我相信它不会再尝试发送任何数据,而只是将其丢弃。对它持大粒盐。
最简单的解决方案就是输出到一个未打开的std::ofstream
(或任何其他处于错误状态的输出流)。这将导致
流永久处于错误状态。这可能是一个优势
(<< 运算符将跳过格式化),但如果您有任何代码
无法控制对错误的检查,并且如果它们执行某些特定的操作
发生,您可能会遇到问题。
否则,实现一个空流非常简单;唯一的
streambuf 你真正必须重写的函数是overflow。
像下面这样的东西应该可以解决问题:
class NulStreambuf : public std::streambuf
{
char dummyBuffer[64];
protected:
virtual int overflow( int c )
{
setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) ) ;
return (c == EOF) ? '\0' : c ;
}
};
(缓冲区会避免一些不必要的虚函数调用。在某些 平台,这有很大的不同。)
然后创建一个使用它的输出流:
class NulOStream : public NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
};
(使用继承而不是包含,可确保
在传递给ostream 之前,streambuf 已完全构建。
这在实践中通常不是必需的,但标准没有
似乎授权将尚未构建的streambuf 传递给
ostream 的构造函数。)
【讨论】:
最简单的解决方案:使用std::stringstream。
#include <sstream>
#include <iostream>
void func(std::ostream& o){
o << "blatest\n";
}
int main(){
std::stringstream black_hole;
func(std::cout);
func(black_hole);
}
stringstream 将包含输出,但如果你不使用它,它就像从未填充过一样。
【讨论】:
由于没有人提及,如果是关于抑制std或错误输出,您可以简单地关闭相应的文件描述符(例如fclose (stdout)或fclose (stderr))。
这会搞砸一切,包括 printf 或 fprintf (stderr, ...)
所以你确实会继续使用通常的cout 或cerr,但它们会变成比特桶。
【讨论】:
这里有一些建议:http://bytes.com/topic/c/answers/589209-std-null-stream
来自该网站的一个很好的答案:
使用普通的std::fstream,只为写入需要的文件打开 “/开发/空”。它应该可以工作。
如果你真的想创建自己的流,只需从 basic_ostream 并简单地将您自己的 operator
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
【讨论】: