#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