Создание таблицы с помощью printf на С ++ - PullRequest
4 голосов
/ 09 февраля 2012

Я пытаюсь создать такую ​​таблицу ... (просто без точек, которые я использовал для разделения каждого элемента)

Еженедельная заработная плата:

Имя ..................... Название ....... Gross ...... Tax ...... Net

Ebenezer Scrooge Partner 250,00 ..62,25 .187,75

Боб Кратчит .......... Клерк ...... 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); 
}

У меня есть первая часть таблицы (часть имени), но после этого я не знаю сейчас, чтобы сделать остальную часть таблицы. Кто-нибудь может мне помочь?

Спасибо

Ответы [ 4 ]

22 голосов
/ 09 февраля 2012

Вы можете использовать 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
5 голосов
/ 09 февраля 2012

Самый очевидный вопрос: зачем использовать printf, когда другие инструменты более адаптироваться? Другой вопрос, который часто забывают, это какой (окончательный) результат Средняя? Если текст собирается в конечном итоге на принтере или в текстовом поле оконная система, вы можете вырезать свою работу для вас. Шрифты На таких системах редко фиксируется ширина, поэтому вам придется принимать во учитывать ширину отдельных символов. Для вывода на принтер, я бы предложил вывести LaTeX и затем обработать его. Для вывода в окно используемая библиотека, вероятно, имеет компонент таблицы, который сделает форматирование за вас.

Если вы выводите на какое-либо устройство с шрифтом фиксированной ширины & mdash; телетайп, для Например, вы можете использовать манипуляторы iostream или пользовательские типы. (Нет способа сделать это чисто с printf - вам нужно iostreams.) Абстрактно говоря, определяя такие типы, как Name, Title и MonitaryAmount - самое чистое решение. В этом случае вы просто определите соответствующий оператор << для типа. Использование определенного пользователем введите имя и заголовок, вместо std::string, может быть излишним, однако и подход манипулятора может быть предпочтительным. (В очень большом приложение, где отдельные типы будут оправданы, вы, скорее всего, нужен вывод в разных контекстах, и хотите, чтобы манипуляторы указывали их тоже.)

В простейшем решении вы можете обойтись всего двумя манипуляторами: 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;
    }
};

и

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;
    }
};

(С практической точки зрения, вероятно, лучше использовать класс для денег. Например, вам понадобятся специальные правила округления для умножения; если Вы рассчитываете налог, на самом деле, вам, вероятно, придется использовать какой-то десятичного типа, а не 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 голосов
/ 09 февраля 2012

Вместо использования вкладок для позиционирования в определенных столбцах используйте стандартный поток Манипуляторы ввода / вывода . Чтобы быть более конкретным, проверьте 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";
1 голос
/ 09 февраля 2012

Вы не должны смешивать printf и cout - они используют разные механизмы буферизации и могут привести вас к различным проблемам. Так как вы используете C ++ stick с cout. Посмотрите на setw и другие манипуляторы, чтобы отформатировать вывод при необходимости.

...