Форматирование строки C++, например Python "{}". Format

Я ищу быстрый и аккуратный способ печати в хорошем формате таблицы с правильно выровненными ячейками.

Есть ли удобный способ в C++ для создания строк подстрок определенной длины, таких как формат Python

"{:10}".format("some_string")

3 ответа

Решение

У вас есть много вариантов здесь. Например, используя потоки.

source.cpp

  std::ostringstream stream;
  stream << "substring";
  std::string new_string = stream.str();

В C++20 вы сможете использовать std::format который привносит в C++ форматирование, подобное Python:

auto s = std::format("{:10}", "some_string");

А пока вы можете использовать библиотеку форматирования с открытым исходным кодом {fmt},std::format основывается на.

Отказ от ответственности: я являюсь автором {fmt} и C++20std::format.

Попробуйте это https://github.com/fmtlib/fmt

fmt::printf("Hello, %s!", "world"); // uses printf format string syntax
std::string s = fmt::format("{0}{1}{0}", "abra", "cad");

@mattn был правильным, библиотека fmt на https://github.com/fmtlib/fmt обеспечивает именно эту функциональность.

Замечательная новость заключается в том, что он принят в стандарт C++20.

Вы можете использовать библиотеку fmt, зная, что в C++20 это будет std:: fmt

https://www.zverovich.net/2019/07/23/std-format-cpp20.htmlhttps://en.cppreference.com/w/cpp/utility/format/format

Вы можете быстро написать простую функцию для возврата строки фиксированной длины.

Мы считаем, что строка str заканчивается null, buf уже определен до вызова функции.

void format_string(char * str, char * buf, int size)
{
    for (int i=0; i<size; i++)
        buf[i] = ' '; // initialize the string with spaces

    int x = 0;
    while (str[x])
    {
        if (x >= size) break;
        buf[x] = str[x]; // fill up the string
    }

    buf[size-1] = 0; // termination char
}

Используется в качестве

char buf[100];
char str[] = "Hello";
format_string(str, buf, sizeof(buf));
printf(buf);

Если вы не можете использовать fmt, как упоминалось выше, лучшим способом будет использовать класс-оболочку для форматирования. Вот что я сделал однажды:

#include <iomanip>
#include <iostream>

class format_guard {
  std::ostream& _os;
  std::ios::fmtflags _f;

public:
  format_guard(std::ostream& os = std::cout) : _os(os), _f(os.flags()) {}
  ~format_guard() { _os.flags(_f); }
};

template <typename T>
struct table_entry {
  const T& entry;
  int width;
  table_entry(const T& entry_, int width_)
      : entry(entry_), width(static_cast<int>(width_)) {}
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const table_entry<T>& e) {
  format_guard fg(os);
  return os << std::setw(e.width) << std::right << e.entry; 
}

И тогда вы будете использовать его как std::cout << table_entry("some_string", 10), Вы можете адаптировать table_entry к вашим потребностям. Если у вас нет вывода аргумента шаблона класса, вы можете реализовать make_table_entry функция для вывода типа шаблона.

format_guard необходимо, так как некоторые параметры форматирования на std::ostream липкие

Другие вопросы по тегам