Home > Blockchain >  Why does this string concatenation loop not work?
Why does this string concatenation loop not work?

Time:09-21

I want to use the formatting capabilites of the cstring library together with std::string's ability to dynamically allocate. Consider the following debug-log (I wouldn't do it in production code this way but for debugs cstring is convenient):

Demo

#include <cstdio>
#include <string>
#include <array>
#include <cstdint>
#include <cstring>

std::array<std::pair<uint32_t, double>, 3> list = {{{1,11.1}, {2,22.2}, {3, 33.3}}};

int main()
{
    std::string start;
    int size = snprintf(NULL, 0, "array (size=%zu);", list.size());
    start.resize(size 1);
    snprintf(&start.front(), size 1, "array (size=%zu);", list.size());

    for (auto [a,b] : list) {
        std::string tmp;
        size = snprintf(NULL, 0, "array (size=%zu);", list.size());
        tmp.resize(size 1);
        snprintf(&tmp.front(), size 1, "\n(%u, %.2f);", a, b);
        start  = tmp;
    }

    printf("%s\n", start.c_str());
}

This doesn't work. It just prints the following:

array (size=3);

.. Instead of additionally printing each element. The loop runs however and if you emit the contents of tmp it shows that tmp actually stores the string mentioned. However, it doesn't seem to get attached to the start string the right way.

I suspect SSO gets in the way here, but I can't explain how. Afaik resize already preallocates on heap if buffer size is > 15 right? What am I overlooking?

CodePudding user response:

Basically you have resized start more then it is needed. std::string is exception and actual buffer size is one item more then size() returns to contain terminating zero.

So start contains "array (size=3);\0" just before entering loop.

Now after each update (loop iteration) content is added after this extra \0.

So when you do printf("%s\n", start.c_str()); it will stop printing on this zero. Extra content is there, but printf API is unable to reach it since encounters zero too soon.

You have also a typo with inconsistent format string.

Fixed version.

  • Related