Как передать форматированную строку в качестве одного аргумента в C?

#c

#c

Вопрос:

Как бы я отформатировал строку и передал ее в качестве одного аргумента в C? Если бы я хотел использовать sprintf() , мне пришлось бы сначала создать переменную, а затем сохранить в ней отформатированный результат перед передачей переменной. Это кажется беспорядочным. Есть ли какой-нибудь способ обойти это? Или это так, как это должно быть сделано?

Комментарии:

1. В C 20 вы можете использовать std::format ( en.cppreference.com/w/cpp/utility/format/format ). Однако в C, я думаю, такой функции нет.

2. Я не уверен, что вы подразумеваете под «передачей ее как одного аргумента». Некоторые системы Linux и FreeBSD предоставляют asprintf , который выделяет память для вас (но тогда вам решать освободить ее позже).

3. @NateEldredge Если у меня есть какая-то функция, которая принимает один аргумент char *msg , и я хотел бы вызвать ее с такой форматированной строкой, myFunction("My message: %s", mymsg); то это будет считаться двумя аргументами.

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

5. Хотя C не дает вам много автоматизаций, это совсем не беспорядочно. Вы должны думать о C как о важном и как о возможности узнать, как некоторые вещи работают на более глубоком уровне

Ответ №1:

«Грязная» часть может быть выделена в вспомогательную myFmtFunction функцию, которая строит строку, а затем вызывает real myFunction . Помощник по форматированию на самом деле можно использовать повторно для разных myFunction целей, передавая дополнительный аргумент указателя функции (хотя приведенный ниже пример кода этого не делает, чтобы упростить его).

 #include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

void myFunction(const char *msg)
{ printf("[myFunction] %s: %dn", msg, rand() % 6   1); }

void myFmtFunction(const char *fmt, ...)
{
  // determine required buffer size 
  va_list args;
  va_start(args, fmt);
  int len = vsnprintf(NULL, 0, fmt, args);
  va_end(args);
  if(len < 0) return;

  // format message
  char msg[len   1]; // or use heap allocation if implementation doesn't support VLAs
  va_start(args, fmt);
  vsnprintf(msg, len   1, fmt, args);
  va_end(args);

  // call myFunction
  myFunction(msg);
}

int main() {
  const char s[] = "dice roll";
  const int n = 3;
  for(int i = 1; i <= n; i  )
    myFmtFunction("%s %d of %d", s, i, n);
  return 0;
}
 

Возможный вывод:

 [myFunction] dice roll 1 of 3: 2
[myFunction] dice roll 2 of 3: 5
[myFunction] dice roll 3 of 3: 4