Форматирование вывода в C++

В коде C++ у меня есть матрица двойных переменных, которые я распечатываю. Однако, поскольку все они имеют разное количество цифр, формат вывода уничтожается. Одним из решений является выполнение cout.precision(5), но я хочу, чтобы разные столбцы имели разную точность. Кроме того, поскольку в некоторых случаях встречаются отрицательные значения, наличие знака - также вызывает проблемы. Как обойти это и создать правильно отформатированный вывод?


person lovespeed    schedule 27.06.2012    source источник


Ответы (6)


Внезапно вы можете использовать setw(int) для указания ширины вывода.

как это:

std::cout << std::setw(5) << 0.2 << std::setw(10) << 123456 << std::endl;
std::cout << std::setw(5) << 0.12 << std::setw(10) << 123456789 << std::endl;

дает это:

    0.2    123456
   0.12 123456789
person stanri    schedule 27.06.2012
comment
просто к вашему сведению: при выполнении std::setw(x) убедитесь, что x больше, чем ваша десятичная точность. - person solti; 24.12.2016
comment
Это правильный ответ, но он не работает в Ubuntu (gcc) без дополнительной библиотеки: #include <iomanip>. Проверьте это здесь: stackoverflow.com/a/18983787/4960953 - person Mikhail_Sam; 09.10.2020

Ключ, как говорили другие, в использовании манипуляторов. Они забыли сказать, что обычно вы используете манипуляторы, которые пишете сами. Манипулятор FFmt (который соответствует формату F в Fortran) довольно прост:

class FFmt
{
    int myWidth;
    int myPrecision;
public:
    FFmt( int width, int precision )
        : myWidth( width )
        , myPrecision( precision )
    {
    }

    friend std::ostream& 
    operator<<( std::ostream& dest, FFmt const& fmt )
    {
        dest.setf( std::ios_base::fixed, std::ios_base::formatfield );
        dest.precision( myPrecision );
        dest.width( myWidth );
        return dest;
    }
};

Таким образом, вы можете определить переменную для каждого столбца, скажем:

FFmt col1( 8, 2 );
FFmt col2( 6, 3 );
//  ...

и написать:

std::cout  << col1 << value1
    << ' ' << col2 << value2...

В общем, за исключением самых простых программ, вам, вероятно, следует использовать не стандартные манипуляторы, а пользовательские манипуляторы, основанные на вашем приложении; например temperature и pressure, если это то, с чем вы имеете дело. Таким образом, в коде понятно, что вы форматируете, и если клиент вдруг запросит еще одну цифру в нажиме, вы точно знаете, где внести изменения.

person James Kanze    schedule 27.06.2012
comment
Помните, что вам нужно подключить ‹iomanip›, чтобы найти setw() - person user1603472; 18.06.2014
comment
@user1603472 user1603472 Да, но мой код не использует std::setw. - person James Kanze; 18.06.2014
comment
извините, мой плохой, я щелкнул не в том месте, был быстрый комментарий, чтобы вставить - person user1603472; 18.06.2014

Используйте манипуляторы.

Из примера здесь:

#include <iostream>
#include <iomanip>
#include <locale>
int main()
{
    std::cout.imbue(std::locale("en_US.utf8"));
    std::cout << "Left fill:\n" << std::left << std::setfill('*')
              << std::setw(12) << -1.23  << '\n'
              << std::setw(12) << std::hex << std::showbase << 42 << '\n'
              << std::setw(12) << std::put_money(123, true) << "\n\n";

    std::cout << "Internal fill:\n" << std::internal
              << std::setw(12) << -1.23  << '\n'
              << std::setw(12) << 42 << '\n'
              << std::setw(12) << std::put_money(123, true) << "\n\n";

    std::cout << "Right fill:\n" << std::right
              << std::setw(12) << -1.23  << '\n'
              << std::setw(12) << 42 << '\n'
              << std::setw(12) << std::put_money(123, true) << '\n';
}

Выход:

Left fill:
-1.23*******
0x2a********
USD *1.23***

Internal fill:
-*******1.23
0x********2a
USD ****1.23

Right fill:
*******-1.23
********0x2a
***USD *1.23
person John Dibling    schedule 27.06.2012

Взгляните на манипуляторы потока, особенно std::setw и std::setfill.

float f = 3.1415926535;
std::cout << std::setprecision(5)   // precision of floating point output
          << std::setfill(' ')      // character used to fill the column
          << std::setw(20)          // width of column
          << f << '\n';             // your number
person jrok    schedule 27.06.2012

Попробуйте использовать манипулятор setw. См. http://www.cplusplus.com/reference/iostream/manipulators/setw/ для получения дополнительной информации

person Premkumar U    schedule 27.06.2012

Есть способ использовать манипуляторы ввода-вывода, но я нахожу его громоздким. Я бы просто написал такую ​​функцию:

template<typename T>
std::string RightAligned(int size, const T & val)
{
    std::string x = boost::lexical_cast<std::string>(val);
    if (x.size() < size)
        x = std::string(size - x.size(), ' ') + x;
    return x;
}
person Benjamin Lindley    schedule 27.06.2012