Помимо самой распространенной (форматированной) функции C ++ 20 также поставляется с format_to_n, которая принимает выходной итератор и счетчик.

То, что я ищу, - это способ убедиться, что в случае, если у меня не хватило места, моя строка все еще обнуляется. Например, я хочу, чтобы следующая программа выводила 4 вместо 42.

#include<string>
#include<iostream>
#define FMT_HEADER_ONLY 
#include <fmt/format.h>
void f(char* in){
    fmt::format_to_n(in, 2,"{}{}", 42,'\0');
    std::cout << in;
}

int main(){
    char arr[]= "ABI";
    f(arr);
}

Возможно ли это без того, чтобы я вручную выполнял сравнение числа записанных символов и максимального количества символов, предоставленных мной для работы?

Если вам интересно, почему я использую '\ 0' в качестве аргумента:

Я понятия не имею, как положить завершающий символ в строке формата.

Примечание: я знаю, что для одного аргумента я могу указать max len с:. но я хотел бы решение, которое работает для нескольких аргументов.

1
NoSenseEtAl 28 Фев 2020 в 13:50

2 ответа

Лучший ответ

format_to_n возвращает результат. Вы можете использовать эту структуру:

void f(char* in){
    auto [out, size] = fmt::format_to_n(in, 2, "{}", 42);
    *out = '\0';
    std::cout << in;
}

Обратите внимание, что это может записать "42\0" в in, поэтому отрегулируйте свою емкость соответствующим образом (2 для буфера размером 3 является правильным).

3
Barry 28 Фев 2020 в 14:36

format_to_n возвращает структуру, содержащую, помимо прочего, итератор после последнего записанного символа. Поэтому довольно просто проверить разницу между этим итератором и исходным итератором по максимальному количеству символов и вставить \0 там, где это необходимо:

void f(char* in)
{
  const max_chars = 2;
  auto fmt_ret = fmt::format_to_n(in, max_chars,"{}", 42);
  char *last = fmt_ret.out;
  if(last - in == max_chars)
    --last;
  *last = '\0';

  std::cout << in;
}

Обратите внимание, что это предполагает, что в массиве содержится ровно столько символов ( включая терминатор NUL), сколько число вы пытались передать format_to_n. Вышеприведенный код, следовательно, будет перезаписывать последний символ, написанный с помощью NUL-терминатора, по существу, делая дальнейшее усечение.

Если вместо этого вы передаете format_to_n количество символов в массиве - 1, то вы всегда можете просто записать терминатор NUL в сам fmt_ret.out.

1
Nicol Bolas 28 Фев 2020 в 14:34