类似printf的c++函数

c++ function like printf

本文关键字:函数 c++ printf 类似      更新时间:2023-10-16

我有这个函数

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;

结果是"test"而不是"test test"出什么问题了?

似乎您期望va_start/va_end对参数进行某种循环。事实并非如此,您需要自己进行迭代。

但是可变函数不提供获取传递的参数数量的方法,所以你也不能像现在这样安全地循环。你需要:

  • 改变第一个参数,使其表明你传递的参数的数量。
  • 更改调用约定,以便始终传递NULL作为最后一个参数。

这两种方法都容易出错,需要在调用处仔细编码,这不是很好。

查看此处的示例,了解如何遍历参数。

你真的应该考虑使用std::string s。他们有一个方便的operator+,所以你不必做任何诡计。

如果你真的想用困难的方式来完成它,请确保:

    初始化本地vLen参数
  • 使用strcat来连接c风格的字符串(只要你真的分配了足够的内存就安全,但不是最有效的)

看起来您不清楚如何使用可变宏。您忘记调用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] = '';
    return dst;
}

然后调用:

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

关键行如下:

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

将参数字符串的内容复制到输出字符串的开头。你需要给strncpy()一个指针,指向你上次复制的点,这样你就可以追加数据,而不是覆盖。

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);

以上注释也适用

您错过的是一些循环,提取va_arg。此外,对于传递了多少个参数也没有给出提示,您应该用NULL结束列表,或者传递数字。

您所生成的并不是真正的c++,但就您所看到的输出而言,我相信:

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

只是取pString(其中包含字符串"test")并将其直接复制到vToate。所以你返回的是字符串"test"

在c++中有很多方法可以将不同的数据类型连接到一个字符串上,但我发现最简单的方法是使用std:stringstream:
stringstream ss;
ss << vTest << " " << vTest;
char* vTmp = ss.str();
cout << vTmp;