Roger
Roger

Reputation: 2953

converting string into char

I know I can do this by str.c_str(), but I do not want a character constant. I want a char so that I can make some modifications.

char* removeDup(char *s)
{


        int len = strlen(s);
        int p,q, idx = -1;
    for(p = 0; p< len; p++)
   {
    char temp = s[p];
    bool flag = true;
    for(q=0;q<p;q++)
    {
        if(s[q] == temp)
        {
            flag = false;
            break;
        }
    }
    if(flag == true)
    {
        s[++idx] = temp;
    }
}
    s[++idx] = '\0';
    return s;
}

if I call this function as below, I get errors;

string s = "abcde";
removeDuplicate(s.c_str());

I need to convert this s into char and not const char.

Upvotes: 2

Views: 607

Answers (6)

Pete Cordell
Pete Cordell

Reputation: 1

In the realm of 'possible' as opposed to 'sensible' you could do:

std::string str("foo");
str = removeDup( std::auto_ptr<char>(strdup(str.c_str()).get() );

But rewriting in terms of std::string would be better.

Upvotes: 0

James Kanze
James Kanze

Reputation: 153889

The only way to legally make modifications to a std::string is through it's member functions (including the access paths they indirectly provide). Thus, you should rewrite your removeDup to take std::string::iterator as arguments, something like:

std::string
removeDup( std::string& original )
{
    std::string::iterator current = original.begin();
    std::string::iterator end = original.end();
    while ( current != end ) {
        end = std::remove( current + 1, end, *current );
        ++ current;
    }
    original.erase( end, original.end() );
    return original;
}

(I think this does what your original code does. I can't be sure, because I couldn't really figure out your original code.)

From a design point of view, this is ugly; you should probably pass a std::string const&, and return a new std::string:

std::string
removeDup( std::string const& original )
{
    std::string results;
    std::bitset<UCHAR_MAX + 1> alreadySeen;
    for ( std::string::const_iterator current = original.begin();
            current != original.end();
            ++ current ) {
        if (! alreadySeen.test( static_cast<unsigned char>( *current ) ) ) {
            results += *current;
            alreadySeen.set( static_cast<unsigned char>( *current ));
        }
    }
    return results;
}

The only time you want to get a char* from a std::string is to pass it to legacy code (or C). In such cases, std::string::c_str() is the approved method; if the function you are calling requires a char*, then:

  • if the function doesn't actually modify the string (it's not const correct, but this is the case for many C functions), then use const_cast on the return value of std::string::c_str(), otherwise

  • you must allocate a local buffer, and pass it:

    std::vector localBuffer( s.begin(), s.end() ); localBuffer.push_back( '\0' ); legacyFunction( &localBuffer[0], localBuffer.size() );

Upvotes: 1

Luchian Grigore
Luchian Grigore

Reputation: 258548

To get the underlying data from a std::string You can use:

string::data() or string::c_str(), both return a const char *.

In either case the returned data is const char * because the memory for it is allocated in some read only implementation defined region which an user program is not allowed to modify. Any attempt to modify the returned const char * would result in Undefined Behavior.

So you cannot and should not(through const_cast) modify the returned character string.

The only correct way to achieve this by creating a new char*, allocate it, and copy in the contents from the const char*:

std::string myString = "blabla";
char* myPtr = new char[myString.size() + 1];
myString.copy(myPtr, myString.size());
myPtr[myString.size()] = '\0';

Upvotes: 5

RC.
RC.

Reputation: 28197

I would suggest making a copy of the buffer, calling your function, and then setting the original string to the new char buffer. Something like:

std::string str("some string");
char tmp[str.length() + 1];
memset(tmp, 0, sizeof(tmp));
copy(str.begin(), str.end(), tmp);
str = removeDup(tmp);

Using the const buffer returned by c_str() directly and modifying it is asking for trouble. The buffer is owned by the string object and you should think of modifying that as breaking encapsulation and at minimum implementation dependent.

Upvotes: 2

Cpt. Red
Cpt. Red

Reputation: 102

Just copy it.

string str = "Hello";
char * cStr = new char[str.size()];
memcpy(cStr, str.c_str(), str.size());

Upvotes: 1

Shawabawa
Shawabawa

Reputation: 2587

I think you want this method from string:

Copy sequence of characters from string: http://www.cplusplus.com/reference/string/string/copy/

eg. If you had a string 'str', you could do this:

char buf[str.len()+1]
str.copy(buf, str.len())

//terminate with newline
buf[str.len() = '\n']

Hope that helps.

Upvotes: 0

Related Questions