在 C++ 中用 printf 制作表格
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9206669/
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
Making a table with printf in c++
提问by Gvegas222
I'm trying to make a table like this.... (Just without the dots I used to separate the each item)
我正在尝试制作这样的表格....(只是没有我用来分隔每个项目的点)
Weekly Payroll:
Name.....................Title.......Gross......Tax......Net
Ebenezer Scrooge Partner 250.00 ..62.25 .187.75
Bob Cratchit ..........Clerk ......15.00 ....2.00 ..13.00
每周工资:
名称.......职称.......总......税......净额
Ebenezer Scrooge Partner 250.00 ..62.25 .187.75
Bob Cratchit .......职员......15.00 ....2.00 ..13.00
This is what my code looks like for this part....
这就是我的代码在这部分的样子......
for (int count=0; count < numberOfEmployees; count++)
{
cout << "Employee: \n";
cout << "\t Name: ";
cin.getline (employees[count].name, EMPLOYEESIZE);
cout << "\t Title: ";
cin.getline (employees[count].title, EMPLOYEESIZE);
cout << "\t SSNum: ";
cin >> employees[count].SSNum;
cout << "\t Salary: ";
cin >> employees[count].Salary;
cout << "\t Withholding Exemptions: ";
cin >> employees[count].Withholding_Exemptions;
cin.ignore();
cout << "\n";
}
double gross;
double tax;
double net;
double adjusted_income;
cout << "\n";
cout << "Weekly Payroll: \nName \t \t Title \t Gross \t Tax \t Net \n";
for (int count=0; count < numberOfEmployees; count++)
{
gross = employees[count].Salary;
adjusted_income = subtraction_times (employees[count].Salary, employees[count].Withholding_Exemptions);
tax = adjusted_income * .25;
net = subtraction (gross, tax);
printf ("\n%s", employees[count].name);
}
I have the first part of the table(the name part), but after that I dont know now to do the rest of the table. Can anyone help me?
我有表格的第一部分(名称部分),但在那之后我不知道现在要做表格的其余部分。谁能帮我?
Thanks
谢谢
回答by Meysam
You can use printf
with left-justify flag (-).
您可以printf
与左对齐标志 (-) 一起使用。
printf("%-10s", "title"); // this will left-align "title" in space of 10 characters
Here is a sample program:
这是一个示例程序:
#include <string>
using namespace std;
int main()
{
string name = "Bob Cratchit";
string title = "Clerk";
float gross = 15;
float tax = 2;
float net = 13;
printf("%-25s%-20s%-10s%-10s%-10s\n", "Name", "Title", "Gross", "Tax", "Net");
printf("%-25s%-20s%-10.2f%-10.2f%-10.2f\n", name.c_str(), title.c_str(), gross, tax, net);
return 0;
}
Output:
输出:
Name Title Gross Tax Net
Bob Cratchit Clerk 15.00 2.00 13.00
回答by James Kanze
The most obvious question is: why use printf, when other tools are more adapt? Another question, often forgotten, is what is the (final) output medium? If the text is going to end up on a printer or in a text box in a windowing system, you may have your work cut out for you. The fonts on such systems are rarely fixed width, so you'll have to take into account the width of the individual characters. For output to a printer, I would suggest outputting LaTeX and then postprocessing it. For outputting to a window, the library you're using probably has some sort of table component which will do the formatting for you.
最明显的问题是:当其他工具更适应时,为什么要使用printf?另一个经常被遗忘的问题是(最终)输出媒介是什么?如果文本最终会出现在打印机上或窗口系统中的文本框中,您可能需要为您完成工作。此类系统上的字体很少是固定宽度的,因此您必须考虑单个字符的宽度。对于输出到打印机,我建议输出 LaTeX,然后对其进行后处理。为了输出到窗口,您使用的库可能具有某种表格组件,可以为您进行格式化。
If you're outputing to some fixed width font device—a teletyp, for
example, then you can either use iostream manipulators or user defined
types. (There's no way to do this cleanly with printf
—you need
iostreams.) Abstractly speaking, defining types like Name
, Title
and MonitaryAmount
is the cleanest solution. In which case, you just
define an appropriate <<
operator for the type. Using a user defined
type for name and title, instead of just std::string
, may be overkill,
however, and the manipulator approach may be preferred. (In a very large
application, where the separate types would be justified, you're likely
to need output in different contexts, and want manipulators to specify
them as well.)
如果您要输出到某个固定宽度的字体设备(例如电传打字机),那么您可以使用 iostream 操纵器或用户定义的类型。(没有办法用printf
iostreams干净地做到这一点。)抽象地说,定义像Name
, Title
and这样的类型MonitaryAmount
是最干净的解决方案。在这种情况下,您只需<<
为该类型定义一个适当的运算符。使用用户定义的名称和标题类型,而不仅仅是std::string
,可能有点矫枉过正,而操纵器方法可能是首选。(在一个非常大的应用程序中,单独的类型是合理的,您可能需要在不同的上下文中输出,并希望操纵器也指定它们。)
In the simplest solution, you could get by with just two manipulators:
TextField
and MoneyField
: each manipulator would take the field
width as an argument to the constructor, and set the appropriate format
fields in its <<
operator, e.g.:
在最简单的解决方案中,您可以只使用两个操纵器:
TextField
和MoneyField
: 每个操纵器将字段宽度作为构造函数的参数,并在其<<
运算符中设置适当的格式字段,例如:
class TextField
{
int myWidth;
public:
TextField( int width ) : myWidth( width ) {}
friend std::ostream&
operator<<( std::ostream& dest, TextField const& manip )
{
dest.setf( std::ios_base::left, std::ios_base::adjustfield );
dest.fill( ' ' );
dest.width( manip.myWidth );
return dest;
}
};
and
和
class MoneyField
{
int myWidth;
public:
MoneyField( int width ) : myWidth( width ) {}
friend std::ostream&
operator<<( std::ostream& dest, MoneyField const& manip )
{
dest.setf( std::ios_base::right, std::ios_base::adjustfield );
dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
dest.fill( ' ' );
dest.precision( 2 );
dest.width( manip.myWidth );
return dest;
}
};
(Practically speaking, it's probably better to use a class for Money.
You'll want special rounding rules for multiplication, for example; if
you're calculating tax, in fact, you'll probably need to use some sort
of decimal type, rather than double
, in order to meet legal
requirements as to how it is calculated.)
(实际上,最好为 Money 使用一个类。例如,您需要特殊的乘法舍入规则;如果您正在计算税收,实际上,您可能需要使用某种小数类型,而不是double
为了满足有关如何计算的法律要求。)
Anyway, given the above manipulators, you can write something like:
无论如何,鉴于上述操纵器,您可以编写如下内容:
TextField name( 15 );
TextField title( 8 );
MoneyField gross( 8 );
MoneyField tax( 6 );
MoneyField net( 8 );
for ( std::vector< Employee >::const_iterator employee = employees.begin();
employee != employees.end();
++ employee ) {
std::cout << name << employee->name()
<< title << employee->title()
<< gross << employee->salary()
<< tax << calculateTax( employee->salary() )
<< net << calculateNet( employee->salary() )
<< std::endl;
}
(This assumes that you've cleaned up the rest to make it idiomatic and maintainable C++ as well.)
(这假设您已经清理了其余部分,使其也成为惯用且可维护的 C++。)
回答by Some programmer dude
Instead of using tabs to position at specific columns, use standard stream I/O manipulators. To be more specific, check out std::setw
and std::left
.
使用标准流I/O 操纵器,而不是使用选项卡来定位特定列。更具体地说,请查看std::setw
和std::left
。
Something like this:
像这样的东西:
std::cout << std::left << std::setw(25) << "Name" << std::setw(12) << "Title"
<< std::setw(11) << "Gross" << std::setw(9) << "Tax" << "Net\n";
回答by Ed Heal
You should not mix printf
and cout
- they use different buffering mechanisms and can lead you into all sort of problems. As you are using C++ stick with cout
. Look into setw
and other manipulators to format the output as required.
您不应该混合使用printf
和cout
- 它们使用不同的缓冲机制,并且会导致您遇到各种问题。当您使用 C++ 时,坚持使用cout
. 查看setw
和其他操纵器以根据需要格式化输出。