Question

I'm trying to make a class with a char* ptr to where I can print data with automatic allocation.

class String 
{
    char* data;
    size_t size;
    int pos;
    void init(size_t size)
    {
        this->size = size;
        data = new char[this->size+1];

        data[0] = 0;
        pos = 0;
    }

public:

String(size_t size=1)
{
    init(size);
}
    ...

    void show();
    void s_printf(char *format, ...);
}

I have the allocation, and raii things everything working ok. But my wrapper function, doesn't process the variable arguments the way I want. I'm using va_list,va_start,va_end to the best of my knowledge but it seems that is not enough.

Code:

void sprintf(char *format, ...)
{
    va_list args;
    va_start (args, format);

    int c = vsnprintf(&data[pos],size-pos,format,args);

    // this value is different on windows and linux (or msvc and gcc)
    if((c == -1) || (c > (size-pos)))
    {
        this->size *= 2;

        data = (char*)realloc(data,this->size);

        this->sprintf(format,args);
    }
    else
    {
        pos += c;
        data[pos] = 0;
    }

    va_end (args);

    return;
}

The reallocation, the handling of the variable "pos" and "size", everything is ok. But the formatting is wrong:

Example:

String x;

x.sprintf("thing %d, ",123);
x.sprintf("other thing");

x.show();

On windows it prints:

thing 5698652, other thing

On linux, the same thing and sometimes, from my testing, the "other thing" pointer value is even used as the first "%d" in "thing %d" (so it prints "thing address,") where address is the address of the char* "other thing"

Was it helpful?

Solution

Since you cannot reuse a va_list, you should recreate it in order to repeat the print:

void sprintf(char *format, ...)
{
  while(true)
  {
    va_list args;
    va_start (args, format);

    int c = vsnprintf(&data[pos],size-pos,format,args);

    va_end (args);

    // this value is different on windows and linux (or msvc and gcc)
    if((c == -1) || (c > (size-pos)))
    {
        this->size *= 2;
        data = (char*)realloc(data,this->size);
        continue;
    }
    else
    {
        pos += c;
        data[pos] = 0;
    }
    return;
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top