std::string formatting like sprintf

前端 未结 30 2570
野趣味
野趣味 2020-11-22 04:42

I have to format std::string with sprintf and send it into file stream. How can I do this?

30条回答
  •  长情又很酷
    2020-11-22 05:25

    Took the idea from Dacav and pixelpoint's answer. I played around a bit and got this:

    #include 
    #include 
    #include 
    
    std::string format(const char* fmt, ...)
    {
        va_list vl;
    
        va_start(vl, fmt);
        int size = vsnprintf(0, 0, fmt, vl) + sizeof('\0');
        va_end(vl);
    
        char buffer[size];
    
        va_start(vl, fmt);
        size = vsnprintf(buffer, size, fmt, vl);
        va_end(vl);
    
        return std::string(buffer, size);
    }
    

    With sane programming practice I believe the code should be enough, however I'm still open to more secure alternatives that are still simple enough and would not require C++11.


    And here's another version that makes use of an initial buffer to prevent second call to vsnprintf() when initial buffer is already enough.

    std::string format(const char* fmt, ...)
    {
    
        va_list vl;
        int size;
    
        enum { INITIAL_BUFFER_SIZE = 512 };
    
        {
            char buffer[INITIAL_BUFFER_SIZE];
    
            va_start(vl, fmt);
            size = vsnprintf(buffer, INITIAL_BUFFER_SIZE, fmt, vl);
            va_end(vl);
    
            if (size < INITIAL_BUFFER_SIZE)
                return std::string(buffer, size);
        }
    
        size += sizeof('\0');
    
        char buffer[size];
    
        va_start(vl, fmt);
        size = vsnprintf(buffer, size, fmt, vl);
        va_end(vl);
    
        return std::string(buffer, size);
    }
    

    (It turns out that this version is just similar to Piti Ongmongkolkul's answer, only that it doesn't use new and delete[], and also specifies a size when creating std::string.

    The idea here of not using new and delete[] is to imply usage of the stack over the heap since it doesn't need to call allocation and deallocation functions, however if not properly used, it could be dangerous to buffer overflows in some (perhaps old, or perhaps just vulnerable) systems. If this is a concern, I highly suggest using new and delete[] instead. Note that the only concern here is about the allocations as vsnprintf() is already called with limits, so specifying a limit based on the size allocated on the second buffer would also prevent those.)

提交回复
热议问题