2011-12-04 43 views
1

功能我有這個功能類似於C++的printf

char* copy(char* pString,...){ 
    char *vToate; 
    int vLen; 
    va_list vAp; 
    va_start(vAp,pString); 
    vLen+=strlen(pString); 
    va_end(vAp); 

    vToate=new char[vLen+1]; 

    va_list vAp1; 
    va_start(vAp1,pString); 
    strncpy(vToate,pString,strlen(pString)); 
    va_end(vAp1); 
    return vToate; 
} 

,如果我嘗試這個

char *vTest="test"; 
char *vTmp=copy(vTest," ",vTest); 
cout<<vTmp; 

結果是 「測試」 而不是 「考試考試」 什麼是錯的?

+1

這是什麼都與'printf'共同點? –

+1

'vLen'的初始化在哪裏?你對未初始化的值使用'operator + ='或者這不是整個代碼? –

+1

你永遠不會調用'va_arg()'遍歷參數列表。你也不會初始化'vLen',所以你最終用'new char []'分配一個未定義數量的內存。我很驚訝這個程序大部分時間不會立即崩潰。 –

回答

0

看起來你不清楚如何使用可變宏。您忘記調用va_arg來獲取每個下一個元素。您還需要一個長度或標記值,以便您可以知道什麼時候沒有更多參數。好像你想這樣:

char *copy(char *str, ...) 
{ 
    va_arg ap; 
    va_start(str, ap); 
    int len = 0; 
    char *sp; 
    for(sp=str; sp; sp=va_arg(ap, char*)) 
     len+=strlen(sp); 
    va_end(ap); 
    va_start(ap); 
    char *dst = new char[len+1]; 
    int pos = 0;   
    for(sp=str; sp; sp=va_arg(ap, char*)){ 
     memcpy(dst+pos, sp, strlen(sp)); 
     pos+=strlen(sp); 
    } 
    va_end(ap); 
    dst[pos] = '\0'; 
    return dst; 
} 

,你會再調用:

char *str = copy("foo", " ", "bar", NULL); 
0

的臨界線是這個:

strncpy(vToate,pString,strlen(pString)); 

你複製參數字符串的內容到您的輸出字符串的開頭。你需要給一個指針以超越最後一個副本的位置,以便追加數據而不是覆蓋。

char* vCpy = vToate; 
int len = 0; 
va_list vAp1; 
    va_start(vAp1,pString); 
     len = strlen(pString); 
     strncpy(vCpy, pString, len); 
     vCpy += len; 
va_end(vAp1); 

以上意見也適用。

3

看起來像你期望va_start/va_end做參數的循環。事實並非如此,你需要自己做迭代。

但可變參數函數不提供獲取傳遞參數數量的方法,因此無法安全地循環使用它。您需要:

  • 更改第一個參數,以便它表示您傳遞的參數數量。
  • 改變調用約定,所以你總是通過一個NULL作爲最後一個參數。

這兩者都有容易出錯的問題,需要在呼叫站點仔細編碼,這並不是很好。

查看here瞭解如何迭代參數的示例。

你應該真的考慮使用std::string s。他們有一個方便的operator+,所以你不必做任何欺騙手段。

如果你真的想這樣做硬盤的方式,確保:

  • 初始化本地vLen參數
  • 使用strcat爲長串聯C風格的字符串(安全的,因爲你真的確實分配了足夠的內存,但這裏並不是最有效的)
0

你錯過的是一些循環,提取va_arg。另外,您不會提示您傳遞了多少個參數,您應該使用NULL來終止列表或傳遞該數字。

0

你已經產生的不是真正的C++,但您所看到的輸出方面我相信:

strncpy(vToate,pString,strlen(pString)); 

僅僅是服用pstring類型(其中包含字符串「測試」),並直接將其複製到vToate。所以你返回的是字符串「測試」。

有許多方法來連接各種數據類型在C++一個字符串,而是一個我覺得最簡單的使用STD:字符串流:

stringstream ss; 
ss << vTest << " " << vTest; 
char* vTmp = ss.str(); 
cout << vTmp;