Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция с переменным количеством параметров, передача va_list в качестве параметра 
V
    Опции темы
DjoNIK
Дата 7.10.2008, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

Репутация: 4
Всего: 5



Доброго времени суток.
Возникла такая проблема, есть класс, у которого два перегруженых operator():
Код

 void operator()(const char* pszVal, ...) const
 void operator()(const wchar_t* pszVal, ...) const

Чтобы не писать куча одинакового кода возникла идея получить во 2-ой версии оператора строку в MB, а потом передать эту строку и неизвесное количество параметров в первый оператор. Что-то типа:
Код

 void operator()(const wchar_t* pszVal, ...) const
 {
    if( !pszVal || (0 == *pszVal) )
        return;

    va_list args;
    va_start(args, pszVal);
    int size_msgbuf = _vscwprintf(pszVal, args) + 1;
    int mbSize = (size_msgbuf-1)/sizeof(wchar_t);
    //::WideCharToMultiByte(CP_ACP, 0, pszVal, size_msgbuf, pszMbVal, 0, NULL, NULL);
    CMacroCall()("Для теста %s \r\n", args);
    va_end(args);
 }

В итоге получаю на выходе (идет запись в файл) НЕ то, что ожидалось.

Никто не подскажет как можно va_list передать другой функции с переменным количеством параметров, чтобы получить форматированую строку.

Или, если я в корне ошибаюсь, как реализовать все это дело?

Это сообщение отредактировал(а) DjoNIK - 7.10.2008, 15:35


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
azesmcar
Дата 7.10.2008, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



что-то вроде этого не пойдет?

Код

void f(const char* pszVal, va_list t)
{
    
}

void operator1(const char* pszVal, ...)
{
    va_list args;
    va_start(args, pszVal);    
    return f( pszVal, args );
}

void operator2(const char* pszVal, ...)
{
    va_list args;
    va_start(args, pszVal);    
    return f( pszVal, args );
}


или я неправильно понял вопрос?
PM   Вверх
DjoNIK
Дата 7.10.2008, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

Репутация: 4
Всего: 5



Во-первых (чтобы с толку не сбить читающих этот топик) - если есть va_start(), то его должен обязательно завершать va_end(). Иначе там проблемы возникают со стеком.

Во-вторых - в приведеном примере мне в методе f по t  va_arg-ом пробежаться нужно будет там неизветно какие типы. А все ради получения одной единственной форматированой строчки.

Я думал, может есть какой-то способ передать дальше весь брус параметров в таком же виде, в каком они пришли в оператор.


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
Earnest
Дата 7.10.2008, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



DjoNIK, it depends ... под микрософтом никаких проблем нет - ничего там va_end со стеком не делает, равно как и va_start. Но, чтобы соблюдать кошерность, конечно, надо и va_end вызывать.

Цитата(DjoNIK @  7.10.2008,  16:42 Найти цитируемый пост)
 думал, может есть какой-то способ передать дальше весь брус параметров в таком же виде, в каком они пришли в оператор. 

Низя никак (на C), только через va_list.

Цитата(DjoNIK @  7.10.2008,  16:42 Найти цитируемый пост)
Во-вторых - в приведеном примере мне в методе f по t  va_arg-ом пробежаться нужно будет там неизветно какие типы. А все ради получения одной единственной форматированой строчки.

Да зачем? Пробегаться будет vprintf. azesmcar нормальный выход предложил: реальный метод с параметром va_list и оболочки с многоточием, которые его вызывают.    


--------------------
...
PM   Вверх
azesmcar
Дата 8.10.2008, 06:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



DjoNIK я сам принцып писал, на va_end внимание не обратил просто..
По другому никак, в С подобное так и делается, взять хотя бы к примеру функцию vsnprintf. 
PM   Вверх
Lycifer
Дата 8.10.2008, 11:05 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 144
Регистрация: 4.11.2007

Репутация: нет
Всего: нет



Всем двойка, 
DjoNIK, при передавчи параметров в функию перевый параметр является адресным(то и есть это точка отчета), создаёш указатель присваеваеш адресс перфой переменной(&pszVal), ну а дальше раскручиваеш указатель посредством приведения и присвоении
пример:
char* pointer = &pszVal;
(переход на следующий параметр)
++pointer;
(теперь параметр типа инт)
pointer += sizeof(int);(step char 1 byte)

Это всё пиши есчё))))
PM MAIL ICQ   Вверх
DjoNIK
Дата 8.10.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

Репутация: 4
Всего: 5



Спасибо за идею.
Только с va_start(), va_end() ситуация немного непонятна.
Я читал, у Страуструпа кажется, что va_start() может модифицировать стек. И выход из функции становится невозможным.
Цитата(Earnest @  7.10.2008,  21:00 Найти цитируемый пост)
под микрософтом никаких проблем нет - ничего там va_end со стеком не делает, равно как и va_start. Но, чтобы соблюдать кошерность, конечно, надо и va_end вызывать.

Это MS компилер корректно отрабатывает?

Добавлено через 2 минуты и 49 секунд
Lycifer, я так понимаю тебе двойка.
А если второй параметр не int. И до каких пор ты будешь наращивать указатель? Можно конечно передавать одним из параметров общее кол-во переданых аргументов, но это как-то через одно место.


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
scrolscrol
Дата 8.10.2008, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 8.10.2008

Репутация: -1
Всего: нет



вот посмотрите  что имеется _http://www.lineage-game.ru/?r=Toolsa&s=10

PM MAIL   Вверх
Lycifer
Дата 8.10.2008, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 144
Регистрация: 4.11.2007

Репутация: нет
Всего: нет



Цитата

Lycifer, я так понимаю тебе двойка.
А если второй параметр не int. И до каких пор ты будешь наращивать указатель? Можно конечно передавать одним из параметров общее кол-во переданых аргументов, но это как-то через одно место. 
 - ты понял что ты вообще пишеш? посмотри реализацию va_start(),va_end()? посмори printf(), если не знание не снимает ответственности, перестань писать глупости
Теб две двойки
PM MAIL ICQ   Вверх
azesmcar
Дата 8.10.2008, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Lycifer
ответьте на вопрос...чем отличаеться va_list от вашего char*?

это вопрос риторический, потому отвечу на него сам...
Код

typedef char *  va_list;

ничем, а процесс арифметических операций с указателями который вы так прекрасно расписали реализован в соответствующих макросах va_arg
Код

#define va_arg _crt_va_arg
...
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

PM   Вверх
DjoNIK
Дата 8.10.2008, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

Репутация: 4
Всего: 5



Lycifer, я посмотрел define-ы. Вторую двойку признаю smile


И не подскажите ответ на вопрос в моем 3-ем посте.


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
Lycifer
Дата 8.10.2008, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 144
Регистрация: 4.11.2007

Репутация: нет
Всего: нет



Цитата

ничем, а процесс арифметических операций с указателями который вы так прекрасно расписали реализован в соответствующих макросах va_arg


Цитата

Цитата

Lycifer, я так понимаю тебе двойка.
А если второй параметр не int. И до каких пор ты будешь наращивать указатель? Можно конечно передавать одним из параметров общее кол-во переданых аргументов, но это как-то через одно место. 
 - ты понял что ты вообще пишеш? посмотри реализацию va_start(),va_end()? посмори printf(), если не знание не снимает ответственности, перестань писать глупости
Теб две двойки 

???????????????????????????????????????????????????
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0874 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.