Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
Алексей Инкин
Зарегистрирован: 19.09.2004 Сообщения: 32 Откуда: Россия, Нижний Новгород
|
Добавлено: Вс Мар 20 2005 18:58 Заголовок сообщения: Функции с переменным количеством аргументов в C++ |
|
|
У меня есть функция с переменным количеством аргументов, которая должна обратиться, например, к printf, передав ей все свои переменные аргументы. Я знаю, что для этого используется похожая функция vprintf, и код будет примерно таким:
va_start(lstArguments, strPrintfPattern);
vprintf(strPrintfPattern, lstArguments);
va_end(lstArguments);
Это работает замечательно. Но что если мне нужно перед этими переменными аргументами вставить один свой? Строку с шаблоном модифицировать легко, а вот как пропихнуть дополнительный аргумент в список? Т.е. мне нужно, например, чтобы при вызове
fn("%i", 123);
моя функция вызывала
printf("%s%i", "My Additional String", 123);
printf я привёл для простоты, на самом деле я вызываю syslog / vsyslog, которые тоже работают с переменным количеством аргументов. Поэтому вариант писать в два захода не подходит. Вручную перебирать все аргументы тоже не хочется.
Спасибо, если кто знает, что делать... ![Smile](images/smiles/icon_smile.gif) _________________ puts("hit");
printf("uck"); |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
genok
Зарегистрирован: 01.02.2005 Сообщения: 9
|
Добавлено: Ср Мар 23 2005 05:31 Заголовок сообщения: |
|
|
Почему бы в начале функции не обрабатывать те строковые параметры, которые надо вставлять, и просто делать составную строку из нужных спецификаторов формата? Это же можно сделать при одном спецификаторе с помощью switch или для варианта с несколькими с помощью условных операторов if then else... ![Cool](images/smiles/icon_cool.gif) |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
Алексей Инкин
Зарегистрирован: 19.09.2004 Сообщения: 32 Откуда: Россия, Нижний Новгород
|
Добавлено: Ср Мар 23 2005 06:16 Заголовок сообщения: |
|
|
Если бы проблема заключалась в переделывании форматной строки, то я бы наверное не захламлял этот форум
Меня интересует следующее: хочу именно физически пропихнуть в функцию несколько дополнительных параметров, а не просто заявить об этом в строке формата. Функция существует в двух вариантах: printf(const char*, ...) и vprintf(const char*, va_list), а мне в идеале нужно что-то вроде fn(const char*, ..., va_list).
Вот появилась одна идея, как это сделать с ассемблерными вставами: вручную пропихивать параметры в стек: сначала скопировать всё, что является переменным, потом те параметры, которые мне нужно вставить, потом указатель на изменённую форматную строку. Но, наверное, это не дело, потому что программа будет привязана к конкретной системе (например, будет фиксированный размер указателя). Да и на ассемблере я длинее 20 команд ничего не писал, поэтому всё только в теории. _________________ puts("hit");
printf("uck"); |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
критикан
Зарегистрирован: 18.02.2005 Сообщения: 247
|
Добавлено: Пт Мар 25 2005 16:50 Заголовок сообщения: Машины не думают -- машины работают. |
|
|
Алексей Инкин писал(а): | Вручную перебирать все аргументы тоже не хочется. |
В стандарте С++ доходчиво написано, что ответственность за обработку аргументов функции с переменным количеством аргументов лежит на программисте. Точка. Поэтому аргументы придётся перебирать вручную. Со всеми последствиями.
--------------------------
Машины не думают -- машины работают. |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
Алексей Инкин
Зарегистрирован: 19.09.2004 Сообщения: 32 Откуда: Россия, Нижний Новгород
|
Добавлено: Пт Мар 25 2005 18:37 Заголовок сообщения: |
|
|
В стандарте не это имают в виду. Можно создать функцию, и в ней реализовать все необходимые действия. Вот тогда нужно перебирать. А можно переадресовать весь набор переменных аргументов другой функции тоже с переменным их количеством. Специально для этого для каждой функции библиотеки есть эквивалент (printf->vprintf), такая переадресация делается очень просто:
va_list lstArguments;
va_start(lstArguments, strPrintfPattern);
vprintf(strPrintfPattern, lstArguments);
va_end(lstArguments);
А меня интересует почти то же самое, но плюс пропихнуть несколько дополнительных аргументов. Вот и всё.
Кстати, где можно почитать официальные тексты стандартов? Что-то мне интересно стало. _________________ puts("hit");
printf("uck"); |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
критикан
Зарегистрирован: 18.02.2005 Сообщения: 247
|
Добавлено: Пн Мар 28 2005 08:56 Заголовок сообщения: Мыслить нужно просто. Как машины. |
|
|
Да понял я, что Вы хотите сделать. Я это не поддерживаю, но если очень уж хочется, то нужно взять описание va_list (из stdio.h или stdarg.h) и проинициализировать свой список самостоятельно. Например, так:
#include <stdio.h>
// в нём есть такое описание: typedef struct {
// char *a0; /* pointer to first homed integer argument */
// int offset; /* byte offset of next parameter */
//} va_list;
va_list lstArguments;
int lstArguments_size;
char *contentArguments_new;
#define newArg_size sizeof(char*);
...; // подсчёт количества рагументов и размера памяти, занятой аргументами, в зависимости от способа определения количества и типов переданных аргументов -- в случае vprintf() подсчёт выполняется по символам "%" в форматной строке
contentArguments_new=malloc(lstArguments_size+newArg_size);
...; //заносим в contentArguments_new свой аргумент и копируем переданные аргументы
va_start(lstArguments, *contentArguments_new);
и т. д.
----------------------
Мыслить нужно просто. Как машины. |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
|