C++ string formatting like Python "{}".format
Asked Answered
G

6

26

I am looking for a quick and neat way to print in a nice table format with cells being aligned properly.

Is there a convenient way in c++ to create strings of substrings with certain length like python format

"{:10}".format("some_string")
Geotropism answered 30/6, 2017 at 4:53 Comment(1)
Look at the printf family in stdio.hJacinda
V
51

In C++20 you can use std::format which brings Python-like formatting to C++:

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

Until it is widely available you can use the open-source {fmt} formatting library, std::format is based on.

Disclaimer: I'm the author of {fmt} and C++20 std::format.

Vexation answered 26/1, 2020 at 2:40 Comment(4)
Nice. Too bad, though, that realistically, by the time we will be switching to C++20, it will be 2025Geotropism
You can use {fmt} in the meantime =).Vexation
Python supports this style: str = f'{v1} xxx {v2} xxx {v3}'. Does modern C++ support similar style?Jeth
No but there is a proposal to add string interpolation to C++.Vexation
K
30

Try this 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");
Konstanze answered 30/6, 2017 at 5:1 Comment(5)
Useful lib, but might be an overkill inclusion for something that can be done in a few lines, and also has license restrictions.Arianearianie
Yes, I prefer to disable some features with ifdef. ex: colors.Konstanze
I would not consider using a lib a "quick and neat way".Newmint
@Arianearianie What are the license restrictions?Woven
You have to include the MIT license to your software, whilst this license is quite permissive, there are a few downsides softwareengineering.stackexchange.com/questions/264700/…Arianearianie
T
6

You have many options here. For instance using streams.

source.cpp

  std::ostringstream stream;
  stream << "substring";
  std::string new_string = stream.str();
Tribune answered 30/6, 2017 at 4:59 Comment(0)
P
4

@mattn was correct, the fmt library at https://github.com/fmtlib/fmt provides exactly this functionality.

The exciting news is this has been accepted into the C++20 standard.

You can use the fmt library knowing that it will be std::fmt in C++20

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

Patti answered 18/12, 2019 at 23:52 Comment(0)
A
0

you can quickly write a simple function to return a fixed length string.

We consider the str string is terminated by null, buf is already defined before calling the function.

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
}

Used as

char buf[100];
char str[] = "Hello";
format_string(str, buf, sizeof(buf));
printf(buf);
Arianearianie answered 30/6, 2017 at 6:55 Comment(0)
A
-1

If you cannot use fmt as mentioned above the best way would be to use a wrapper class for formatting. Here is what I have done once:

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

And then you would use it as std::cout << table_entry("some_string", 10). You can adapt table_entry to your needs. If you don't have class template argument deduction you could implement a make_table_entry function for template type deduction.

The format_guard is needed since some formatting options on std::ostream are sticky.

Anabaptist answered 17/12, 2018 at 19:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.