简体   繁体   中英

c++ function like printf

i have this function

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

if i try this

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

the result are "test" not "test test" what are wrong ?

It seems like you expect va_start / va_end to do a sort of loop over the parameters. That's not the case at all, you need to do the iteration yourself.

But variadic functions don't provide a way of getting the number of arguments passed, so you can't loop safely the way you are doing it either. You'll need to:

  • Change the first parameter so that it indicates the number of arguments you're passing.
  • Change the calling convention so you allways pass a NULL as the last argument.

Both of there are error-prone and require careful coding at the call sites, which is not great.

Look here for an example of how to iterate over the parameters.

You should really consider using std::string s. They have a handy operator+ , so you don't have to do any of that trickery.

If you really do want to do it the hard way, make sure that:

  • You initialize your local vLen parameter
  • Use strcat to concatenate C-style strings (safe as long as you really did allocate enough memory, but not the most efficient here)

The critical line is this one:

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

You're copying the contents of the argument string to the beginning of your output string. You need to given strncpy() a pointer past the point of your last copy so that you're appending data rather than overwriting.

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

The above comments also apply.

What you miss is some loop, extracting va_arg . Also, you give no hints as to how many arguments you're passing, you should either terminate the list with NULL or pass the number.

What you have produced isn't really C++, but in terms of the output you are seeing I believe:

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

Is merely taking pString (which contains the string "test") and copying it directly to vToate. So what you return is the string "test".

There are numerous ways to concatenate various data types to a single string in C++, but the one I find the most simple is using std:stringstream:

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

It looks you're unclear about how to use variadic macros. You forgot to call va_arg to get each next element. You also need a length or sentinel value, so you can know when there aren't any more arguments. It seems like you want this:

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

Which you would then call:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM