Converting data to C++ and C-style strings

Anything to C++ string

This function can be used to convert anything printable (through cout, for example) to a C++ string:

// utility to convert anthing to a string
#include <sstream>
template<typename T> std::string tostring(const T& x) {
    std::ostringstream os;
    os << x;
    return os.str();
}

Put it towards the top of your program, then you can convert a number, for example, to a string like this:

int i;
string mystring;
i = 15;
mystring = tostring(i);

C++ string into FLTK

FLTK (sadly) does not know about the standard C++ string class, but requires its textual information as C-style character arrays ("C strings"). For a message box or a label, you can use a literal string constant in double quotes "like this".

If the text you need is not constant, but you have it in a C++ string object (perhaps by using the tostring function above) you can just use its c_str() function, e.g:

string myname("Dogbert");
mybox->value(myname.c_str());

This works fine for the value() function, which makes for itself a private copy of the supplied string. However, if you are providing a label, either via the label() function, or as the last item in the constructor of a widget:

namebut = new Fl_Button(100,50,200,25, myname.c_str());

then you must not subsequently change the underlying C++ string, because that would invalidate the label (which by default is not copied, but just a pointer into the C++ string). The safest thing if you are using a string variable is to use copy_label(), which does make its own copy. You can leave the label out of the constructor, then immediately set it:

namebut = new Fl_Button(100,50,200,25);
namebut->copy_label(myname.c_str());

Alternatively, you can define your own function to make a new a C-string from a C++ string:

#include <cstring>

char* copycstr(std::string s) {
        char* cstr = new char[s.length() + 1];
        std::strcpy(cstr, s.c_str());
        return cstr;
}

// then...

namebut = new Fl_Button(100,50,200,25, copycstr(myname));

This approach will also work for functions that need an unchanging copy, but which do not have a copy_ version, for example:

mywidget->tooltip(copycstr(myname));

Anything to C string

The most general way of making a C-string from anything that can be output with the << insertion operator is to use a function like this (shorter solutions welcomed):

#include <sstream>

// Convert to C-string. Caller responsible for delete[]
template<typename T>
char* makestr(const T& i) {
    std::ostringstream os;
    os << i;
    std::string oss = os.str();
    char* sp = new char[oss.length()+1];
    sp[oss.copy(sp, std::string::npos)] = 0;
    return sp;
}

// then you can say...
int j = 42;
mybutton->label(makestr(j));

The older strstream method is a bit shorter, but modern compilers are sniffy about it:

#include <strstream>

// Convert to C-string. Caller responsible for delete[]
template<typename T>
char* makestr(const T& i) {
        std::ostrstream os;
        os << i << std::ends;
        return os.str();  // buffer claimed to outlive stream
}

A note about memory management

In all of these copy functions, the calling program owns the copied buffer. Clearly, if you don't delete[] it after all use of it has finished, you have a memory leak. This is unlikely to be a problem unless your program has the potential to make an unlimited number of copies.


Mark Colclough 17 Oct 2005, 7 Nov 2008, 3 Nov 2009