2011-11-23 14 views
38

Estoy buscando una implementación std::ostream que actúe como /dev/null. Simplemente ignoraría todo lo que se transmita a él. ¿Existe tal cosa en las bibliotecas estándar o Boost? ¿O tengo que hacer mi propio?¿Hay una implementación null std :: ostream en C++ o bibliotecas?

+2

Puede abrir '/ dev/null' en un' std :: ofstream' –

+3

necesita algo portátil, @Alexandre – paperjam

+0

me di cuenta de (de lo contrario esto habría sido una respuesta) http://stackoverflow.com/questions/ 313111/dev-null-in-windows debería cubrir suficientes casos sin embargo. –

Respuesta

18

Si tiene boost, entonces hay una implementación istream nulo ostream & disponible en boost/iostreams/device/null.hpp. El quid de la cuestió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

Tenga cuidado con la mayoría de análisis molestos si usa esto como es ... – paperjam

+1

@paperjam, ¿puede por favor dar más detalles? –

+0

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

15

Si establece badbit en una corriente que no lo hará nada de salida:

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

Salidas:

a 
c 
+11

Obviamente, eso está modificando una variable global ... –

+2

@MatthieuM. Usar 'std :: cout << std :: boolalpha' también es una modificación de una variable global. Usando 'std :: cout << anything' también. No entiendo tu punto. – Notinlist

+0

Aunque tiene razón acerca de eso en un caso general, hay una colisión de intereses entre partes del mismo programa si uno o ambos cambian la configuración de 'std :: cout'. Pero entonces, ¿por qué es configurable? Si estuviera en el pasado y diseñara C++, separaría el filtrado de salida del flujo de salida, algo así como 'std :: out_filter of; de << std :: boolalpha << std :: whatever_option; std :: out_proxy (std :: cout, of) << "algo"; '. – Notinlist

19

La solución más simple es utilizar un std::ofstream sin abrir. Este dará como resultado un estado de error en la transmisión, pero la mayoría de los productores no lo verán; verifique esto; la expresión habitual es dejar el cheque hasta el final, después del cierre de (que lo pondría en el código que escribió, donde sabe que la secuencia no debería ser válida).

lo contrario, es bastante sencillo de implementar: basta con crear una streambuf que contiene una pequeña memoria intermedia, y lo establece en overflow (éxito siempre volviendo). Sin embargo, tenga en cuenta que esto será más lento que el archivo sin abrir ; los diversos operadores >> se mantendrán a todos de la conversión (que no hacen si la secuencia tiene un estado de error).

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

Es usual para proporcionar una clase de conveniencia derivado de istream o ostream así, que contendrá una instancia de este tampón que utiliza. Algo a lo largo de las líneas de:

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

o simplemente puede usar un std::ostream, pasando la dirección de la streambuf a ella.

+0

¿Puedes proporcionar el código? – einpoklum

+1

La idea original (sin abrir 'std :: ofstream') funciona realmente genial. ¿Es confiable/estándar compatible, y no es probable que cause problemas (¿excepciones?) En el futuro. Estoy un poco preocupado por el rendimiento, pero supongo que el único desperdicio es llamar a los operadores << << ', verificando uno' si' y volviendo? –

3

Sé que esto es hilo muy antiguo, pero me gustaría añadir esto a cualquier persona que esté buscando la misma solución sin impulso y la y la más rápida.

que combinan tres propuestas diferentes por encima y otro por escrito directamente a/dev/null (lo que implica núcleo.)

Sorprendentemente, el NullStream que obtuvo la mayoría de votos a cabo el peor.

Aquí hay resultados para 100.000.000 escribe:

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) 

Aquí está el código de prueba

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

EDITAR

La solución más rápida - en la que usamos badbit - tiene un lado negativo. Si el programa comprueba si la salida está escrita correctamente y no tengo idea de por qué el programa no debería hacer eso, entonces fallará debido a este badbit. Por lo tanto, el finalista - bost - es el ganador.

Cuestiones relacionadas