如何在 C++ 中轻松格式化数据表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14765155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:40:20  来源:igfitidea点击:

How can I easily format my data table in C++?

c++

提问by pearbear

I'm not sure, but I think I remember there being something in Java that can specify how far from the left of a window that a string or digit begins..

我不确定,但我想我记得 Java 中有一些东西可以指定字符串或数字从窗口左侧开始的距离。

How to easily format a table? I have this (using setw):

如何轻松格式化表格?我有这个(使用 setw):

Bob Doe     10.96      7.61     14.39      2.11     47.30     14.21     44.58      5.00     60.23
Helen City     10.44      7.78     16.27      1.99     48.92     13.93     53.79      5.00     70.97
Joe Green     10.90      7.33     14.49      2.05     47.91     14.15     44.45      4.70     73.98

and ideally would like:

并且理想情况下希望:

Bob           Doe        BLR  10.96   7.61  14.39   2.11  47.30  14.21  44.58   5.00  60.23  4:27.47
Helen         City       CUB  10.90   7.33  14.49   2.05  47.91  14.15  44.45   4.70  73.98  4:29.17
Joe           Green      USA  10.44   7.78  16.27   1.99  48.92  13.93  53.79   5.00  70.97  5:06.59

Is the only way calculations? Or is there some magical even more simple way?

是计算的唯一方法吗?或者有什么神奇的更简单的方法?

回答by Cyril Leroux

In C++, you have three functions to help you do what you want. There are defined in <iomanip>.
- setw()helps you defined the width of the output.
- setfill()Fill the rest with the character you want (in your case ' ').
- left(or right) allow you to define the alignment.

在 C++ 中,您可以使用三个函数来帮助您做您想做的事。中有定义<iomanip>
- setw()帮助您定义输出的宽度。
- setfill()用您想要的字符填充其余部分(在您的情况下为“ ”)。
-(或右)允许您定义对齐方式。

Here is the code to write your first line :

这是编写第一行的代码:

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
    const char separator    = ' ';
    const int nameWidth     = 6;
    const int numWidth      = 8;

    cout << left << setw(nameWidth) << setfill(separator) << "Bob";
    cout << left << setw(nameWidth) << setfill(separator) << "Doe";
    cout << left << setw(numWidth) << setfill(separator) << 10.96;
    cout << left << setw(numWidth) << setfill(separator) << 7.61;
    cout << left << setw(numWidth) << setfill(separator) << 14.39;
    cout << left << setw(numWidth) << setfill(separator) << 2.11;
    cout << left << setw(numWidth) << setfill(separator) << 47.30;
    cout << left << setw(numWidth) << setfill(separator) << 14.21;
    cout << left << setw(numWidth) << setfill(separator) << 44.58;
    cout << left << setw(numWidth) << setfill(separator) << 5.00;
    cout << left << setw(numWidth) << setfill(separator) << 60.23;
    cout << endl;

    cin.get();
}


EDIT :To reduce the code, you can use a template function :


编辑:要减少代码,您可以使用模板函数:

template<typename T> void printElement(T t, const int& width)
{
    cout << left << setw(width) << setfill(separator) << t;
}

That you can use like this :

你可以这样使用:

printElement("Bob", nameWidth);
printElement("Doe", nameWidth);
printElement(10.96, numWidth);
printElement(17.61, numWidth);
printElement(14.39, numWidth);
printElement(2.11, numWidth);
printElement(47.30, numWidth);
printElement(14.21, numWidth);
printElement(44.58, numWidth);
printElement(5.00, numWidth);
printElement(60.23, numWidth);
cout << endl;

回答by synaptik

Here are the various functions I use to display data in an organized, tabular form, along with an example demonstrating a possible use scenario.

以下是我用来以有组织的表格形式显示数据的各种函数,以及一个演示可能使用场景的示例。

Because the functions use stringstreams, they aren't as fast as other solutions, but for me that never matters --- the computing bottlekneck is elsewhere.

因为这些函数使用字符串流,所以它们没有其他解决方案那么快,但对我来说这无关紧要——计算瓶颈在别处。

One advantage of using stringstreams is that the functions alter the precision of their own (internal scope) stringstreams, instead of changing the static cout precision. So you never have to worry about unintentionally modifying precision in a way that persists to affect other parts of your code.

使用 stringstreams 的一个优点是函数改变它们自己(内部作用域)stringstreams 的精度,而不是改变静态 cout 精度。因此,您永远不必担心以一种持续影响代码其他部分的方式无意中修改精度。



DISPLAYING ARBITRARY PRECISION

显示任意精度

This prdfunction (short for "print double") simply prints a double value with a specified precision.

prd函数(“print double”的缩写)只是打印具有指定精度的双精度值。

/* Convert double to string with specified number of places after the decimal. */
std::string prd(const double x, const int decDigits) {
    stringstream ss;
    ss << fixed;
    ss.precision(decDigits); // set # places after decimal
    ss << x;
    return ss.str();
}

The following is just a variant that allows you to specify a blank-space padding to the left of the number. This can be helpful in displaying tables.

以下只是允许您在数字左侧指定空格填充的变体。这有助于显示表格。

/* Convert double to string with specified number of places after the decimal
   and left padding. */
std::string prd(const double x, const int decDigits, const int width) {
    stringstream ss;
    ss << fixed << right;
    ss.fill(' ');        // fill space around displayed #
    ss.width(width);     // set  width around displayed #
    ss.precision(decDigits); // set # places after decimal
    ss << x;
    return ss.str();
}

CENTER-ALIGN FUNCTION

中心对齐功能

This function simply center-aligns text, padding left and right with blank spaces until the returned string is as large as the specified width.

此函数只是将文本居中对齐,用空格向左和向右填充,直到返回的字符串与指定的宽度一样大。

/*! Center-aligns string within a field of width w. Pads with blank spaces
    to enforce alignment. */
std::string center(const string s, const int w) {
    stringstream ss, spaces;
    int padding = w - s.size();                 // count excess room to pad
    for(int i=0; i<padding/2; ++i)
        spaces << " ";
    ss << spaces.str() << s << spaces.str();    // format with padding
    if(padding>0 && padding%2!=0)               // if odd #, add 1 space
        ss << " ";
    return ss.str();
}

EXAMPLE OF TABULAR OUTPUT

表格输出示例

So, we could use the prdand centerfunctions above to output a table in the following fashion.

因此,我们可以使用上面的prdcenter函数以以下方式输出表格。

The code:

编码:

std::cout << center("x",10)       << " | "
          << center("x^2",10)     << " | "
          << center("(x^2)/8",10) << "\n";

std::cout << std::string(10*3 + 2*3, '-') << "\n";

for(double x=1.5; x<200; x +=x*2) {
    std::cout << prd(x,1,10)       << " | "
              << prd(x*x,2,10)     << " | "
              << prd(x*x/8.0,4,10) << "\n";
}

will print the table:

将打印表格:

    x      |    x^2     |  (x^2)/8  
------------------------------------
       1.5 |       2.25 |     0.2812
       4.5 |      20.25 |     2.5312
      13.5 |     182.25 |    22.7812
      40.5 |    1640.25 |   205.0312
     121.5 |   14762.25 |  1845.2812


RIGHT- and LEFT-ALIGN FUNCTIONS

右对齐和左对齐功能

And, of course, you can easily construct variants of the centerfunction that right- or left-align and add padding spaces to fill the desired width. Here are such functions:

而且,当然,您可以轻松构建center右对齐或左对齐的函数变体,并添加填充空间以填充所需的宽度。下面是这样的函数:

/* Right-aligns string within a field of width w. Pads with blank spaces
   to enforce alignment. */
string right(const string s, const int w) {
    stringstream ss, spaces;
    int padding = w - s.size();                 // count excess room to pad
    for(int i=0; i<padding; ++i)
        spaces << " ";
    ss << spaces.str() << s;                    // format with padding
    return ss.str();
}

/*! Left-aligns string within a field of width w. Pads with blank spaces
    to enforce alignment. */
string left(const string s, const int w) {
    stringstream ss, spaces;
    int padding = w - s.size();                 // count excess room to pad
    for(int i=0; i<padding; ++i)
        spaces << " ";
    ss << s << spaces.str();                    // format with padding
    return ss.str();
}

I'm sure there are plenty of more-elegant ways to do this kind of thing --- certainly there are more concise ways. But this is what I do. Works well for me.

我相信有很多更优雅的方法可以做这种事情——当然还有更简洁的方法。但这就是我所做的。对我来说效果很好。

回答by BlackBada

Just use sprintf with format specifiersto format fields. You can also use MFC CString

只需使用带有格式说明符的sprintf来格式化字段。你也可以使用 MFC CString

#include <iostream>
#include "stdio.h"

using namespace std;

int main()
{
    char buf[256];
    char pattern[]  = "%10s %10s     %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f";
    sprintf(buf, pattern, "Bob",  "Doe",     10.96,      7.61,     14.39,      2.11,     47.30,     14.21,     44.58,      5.00,     60.23);
    cout << buf << endl;
    sprintf(buf, pattern, "Helen", "City",     10.44,      7.78,     16.27,      1.99,     48.92,     13.93,     53.79,      5.00,     70.97);
    cout << buf << endl;
    sprintf(buf, pattern, "Joe", "Green",     10.90,      7.33,     14.49,      2.05,     47.91,     14.15,     44.45,      4.70,     73.98);
    cout << buf << endl;
}

回答by Alok Save

Assuming you want to format your output to resemble a table, what you need is I/O manipulators.
You can use setw()manipulator to set the output width and setfill()to set the filling character.

假设您想将输出格式化为类似于表格,您需要的是I/O manipulators
您可以使用setw()操作设置输出宽度和setfill()设置填充字符。

回答by Rapptz

You could do something like this to simplify the process a bit.

你可以做这样的事情来简化这个过程。

#include <iomanip>
#include <iostream>

struct TableFormat {
    int width;
    char fill;
    TableFormat(): width(14), fill(' ') {}
    template<typename T>
    TableFormat& operator<<(const T& data) {
        std::cout << data << std::setw(width) << std::setfill(fill);
        return *this;
    }
    TableFormat& operator<<(std::ostream&(*out)(std::ostream&)) {
        std::cout << out;
        return *this;
    }
};

int main() {
    TableFormat out;
    out << "Bob" << "Doe";
    out.width = 8;
    out << "BLR" << 10.96 << 7.61 << 14.39 << 2.11 << 47.30;
}

Which would print out (horribly in my case, but it's "customisable" to a degree):

哪个会打印出来(在我的情况下很糟糕,但它在某种程度上是“可定制的”):

Bob           Doe           BLR   10.96    7.61   14.39    2.11    47.3

The code is pretty self-explanatory, it's just a wrapper around std::coutto allow you to make the tedious calls easier, the second overload for operator<<is to allow you send std::endl..

代码是不言自明的,它只是一个包装器std::cout,使您可以更轻松地进行繁琐的调用,第二个重载operator<<是允许您发送std::endl..

回答by Aniket Inge

Considering an example:

考虑一个例子:

string firstname = "Bob";
string lastname = "Doe";
string country = "BLR";
float f1 = 10.96f, f2=7.61f, f3=14.39f, f4=2.11f, f5=47.30f, f6=14.21f, f7=44.58f, f8=5.00f, f9=60.23f;
string time = "4:27.47";
cout << setw(12) << firstname << set(12) << lastname;
cout << setw(5) << country << setprecision(2) << f1 << setprecision(2) << f2 << setprecision(2) << f3..
  1. use setw()to set the width while printing a string
  2. use setprecisionto set the precision for floating values
  3. read MSDN
  1. 用于setw()在打印字符串时设置宽度
  2. 用于setprecision设置浮点值的精度
  3. 阅读MSDN

回答by bames53

I'm not sure what you wrote so I can't see what's wrong, but you can get the results you want with std::setw:

我不确定你写了什么,所以我看不出有什么问题,但是你可以用 std::setw 得到你想要的结果:

#include <iostream>
#include <iomanip>

int main() {
   std::cout << std::left << std::setw(20) << "BoB" << std::setw(20) << 123.456789 << '\n';
   std::cout << std::left << std::setw(20) << "Richard" << std::setw(20) << 1.0 << '\n';
}

http://ideone.com/Iz5RXr

http://ideone.com/Iz5RXr