打印2d表(标题)

时间:2010-06-01 14:33:21

标签: c++

有没有比这个更好的方法来打印2d表?

  std::cout 
      << std::setw(25) << left << "FF.name"
      << std::setw(25) << left << "BB.name"
      << std::setw(12) << left << "sw.cycles"
      << std::setw(12) << left << "hw.cycles"  << "\n"
      << std::setw(25) << left << "------"
      << std::setw(25) << left << "------"
      << std::setw(12) << left << "---------"
      << std::setw(12) << left << "---------"  << "\n";

4 个答案:

答案 0 :(得分:2)

您可以将标题放入数组或向量中,然后自动生成正确的宽度:

boost::array<std::string, 4> head = { ... }

BOOST_FOREACH(std::string& s, head)
{
    int w = 5*(s.length()/5 + 1);
    std::cout << std::setw(w) << left << s;
}
std::cout << '\n';

BOOST_FOREACH(std::string& s, head)
{
    int w = 5*(s.length()/5 + 1);
    std::cout << std::string(w,'-');
}
std::cout << std::endl;

如果你有很多标题我可能是值得的。

答案 1 :(得分:1)

使用printf。它是C的一部分,但它仍然在C ++中得到支持。

答案 2 :(得分:0)

将功能分解为功能并且不是那么糟糕。

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

typedef std::vector< std::string > StringVector;


void printRow( std::ostream& s, const StringVector& strings )
{
    s << std::setw(25) << std::left << strings[ 0 ];
    s << std::setw(25) << std::left << strings[ 1 ];
    s << std::setw(12) << std::left << strings[ 2 ];
    s << std::setw(12) << std::left << strings[ 3 ];
    s << "\n";
}

void printHeadings( std::ostream& s, const StringVector& headings )
{
    printRow( s, headings );
    StringVector lines;
    for ( StringVector::const_iterator H  = headings.begin();
                                       H != headings.end();
                                     ++H )
    {
        lines.push_back( std::string( H->size(), '-' ) );
    }
    printRow( s, lines );
}

int main()
{
    StringVector headings( 4 );
    headings[ 0 ] = "FF.name";
    headings[ 1 ] = "BB.name";
    headings[ 2 ] = "sw.cycles";
    headings[ 3 ] = "hw.cycles";

    printHeadings( std::cout, headings );

    StringVector contents( 4 );
    contents[ 0 ] = "foo";
    contents[ 1 ] = "bar";
    contents[ 2 ] = "baz";
    contents[ 3 ] = "foobarbaz";
    printRow( std::cout, contents );

    return 0;
}

请注意,我已经省略了对字符串向量的边界检查,因为这只是一个例子。

答案 3 :(得分:0)

宽度是唯一可以重置的格式设置,因此您可以简单地简化为:

std::cout << left;
std::cout
  << std::setw(25) << "FF.name"
  << std::setw(25) << "BB.name"
  << std::setw(12) << "sw.cycles"
  << std::setw(12) << "hw.cycles"
  << "\n";

你可能会喜欢:

//...
std::cout << w(25, "FF.name");
//...

// implemented:

template<class T>
struct AtWidth {
  std::streamsize width;
  T const& obj;
  AtWidth(std::streamsize width, T const& obj) : width(width), obj(obj) {}
  template<class Stream> // easier than templating on basic_stream
  friend Stream& operator<<(Stream& s, AtWidth const& value) {
    s.width(value.width);
    return s << value.obj;
  }
};

template<class T>
AtWidth<T> w(std::streamsize width, T const& obj) {
  return AtWidth<T>(width, obj);
}

或者如果要重命名setw函数(C ++ 0x):

auto w(std::streamsize width) -> decltype(std::setw(width)) {
  return std::setw(width);
}
// ...
std::cout << w(25) << "FF.name";

(在非0x中,您必须知道您的库如何实现setw以获得正确的类型或自己重新编写它,这不是太难,BTW。)

编辑:我错过了第二行破折号,另一个答案涵盖了这一点。对此的解决方案确实是构建一个标题“对象”并立即或多或少地打印出来。