我正在尝试制作一张这样的桌子......(只是没有用来分隔每个项目的点数)
每周工资单:
名称.....................标题.......总...... ......税净
Ebenezer Scrooge Partner 250.00 ..62.25 .187.75
Bob Cratchit ..........职员...... 15.00 ...... 2.00 ..13.00
这是我的代码看起来像这部分......
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);
}
我有表的第一部分(名称部分),但之后我现在不知道要做其余的表。任何人都可以帮助我吗?
由于
答案 0 :(得分:22)
您可以将printf
与左对齐标记( - )一起使用。
printf("%-10s", "title"); // this will left-align "title" in space of 10 characters
以下是一个示例程序:
#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;
}
输出:
Name Title Gross Tax Net
Bob Cratchit Clerk 15.00 2.00 13.00
答案 1 :(得分:5)
最明显的问题是:为什么使用printf,当其他工具更多时 适应?另一个经常被遗忘的问题是(最终)输出是什么 介质?如果文本最终将在打印机或文本框中 一个窗口系统,你可能会为你的工作做好准备。字体 在这样的系统上很少固定宽度,所以你必须考虑到 记帐单个字符的宽度。输出到 打印机,我建议输出LaTeX,然后进行后处理。 要输出到窗口,您正在使用的库可能有一些 表格组件将为您进行格式化。
如果你要输出一些固定宽度的字体设备 - 一个远程传输,为
例如,您可以使用iostream操纵器或用户定义
类型。 (没有办法与printf
干净利落地完成 - 你需要
iostreams。)抽象地说,定义像Name
,Title
这样的类型
而MonitaryAmount
是最干净的解决方案。在这种情况下,你只是
为该类型定义适当的<<
运算符。使用用户定义
名称和标题的类型,而不仅仅是std::string
,可能是矫枉过正,
然而,操纵器方法可能是优选的。 (非常大
应用程序,你可能会使用不同的类型
需要在不同的上下文中输出,并希望操纵者指定
他们也是。)
在最简单的解决方案中,你可以通过两个操纵器来完成:
TextField
和MoneyField
:每个操纵者都会占据这个领域
width作为构造函数的参数,并设置适当的格式
其<<
运算符中的字段,例如:
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;
}
};
和
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;
}
};
(实际上,使用Money课程可能更好。
例如,您需要特殊的乘法舍入规则;如果
你在计算税,事实上,你可能需要使用某种方式
十进制类型,而不是double
,以满足合法性
关于如何计算的要求。)
无论如何,考虑到上面的操纵者,你可以写下这样的东西:
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;
}
(这假设你已经清理了其余部分,使其成为惯用语 可维护的C ++。)
答案 2 :(得分:2)
使用标准流I/O manipulators,而不是使用标签位于特定列。更具体地说,请查看std::setw
和std::left
。
这样的事情:
std::cout << std::left << std::setw(25) << "Name" << std::setw(12) << "Title"
<< std::setw(11) << "Gross" << std::setw(9) << "Tax" << "Net\n";
答案 3 :(得分:1)
您不应该混用printf
和cout
- 他们使用不同的缓冲机制,可能会引发各种问题。当你使用C ++ stick cout
时。查看setw
和其他操纵器,根据需要格式化输出。