2013-03-27 65 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 2013-03-27 13:21:36

+0

我試過,但它沒有工作:(好吧,我只是編輯代碼,以顯示 – 2013-03-27 13:24:31

+0

我不認爲該函數的簽名是正確的。'void ordered(int x,double y ...)'意思是'void ordered(int x,double y,...)'。也就是說,可變參數不是一個double類型的序列,而是一個在double參數之後的未知類型序列,同時這意味着你的實現是不正確的(丟棄函數的第二個參數) – 2013-03-27 13:32:46

回答

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

這並沒有解決問題,他似乎有興趣在第一次印刷後再次印刷序列* – 2013-03-27 13:35:21

+0

哇,這是個傑出的人! – 2013-03-27 13:39:31

+1

@DavidRodríguez-dribeas別忘了滾動。 – RedX 2013-03-27 13:39:58

3

從手冊頁:

va_end()

va_start()每次調用必須由va_end()在相同功能的相應調用相匹配。在 呼叫va_end(ap後)變量ap是未定義的。

多次遍歷 的列表,每個括號內都有va_start()va_end()都是可能的。

你能告訴我你試過的代碼,但它沒有工作

注意:另請參見va_copy,使用它可以在破壞性地遍歷它之前複製arguments,然後遍歷重複。

1

簡單的答案(忽略可變參數是如何真正起作用的,我覺得很難找到printf之外的有效使用情況)是複製自己的論點。那麼,實際上一個簡單的答案是不會使用可變參數...爲什麼你沒有通過一個容器(或在使用initializer_list的C + + 11?)

+0

當然,即使對於'printf',使用C++ 11可變參數模板也幾乎沒有任何理由使用可變參數... – 2013-03-28 07:03:37

+0

@MatthieuM。我沒有看到任何我喜歡'printf'沒有可變參數的實現......嗯,我真的沒有看到很多實現。但目前最好的候選者是'printf'周圍的可變參數包裝器,它執行類型檢查,然後轉發到真實的'printf',同時提供可變參數模板的類型安全性和'printf'的性能(在發佈模式中,類型測試可以是'#ifdef' -ed) – 2013-03-28 12:15:32

+0

考慮到編譯器對它進行了特定的檢查,這樣做幾乎沒有什麼好處。我認爲主要問題是沒有人真正考慮過這個問題。如果我進入'printf'重新編碼,我可能會藉此機會更新格式字符串以迎合* objects *以及普通數據類型(這是'printf'的主要缺陷之一)。 – 2013-03-28 12:35:09