[英]“Permanent” std::setw
Is there any way how to set std::setw
manipulator (or its function width
) permanently? 有没有办法如何永久设置
std::setw
操纵器(或其功能width
)? Look at this: 看这个:
#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;
}
After run, I see: 跑完后,我看到:
001 2 4 8 10 20 40 80 100
001 002 004 008 010 020 040 080 100
Ie every manipulator holds its place except the setw
/ width
which must be set for every entry. 即每个操纵器都保持其位置,除了必须为每个条目设置的
setw
/ width
。 Is there any elegant way how to use std::copy
(or something else) along with setw
? 有没有任何优雅的方式如何使用
std::copy
(或其他东西)和setw
? And by elegant I certainly don't mean creating own functor or function for writing stuff into std::cout
. 优雅的我当然不是要创建自己的函子或函数来写东西到
std::cout
。
Well, it's not possible. 嗯,这是不可能的。 No way to make it call
.width
each time again. 无法再次调用
.width
。 But you can use boost, of course: 但是你当然可以使用boost:
#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)
);
}
It does create its own functor, but it happens behind the scene :) 它确实创建了自己的仿函数,但它发生在幕后:)
Since setw
and width
do not result in a persistent setting, one solution is to define a type that overrides operator<<
, applying setw
before the value. 由于
setw
和width
不会导致持久设置,因此一种解决方案是定义一个覆盖operator<<
的类型,在值之前应用setw
。 This would allow an ostream_iterator
for that type to function with std::copy
as below. 这将允许该类型的
ostream_iterator
与std::copy
,如下所示。
int fieldWidth = 4;
std::copy(v.begin(), v.end(),
std::ostream_iterator< FixedWidthVal<int,fieldWidth> >(std::cout, ","));
You could define: (1) FixedWidthVal
as a template class with parameters for data type ( typename
) and width (value), and (2) an operator<<
for an ostream
and a FixedWidthVal
that applies setw
for each insertion . 您可以定义:(1)
FixedWidthVal
作为模板类,其中包含数据类型( typename
)和width(value)的参数,以及(2) ostream
的operator<<
和每个插入应用setw
的FixedWidthVal
。
// 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;
}
Then it could be applied with std::copy
(or a for
loop): 然后它可以应用
std::copy
(或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;
}
1, 2, 4, 8, 16, 32, 64, 128, 256,
1, 2, 4, 8, 16, 32, 64, 128, 256, 512,1024,2048,4096,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.