2013-03-27 2 views
3

Это мой первый раз работающий с va_list и прочее, поэтому я не знаю, что я делаю. Хорошо, что у меня есть куча чисел (1, 2, 3, 4, 5) в упорядоченной функции, и я получаю их для распечатки. Это прекрасно работает.Как я могу заставить аргументы va_list повторяться?

#include <iostream> 
#include <cstdarg> 

using namespace std; 

void ordered(int num1, double list ...); 

void main() 
{ 
    ordered(5, 1.0, 2.0, 3.0, 4.0, 5.0); 
} 

void ordered(int num1, double list ...) 
{ 
    va_list arguments; 

    va_start(arguments, num1); 

    list = va_arg(arguments, double); 
    cout << "There are " << num1 << " numbers" << endl; 

    do { 
     cout << list << endl; // prints out 1 then 2 then 3 then 4 then 5 
     list = va_arg(arguments, double); 
    } while (list != 0); 

    // at this point, list = 0 

    va_end(arguments); 
} 

проблема, после того, как va_end(arguments); или перед ней, я хотел бы получить программу, чтобы распечатать мой список во второй раз; в основном распечатывать 1, 2, 3, 4, 5 еще раз, не выполняя другую функцию. Я попытался дублировать код:

va_start(arguments, num1); 

do { 
    cout << list << endl; 
    list = va_arg(arguments, double); 
} while (list != 0); 

va_end(arguments); 

без успеха. Как программа может повторить list еще раз, или это невозможно сделать в той же функции?

+1

Хороший вопрос на самом деле, но я думаю, вам также нужно повторите также 'va_start' и' va_end'. – RedX

+0

Я пробовал это, но это не сработало :(хорошо я только что отредактировал код, чтобы показать, что –

+0

Я не думаю, что подпись функции правильная. 'Void ordered (int x, double y ...)' означает 'void ordered (int x, double y, ...)'. То есть, varargs не является последовательностью «double», а последовательностью неизвестных типов, которая возникает после двойного аргумента. В то же время это означает, что ваша реализация неверна (отбрасывает второй аргумент функции) –

ответ

4

Вот рабочая реализация:

#include <iostream> 
#include <cstdarg> 

using namespace std; 

void ordered(int num1, ...); // notice changed signature 


int main(int,char**) 
{ 
    ordered(5, 1.0, 2.0, 3.0, 4.0, 5.0); 
    return 0; 
} 

void ordered(int count, ...) // notice changed signature 
{ 
    va_list arguments; 

    va_start(arguments, count); 

    cout << "There are " << count << " numbers" << endl; 

    double value = 0.0; 

    // notice how the loop changed 
    for(int i = 0; i < count; ++i) { 
     value = va_arg(arguments, double); 
     cout << value << endl; // prints out 1 then 2 then 3 then 4 then 5 
    } 

    // at this point, list = 0 

    va_end(arguments); 

    va_list arg2; 
    va_start(arg2, count); 

    cout << "There are " << count << " numbers" << endl; 

    for(int i = 0; i < count; ++i) { 
     value = va_arg(arg2, double); 
     cout << value << endl; // prints out 1 then 2 then 3 then 4 then 5 
    } 

    // at this point, list = 0 

    va_end(arg2); 

} 
+0

Это не решает вопрос. Кажется, он заинтересован в печати последовательности * снова * после первого прохода. –

+0

wow, это блестящий человек! –

+1

@ DavidRodríguez-dribeas Не забудьте прокрутить. – RedX

3

От человека странице:

va_end()

Каждый вызов va_start() должен быть согласован с соответствующим вызовом va_end() в одной и той же функции. После вызова va_end(ap) переменная ap не определена.

Количество переходов Список, каждый из которых заключен в квадратные скобки va_start() и va_end().

Не могли бы вы показать код, где вы пробовал, но это не сработало?

NB. См. Также va_copy, с помощью которого вы можете сделать дубликат arguments, прежде чем (деструктивно) пройдете его, а затем также переверните дубликат.

1

Простой ответ (не обращая внимания, как на самом деле работает с переменным числом аргументов, я считаю, что трудно найти правильный вариант использования вне printf) необходимо скопировать аргументы сами. Ну, на самом деле более простым ответом было бы не использовать varargs вообще ... Почему вы не проходите контейнер (или в C++ 11 с помощью initializer_list?)

+0

И, конечно, даже для 'printf', с C++ 11 вариационными шаблонами вряд ли есть оправдание использованию varargs ... –

+0

@MatthieuM. Я не видел каких-либо реализаций, которые мне нравятся 'printf' без переменных переменных ... Ну, действительно, я не видел многих реализаций. Но в настоящее время лучшим кандидатом является переменная args-обертка вокруг 'printf', которая проверяет тип, а затем пересылает в реальный' printf', предоставляя как безопасность типов вариативных шаблонов, так и производительность 'printf' (в режиме выпуска тип тесты могут быть «# ifdef'-ed out») –

+0

Для этого мало пользы, учитывая, что у компиляторов есть специальные проверки. Я думаю, что главная проблема заключается в том, что никто не думал об этом; и лично, если бы я перешел к перекодировке 'printf', я бы, вероятно, воспользовался возможностью обновить строку формата, чтобы обслуживать * объекты *, а также простые типы данных (что является одним из основных недостатков' printf'). –

Смежные вопросы