setfill libreria ejemplo c++ templates setw

c++ - libreria - "Permanente" std:: setw



setw c++ ejemplo (2)

¿Hay alguna forma de establecer std::setw manipulador std::setw (o su width función)? Mira este:

#include <iostream> #include <iomanip> #include <algorithm> #include <iterator> int main( void ) { int array[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256 }; std::cout.fill( ''0'' ); std::cout.flags( std::ios::hex ); std::cout.width( 3 ); std::copy( &array[0], &array[9], std::ostream_iterator<int>( std::cout, " " ) ); std::cout << std::endl; for( int i = 0; i < 9; i++ ) { std::cout.width( 3 ); std::cout << array[i] << " "; } std::cout << std::endl; }

Después de correr, veo:

001 2 4 8 10 20 40 80 100 001 002 004 008 010 020 040 080 100

Es decir, cada manipulador tiene su lugar excepto el setw / width que debe establecerse para cada entrada. ¿Hay alguna forma elegante de usar std::copy (u otra cosa) junto con setw ? Y por elegante, ciertamente no me refiero a crear un functor o función para escribir cosas en std::cout .


Bueno, no es posible. No hay forma de hacer que .width llamar a .width cada vez. Pero puedes usar boost, por supuesto:

#include <boost/function_output_iterator.hpp> #include <boost/lambda/lambda.hpp> #include <algorithm> #include <iostream> #include <iomanip> int main() { using namespace boost::lambda; int a[] = { 1, 2, 3, 4 }; std::copy(a, a + 4, boost::make_function_output_iterator( var(std::cout) << std::setw(3) << _1) ); }

Crea su propio functor, pero sucede detrás de la escena :)


Como setw y width no dan como resultado una configuración persistente, una solución es definir un tipo que anule el operator<< , aplicando setw antes del valor. Esto permitiría que un ostream_iterator para ese tipo funcione con std::copy como se muestra a continuación.

int fieldWidth = 4; std::copy(v.begin(), v.end(), std::ostream_iterator< FixedWidthVal<int,fieldWidth> >(std::cout, ","));

Podría definir: (1) FixedWidthVal como una clase de plantilla con parámetros para tipo de datos ( typename tipo) y ancho (valor), y (2) un operator<< para un ostream y un FixedWidthVal que aplica setw para cada inserción .

// FixedWidthVal.hpp #include <iomanip> template <typename T, int W> struct FixedWidthVal { FixedWidthVal(T v_) : v(v_) {} T v; }; template <typename T, int W> std::ostream& operator<< (std::ostream& ostr, const FixedWidthVal<T,W> &fwv) { return ostr << std::setw(W) << fwv.v; }

Entonces podría aplicarse con std::copy (o un ciclo for ):

// fixedWidthTest.cpp #include <iostream> #include <algorithm> #include <iterator> #include "FixedWidthVal.hpp" int main () { // output array of values int array[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256 }; std::copy(array,array+sizeof(array)/sizeof(int), std::ostream_iterator< FixedWidthVal<int,4> >(std::cout, ",")); std::cout << std::endl; // output values computed in loop std::ostream_iterator<FixedWidthVal<int, 4> > osi(std::cout, ","); for (int i=1; i<4097; i*=2) osi = i; // * and ++ not necessary std::cout << std::endl; return 0; }

Salida ( demo )

1, 2, 4, 8, 16, 32, 64, 128, 256, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,1024,2048,4096,