Convert from std::string to unsigned char*

S

sposes

Im very much a newbie but perhaps somehone can help me. Ive been
searching for a way to convert a std::string to a unsigned char*

The situation is I have a function that wants a unsigned char* and I
want to give it a std::string

no matching function for call to `MD5::update(std::string&, size_t)'
candidates are: void MD5::update(unsigned char*, unsigned int)

void PrintMD5(string str){
MD5 context;

context.update(str, str.size());
context.finalize();

cout << "MD5: " << context << endl;

return;
}

I hope someone can help me solve this delema.
 
P

Phlip

sposes said:
context.update(str, str.size());

context.update(str.c_str(), str.size());

Please read a good chunk of a C++ tutorial before resuming coding. It might
not have covered c_str(), yet you would still pick enough tips to figure the
c_str() out for yourself!
 
I

Ian Collins

Phlip said:
sposes wrote:




context.update(str.c_str(), str.size());
That won't work, str.c_str() returns const char*, the OP's function
requires unsigned char*.

Passing a std::string might be unsafe, considering the function doesn't
take a const pointer as a parameter.
Please read a good chunk of a C++ tutorial before resuming coding. It might
not have covered c_str(), yet you would still pick enough tips to figure the
c_str() out for yourself!
No comment....
 
J

Jim Langston

Im very much a newbie but perhaps somehone can help me. Ive been
searching for a way to convert a std::string to a unsigned char*

The situation is I have a function that wants a unsigned char* and I
want to give it a std::string

no matching function for call to `MD5::update(std::string&, size_t)'
candidates are: void MD5::update(unsigned char*, unsigned int)

void PrintMD5(string str){
MD5 context;

context.update(str, str.size());
context.finalize();

cout << "MD5: " << context << endl;

return;
}

I hope someone can help me solve this delema.

std::string.c_str() will return a const char *. Notice very carefully this
is const. That means that the contents can't be changed through this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char array
to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];
strcpy( TempString, str.c_str() );
context.update( TempString, strlen( TempString ) );
....

If you know for a total fact that update will not be changing the contents
of the string, and you have to be absolutely sure of this, you can cast away
the const.

context.update( const_cast< char* >( str.c_str() ), str.size() );

I do this for one library I use where the designer is not using const
correctness.
 
S

Stefan Naewe

Jim said:
Im very much a newbie but perhaps somehone can help me. Ive been
searching for a way to convert a std::string to a unsigned char*

The situation is I have a function that wants a unsigned char* and I
want to give it a std::string

no matching function for call to `MD5::update(std::string&, size_t)'
candidates are: void MD5::update(unsigned char*, unsigned int)

void PrintMD5(string str){
MD5 context;

context.update(str, str.size());
context.finalize();

cout << "MD5: " << context << endl;

return;
}

I hope someone can help me solve this delema.

std::string.c_str() will return a const char *. Notice very carefully this
is const. That means that the contents can't be changed through this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char array
to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];

Why 'size * 2' ??
strcpy( TempString, str.c_str() );

You'd need a cast here.
context.update( TempString, strlen( TempString ) );
...

Why not use a std::vector ?

std::vector<unsigned char> tempV(str.begin(), str.end());
context.update(&tempV[0], tempV.size());

If you know for a total fact that update will not be changing the contents
of the string, and you have to be absolutely sure of this, you can cast away
the const.

context.update( const_cast< char* >( str.c_str() ), str.size() );

I do this for one library I use where the designer is not using const
correctness.

/S
 
J

Jim Langston

Stefan Naewe said:
Jim said:
Im very much a newbie but perhaps somehone can help me. Ive been
searching for a way to convert a std::string to a unsigned char*

The situation is I have a function that wants a unsigned char* and I
want to give it a std::string

no matching function for call to `MD5::update(std::string&, size_t)'
candidates are: void MD5::update(unsigned char*, unsigned int)

void PrintMD5(string str){
MD5 context;

context.update(str, str.size());
context.finalize();

cout << "MD5: " << context << endl;

return;
}

I hope someone can help me solve this delema.

std::string.c_str() will return a const char *. Notice very carefully
this
is const. That means that the contents can't be changed through this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char
array
to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];

Why 'size * 2' ??

It is unknown how much the update function is going to change the string.
*2 was a guess at worst case scenario. It may need to be *100, or simply a
fixed limit, unknown without knowing what update is going to do.
You'd need a cast here.

Hmm.. definition I have for strcpy is:
char *strcpy( char *strDestination, const char *strSource );

The only thing I see different is TempString is unsigned where
strDestination is signed. Won't it only give a warning for that?
context.update( TempString, strlen( TempString ) );
...

Why not use a std::vector ?

std::vector<unsigned char> tempV(str.begin(), str.end());
context.update(&tempV[0], tempV.size());

Well, it is presumed that update will change the content (otherwise they can
just use the const_cast) so it's also presumed that the size of the string
will be different. As such, you haven't allocated enough space in your
vector so are going to need another call to allocate more space. Since the
main purpose of using std::vector and std::string over char arrays is
dynamic growth, and because we don't have dynamic growth in the temp object,
might as well just use the char array since we have to allocate the size
anyway. Using std::vector gains us nothing, unless the size is fixed.
 
S

Stefan Naewe

Jim said:
Stefan Naewe said:
Jim said:
Im very much a newbie but perhaps somehone can help me. Ive been
searching for a way to convert a std::string to a unsigned char*

The situation is I have a function that wants a unsigned char* and I
want to give it a std::string

no matching function for call to `MD5::update(std::string&, size_t)'
candidates are: void MD5::update(unsigned char*, unsigned int)

void PrintMD5(string str){
MD5 context;

context.update(str, str.size());
context.finalize();

cout << "MD5: " << context << endl;

return;
}

I hope someone can help me solve this delema.
std::string.c_str() will return a const char *. Notice very carefully
this
is const. That means that the contents can't be changed through this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char
array
to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];
Why 'size * 2' ??

It is unknown how much the update function is going to change the string.
*2 was a guess at worst case scenario. It may need to be *100, or simply a
fixed limit, unknown without knowing what update is going to do.

True.
Who knows without seeing the doc for MD5::update()
Hmm.. definition I have for strcpy is:
char *strcpy( char *strDestination, const char *strSource );

The only thing I see different is TempString is unsigned where
strDestination is signed. Won't it only give a warning for that?

My g++ gives me:

"error: invalid conversion from 'unsigned char*' to 'char*' "
context.update( TempString, strlen( TempString ) );
...
Why not use a std::vector ?

std::vector<unsigned char> tempV(str.begin(), str.end());
context.update(&tempV[0], tempV.size());

Well, it is presumed that update will change the content (otherwise they can
just use the const_cast) so it's also presumed that the size of the string
will be different. As such, you haven't allocated enough space in your
vector so are going to need another call to allocate more space. Since the
main purpose of using std::vector and std::string over char arrays is
dynamic growth, and because we don't have dynamic growth in the temp object,
might as well just use the char array since we have to allocate the size
anyway. Using std::vector gains us nothing, unless the size is fixed.

Even if MD5::update() changed the passed string using, a std::vector would
IMHO be better because:
- no way to forget to delete[]
- no need to cast
- no bad feeling in the neck because std::strings' memory is not guaranteed
to be contiguous (at least not yet IIRC)

/S
 
H

Howard

std::string.c_str() will return a const char *. Notice very carefully
this is const. That means that the contents can't be changed through
this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char array
to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];
strcpy( TempString, str.c_str() );
context.update( TempString, strlen( TempString ) );
...

It's a bad idea to simply "guess" what a function will do with a string, and
how long an array you might need. Such guesses are bound to either 1) fail
miserably at some point, or 2) use up memory needlessly. And nobody's going
to understand why you've chosen to arbitrarily double the size.

I doubt that update() is updating the string. More likely, it's updating
the "context" object. If it _is_ updating the string, then it should be
doing the allocation as well. It's poorly designed if you tell it how much
data it _can_ use, but it decides how much it _needs_ to use. What should
it do if it needs more than you gave it?

-Howard
 
S

sposes

Im still reading the replys and will let you know what hapens soon.

std::string.c_str() will return a const char *. Notice very carefully
this is const. That means that the contents can't be changed through
this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char array
to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];
strcpy( TempString, str.c_str() );
context.update( TempString, strlen( TempString ) );
...

It's a bad idea to simply "guess" what a function will do with a string, and
how long an array you might need. Such guesses are bound to either 1) fail
miserably at some point, or 2) use up memory needlessly. And nobody's going
to understand why you've chosen to arbitrarily double the size.

I doubt that update() is updating the string. More likely, it's updating
the "context" object. If it _is_ updating the string, then it should be
doing the allocation as well. It's poorly designed if you tell it how much
data it _can_ use, but it decides how much it _needs_ to use. What should
it do if it needs more than you gave it?

-Howard
 
J

Jim Langston

Howard said:
std::string.c_str() will return a const char *. Notice very carefully
this is const. That means that the contents can't be changed through
this.

If the
context.update( unsigned char*, unsigned int )
is going to change the contents of the char *, which I highly expect it
will, you can't use this.

My solution in these cases is to actually copy the c_str() to a char
array to copy it back.

unsigned char* TempString = new unsigned char[ str.size() * 2 ];
strcpy( TempString, str.c_str() );
context.update( TempString, strlen( TempString ) );
...

It's a bad idea to simply "guess" what a function will do with a string,
and how long an array you might need. Such guesses are bound to either 1)
fail miserably at some point, or 2) use up memory needlessly. And
nobody's going to understand why you've chosen to arbitrarily double the
size.

I agree. I had planned on explaining why I was using str.size() * 2 instead
of simply str.size() but had forgot. My bad.
I doubt that update() is updating the string. More likely, it's updating
the "context" object. If it _is_ updating the string, then it should be
doing the allocation as well. It's poorly designed if you tell it how
much data it _can_ use, but it decides how much it _needs_ to use. What
should it do if it needs more than you gave it?

I doubt it highly too. Most likely the method is just not const
correctness, and if the OP has the source to the class he should fix it to
be const unsigned char*.

I use a library where I don't have the source (it's a .dll) but only the
interface so can't mess with the signatures by fixing the const correctness
myself and in those cases I use a const_cast because I know for a fact that
the function is not going to change the string.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,824
Latest member
Nater888

Latest Threads

Top