【问题标题】:Making a table with printf in c++在 C++ 中使用 printf 制作表格
【发布时间】:2012-03-01 16:13:40
【问题描述】:

我正在尝试制作这样的表格....(只是没有我用来分隔每个项目的点)

每周工资:

名称.............标题............总......税收......净

Ebenezer Scrooge 合伙人 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); 
}

我有表格的第一部分(名称部分),但之后我不知道现在要完成表格的其余部分。谁能帮帮我?

谢谢

【问题讨论】:

  • 进入循环前需要打印标题行。还可以看看 setw 和其他“iomanipulators”。
  • 使用printf有什么特别的原因吗?
  • 很可能是作业的一部分:^)

标签: c++ printf text-alignment


【解决方案1】:

不要使用制表符来定位特定列,而是使用标准流I/O manipulators。更具体地说,请查看std::setwstd::left

类似这样的:

std::cout << std::left << std::setw(25) << "Name" << std::setw(12) << "Title"
          << std::setw(11) << "Gross" << std::setw(9) << "Tax" << "Net\n";

【讨论】:

    【解决方案2】:

    您不应该混用 printfcout - 它们使用不同的缓冲机制,可能会导致您遇到各种问题。当您使用 C++ 时,请使用 cout。查看setw 和其他操纵器以根据需要格式化输出。

    【讨论】:

    • 当您说“不要混合”时,您的意思是不要将printfcout 语句交错在一个代码块中吗?还是您的意思是为您的整个代码项目选择一个(即,为您输出到std::out 的项目中涉及的每个源文件)?
    【解决方案3】:

    您可以将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
    

    【讨论】:

    • James,什么是可维护的替代方案?
    【解决方案4】:

    最明显的问题是:为什么要使用 printf,而其他工具更多 适应?另一个经常被遗忘的问题是(最终)输出是什么 中等的?如果文本最终会出现在打印机或文本框中 一个窗口系统,你可能会为你完成你的工作。字体 在这样的系统上很少有固定宽度,所以你必须考虑 考虑单个字符的宽度。对于输出到 打印机,我建议输出 LaTeX 然后对其进行后处理。 为了输出到窗口,您使用的库可能有一些 一种表格组件,它将为您进行格式化。

    如果您要输出到某个固定宽度的字体设备 — 电传打字机,例如 例如,您可以使用 iostream 操纵器或用户定义的 类型。 (没有办法用printf干净地做到这一点——你需要 iostreams。)抽象地说,定义像NameTitle这样的类型 MonitaryAmount 是最干净的解决方案。在这种情况下,您只需 为该类型定义一个适当的&lt;&lt; 运算符。使用用户定义的 输入姓名和头衔,而不仅仅是std::string,可能有点矫枉过正, 然而,操纵器方法可能是首选。 (在一个非常大的 应用程序,其中单独的类型是合理的,你很可能 需要在不同的上下文中输出,并希望操纵器指定 他们也是。)

    在最简单的解决方案中,您只需使用两个操纵器即可: TextFieldMoneyField:每个机械手都会上场 width 作为构造函数的参数,并设置适当的格式 &lt;&lt; 运算符中的字段,例如:

    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++ 也是如此。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      相关资源
      最近更新 更多