Flethuseo
Flethuseo

Reputation: 6189

need to build string in C++ without a predefined buffer size

All the examples I have sees on the web for creating a string with sprintf use a statically declared array whose size is fixed.

#include <stdio.h>
#include <math.h>

int main()
{
   char str[80];

   sprintf(str, "Value of Pi = %f", M_PI);
   puts(str);

   return(0);
}

I want to be able to do this with a dynamically sized array in the simplest way possible. I have to write some code that will print the values that compose the array:

    printf("id=%s %s-array is: ", id.value(), name);
    for (unsigned int i = 0; i < depths.size(); i++) {
        printf("%f,", depths[i]);
    }
    printf("\n");

But I don't want to do this with separate printfs.. I want to be able to put it all in a buffer that fits the string I am writing at runtime. I am inclined to think that sprintf is the best way to do this, but if there are other functions I can use in C++. Let me know.

Upvotes: 2

Views: 781

Answers (4)

user4815162342
user4815162342

Reputation: 154856

You can build a C++ string using a printf-like call with a utility function such as:

#include <cstdarg>
#include <string>
#include <vector>

std::string build_string(const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    size_t len = vsnprintf(NULL, 0, fmt, args);
    va_end(args);
    std::vector<char> vec(len + 1);
    va_start(args, fmt);
    vsnprintf(vec.data(), len + 1, fmt, args);
    va_end(args);
    return std::string(vec.begin(), vec.end() - 1);
}

std::string msg = build_string("Value of Pi = %f", M_PI) will work as expected, and you can use c_str() to pass the corresponding char * to functions that expect it (so long as you are careful that the string object is not destroyed before they are done).

Upvotes: 1

goji
goji

Reputation: 7092

Go the more idiomatic way and use a std::ostringstream:

#include <sstream>
#include <iomanip>
#include <iostream>

int main()
{    
    std::ostringstream os;    
    os << "id=" << id.value() << " " << name << "-array is: ";
    for (unsigned int i = 0; i < depths.size(); i++) {
        os << std::fixed << depths[i] << ",";
    }    
    os << "\n";

    std::cout << os.str();
}

No need to worry out buffer size or memory allocation then ..

Upvotes: 4

The idiomatic C++ way (as @Troy points out) is using a string stream:

#include <cmath>
#include <iostream>
#include <sstream>
#include <string>

int main()
{
   std::ostringstream ss;
   ss << "Value of Pi = " << M_PI;

   std::string str = ss.str();

   std::cout << str << '\n';

   return(0);
}

Upvotes: 4

MooseBoys
MooseBoys

Reputation: 6783

You can use snprintf with a string length of zero to determine how many characters would have been printed. Then, allocate a buffer of this length, and re-traverse the list with the allocated buffer.

Upvotes: 2

Related Questions