yarkov
@yarkov
Помог ответ? Отметь решением.

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

Пытался сделать обертку над printf:
void echo(char * const msg, ...)
{
	va_list arguments;
	char *format = (char*)malloc((sizeof(PACKAGE_NAME) + sizeof(PACKAGE_VERSION) + sizeof(msg)) * sizeof(arguments));
	sprintf(format, "[%s-%s]: %s\n", PACKAGE_NAME, PACKAGE_VERSION, msg);
	va_start(arguments, msg);
	vprintf(format, arguments);
	va_end(arguments);
}

// use:
echo("TEST: %d, %d, %d, %d, %d", 1, 2, 3, 4, 5); // вывод: TEST: 1

Я запутался ))) Как исправить функцию?

#UPD1
Почитал ответы и теперь функция выглядит так:
void echo(char * const msg, ...)
{
	va_list arguments;
	va_start(arguments, msg);

	static const char* FORMAT = "[%s-%s]: ";
	char *msgbuf = (char*)malloc(strlen(msg) * sizeof(arguments));
	char *format = (char*)malloc(strlen(FORMAT) + strlen(PACKAGE_NAME) + strlen(PACKAGE_VERSION) + 1);

	vsprintf(msgbuf, msg, arguments);
	sprintf(format, FORMAT, PACKAGE_NAME, PACKAGE_VERSION);
	printf("%s%s\n", format, msgbuf);

	va_end(arguments);
	free(msgbuf);
	free(format);
}

Но магия в другом. Вызывая из разных мест можно получить разные результаты ))) Приведу код без лишнего:
int main (int argc, char * const argv[], char * const argp[])
{
	// Здесь все как надо работает
	Print.echo(_("MSG: %d, %d, %d, %d"), 1, 2, 3, 4);
	Print.echo(_("One of the arguments %s, %s, %s, %s, %s is mandatory"), ArgKeys[4].manstr, ArgKeys[5].manstr, ArgKeys[6].manstr, ArgKeys[7].manstr, ArgKeys[8].manstr);
/**
 * Проверка аргументов и т. п.
 */
	if (strlen(source) > 0)
	{
		while(count >= 1) {
			password = PassGen.getPassword(source, length);
			printf("%s\n", password);
			count--;
		}
	} else {
		// А тут выводится только первый аргумент, а "ArgKeys[5].manstr, ArgKeys[6].manstr, ArgKeys[7].manstr, ArgKeys[8].manstr" игнорируются
		Print.echo(_("One of the arguments %s, %s, %s, %s, %s is mandatory"), ArgKeys[4].manstr, ArgKeys[5].manstr, ArgKeys[6].manstr, ArgKeys[7].manstr, ArgKeys[8].manstr);
		exit(EXIT_FAILURE);
	}

WTF? Как такое возможно?
  • Вопрос задан
  • 279 просмотров
Пригласить эксперта
Ответы на вопрос 2
@Mercury13
Программист на «си с крестами» и не только
char *format = (char*)malloc((sizeof(PACKAGE_NAME) + sizeof(PACKAGE_VERSION) + sizeof(msg)) * sizeof(arguments));

У вас выделяется (и к тому же не освобождается) буфер совершенно рандомного размера. У меня работает и так, но это вопрос везения. Даже если написатьchar format[200]; будет лучше.

1. Более точно (запас допустим, нехватка  — нет) высчитать длину буфера.
2. Освободить его, наконец!
static const char* FORMAT1 = "[%s-%s]: %s\n";
  char *format = (char*)malloc(strlen(FORMAT1) + strlen(msg) + strlen(PACKAGE_NAME) + strlen(PACKAGE_VERSION) + 1);
  sprintf(format, "[%s-%s]: %s\n", PACKAGE_NAME, PACKAGE_VERSION, msg);
  va_start(arguments, msg);
  vprintf(format, arguments);
  va_end(arguments);
  free(format);


Более удачное, но менее универсальное решение — printf заголовок, vprintf строку.
printf("[%s-%s]: ", PACKAGE_NAME, PACKAGE_VERSION);

  va_list arguments;
  va_start(arguments, msg);
  vprintf(msg, arguments);
  va_end(arguments);

  putchar('\n');


UPD1.
Ваша новая ошибка — в коде
char *msgbuf = (char*)malloc(strlen(msg) * sizeof(arguments));

Раз уж хотите так, решение — вычислить длину буфера через snprintf.
Ответ написан
@res2001
Developer, ex-admin
По моему с самими аргументами у вас все нормально.
У меня есть похожий код (не мой), успешно работает.
По моему при выделении памяти ошибка, а именно вот этот момент: sizeof(msg)) * sizeof(arguments)
Думаю вместо этого нужно: strlen(msg)*sizeof(char)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы