Принуждение format_to_n использовать завершающий ноль - PullRequest
1 голос
/ 28 февраля 2020

Помимо самой распространенной (форматированной) функции, 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 с:. но я хотел бы, чтобы решение работало для нескольких аргументов.

Ответы [ 2 ]

3 голосов
/ 28 февраля 2020

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 является правильным).

1 голос
/ 28 февраля 2020

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 самого себя.

...