2009-01-01 5 views
28

Gibt es eine Möglichkeit, std::setw Manipulator (oder seine Funktion width) dauerhaft einzustellen? Schauen Sie sich diese:"Permanent" std :: setw

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

Nach Lauf, ich sehe:

001 2 4 8 10 20 40 80 100 

001 002 004 008 010 020 040 080 100 

D.h. jeder Manipulator behält seinen Platz mit Ausnahme der setw/width, die für jeden Eintrag eingestellt werden muss. Gibt es eine elegante Möglichkeit, std::copy (oder etwas anderes) zusammen mit setw zu verwenden? Und mit elegant meine ich sicherlich nicht, einen eigenen Funktor oder eine Funktion zum Schreiben von Zeug in std::cout zu erstellen.

Antwort

16

Nun, es ist nicht möglich. Keine Möglichkeit, es jedes Mal wieder .width aufzurufen. Aber Sie können boost, natürlich:

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

Es hat seine eigene Funktors schaffen, aber es passiert hinter den Kulissen :)

7

Da setw und width führt nicht zu einer dauerhaften Einstellung, ein Die Lösung besteht darin, einen Typ zu definieren, der operator<< überschreibt und setw vor dem Wert anwendet. Dies würde ermöglichen, dass ein ostream_iterator für diesen Typ mit std::copy wie unten funktioniert.

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

könnten Sie definieren: (1) FixedWidthVal als Template-Klasse mit den Parametern für den Datentyp (typename) und Breite (Wert), und (2) ein operator<< für ein ostream und ein FixedWidthVal die setwgilt für jede Einfügung.

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

Dann könnte es mit std::copy angewendet werden (oder eine for Schleife):

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

Ausgang (demo)

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

Wirklich schönes Design, was ich denke, wäre anwendbar zu vielen Situationen. Es wäre ideal, wenn die Breite ein Laufzeit- (anstatt einer Kompilierzeit-) Parameter wäre, obwohl ich mir keine gute Möglichkeit vorstellen kann, diese Information in "ostream_iterator" zu bekommen. Sie könnten auch eine Hilfsfunktion bereitstellen: template mit_breite (T v) {return FixedWidthVal (v, width); } 'um zu sparen, muss der Typ angegeben werden. –

+1

@j_random_hacker Nun, ich sollte Kredit geben, wo Kredit fällig ist. Ich habe diesen Ansatz von [einer Codereview-Frage] (http://codereview.stackexchange.com/q/18291/35254) übernommen und lediglich den Datentyp-Template-Parameter hinzugefügt. Netter Vorschlag für die Komfortfunktion. – chappjc