Tetramputechture
Tetramputechture

Reputation: 2921

Converting std::string to const char*, getting errors

#include <iostream>
#include <sstream>

template <typename T>
const char* numberToString(T number) {
    std::ostringstream ss;
    ss << number;
    return ss.c_str();
}

int main() {
    printf(numberToString(123));
    return 0;
}

My error:

1>d:\programming\euler\problem 4\problem 4\problem 4\source.cpp(8): error C2039: 'c_str' : is not a member of 'std::basic_ostringstream<char,std::char_traits<char>,std::allocator<char>>'
1>          d:\programming\euler\problem 4\problem 4\problem 4\source.cpp(26) : see reference to function template instantiation 'const char *numberToString<int>(T)' being compiled
1>          with
1>          [
1>              T=int
1>          ]

Why doesn't this work?

Upvotes: 3

Views: 1770

Answers (4)

user1508519
user1508519

Reputation:

You want to do:

template <typename T>
std::string numberToString(T number) {
    std::ostringstream ss;
    ss << number;
    return ss.str();
}

int main() {
    std::cout << numberToString(123);
    return 0;
}

To get the underlying std::string in std::ostringstream, and then the resulting c-style string in std::string. As others have pointed out, the pointer returned by c_str goes out of scope, and therefore you must copy it to a buffer or to another std::string. If you insist on using printf, then use c_str on the function call:

printf("%s", numberToString(123).c_str());

For more information, see Is it a good idea to return " const char * " from a function?

Depending on what somestlstring is and what is being done there.

If it is a local variable you are returning a pointer into memory that is being released when GetSomeString completes, so it is a dangling pointer and an error.

It all boils down to the lifetime of somestlstring and the operations you perform on it. The pointer returned by .c_str() is guaranteed to be valid only up to the next mutating operation in the string. So if something changes somestlstring from the call to .c_str() and before s is constructed you will be in undefined behavior land.

However, you can simply use std::to_string.

std::string s = std::to_string(123);

Upvotes: 2

JBL
JBL

Reputation: 12907

That's because c_str() is the member function of std::string which returns a const char*.

To get the underlying string of a strinstream, you must use str().

The error was pretty much self explanatory:

error C2039: 'c_str' : is not a member of 'std::basic_ostringstream

Note however that you're returning a pointer to something (the underlying data of the temporary string returned by str()) that will not exist after the return statement (i.e. in the calling code) and that manipulating that pointer will quite sureley end up in undefined behavior.

As you are in C++, you could rather return the std::string directly, and output it with

std::cout << numberToString(123);

which would be safer.

Upvotes: 2

Zac Howland
Zac Howland

Reputation: 15872

c_str() does not exist for std::ostringstream. What you meant was:

template <typename T>
const char* numberToString(T number) 
{
    std::ostringstream ss;
    ss << number;
    return ss.str().c_str();
}

After you make that change, you will have another problem: you will be returning a pointer to a buffer that was just destroyed. To fix that, you should return a std::string:

template <typename T>
std::string numberToString(T number) 
{
    std::ostringstream ss;
    ss << number;
    return ss.str();
}

Which you can do with std::to_string already, so it is really pointless to write your own function.

Upvotes: 4

Eran
Eran

Reputation: 22020

c_str is a member of std::string, not ostringstream. If you want to get a string out of the stream, use str(). Note, however, that returning a const char* from that string is wrong - the string will go out of scope before you can use the const char*. Therefore, have your function return a string (or have it get a buffer to write to):

template <typename T>
std::string numberToString(T number) {
    std::ostringstream ss;
    ss << number;
    return ss.str();
}

Upvotes: 7

Related Questions