2011-12-04 47 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;