Convert from std::string to unsigned char*

Discussion in 'C++' started by sposes@gmail.com, Aug 21, 2006.

  1. Guest

    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.
     
    , Aug 21, 2006
    #1
    1. Advertising

  2. Phlip Guest

    sposes wrote:

    > 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!

    --
    Phlip
    http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
     
    Phlip, Aug 21, 2006
    #2
    1. Advertising

  3. Ian Collins Guest

    Phlip wrote:
    > sposes wrote:
    >
    >
    >> context.update(str, str.size());

    >
    >
    > 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....

    --
    Ian Collins.
     
    Ian Collins, Aug 21, 2006
    #3
  4. Jim Langston Guest

    <> wrote in message
    news:...
    > 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.
     
    Jim Langston, Aug 21, 2006
    #4
  5. Stefan Naewe Guest

    Jim Langston schrieb:
    > <> wrote in message
    > news:...
    >> 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
    --
    Stefan Naewe
    stefan_DOT_naewe_AT_atlas_DOT_de
     
    Stefan Naewe, Aug 21, 2006
    #5
  6. Jim Langston Guest

    "Stefan Naewe" <> wrote in message
    news:...
    > Jim Langston schrieb:
    >> <> wrote in message
    >> news:...
    >>> 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.

    >> strcpy( TempString, str.c_str() );

    >
    > 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.

    >> 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.
     
    Jim Langston, Aug 21, 2006
    #6
  7. Stefan Naewe Guest

    Jim Langston schrieb:
    > "Stefan Naewe" <> wrote in message
    > news:...
    >> Jim Langston schrieb:
    >>> <> wrote in message
    >>> news:...
    >>>> 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()

    >>> strcpy( TempString, str.c_str() );

    >> 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?


    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
    --
    Stefan Naewe
    stefan_DOT_naewe_AT_atlas_DOT_de
     
    Stefan Naewe, Aug 21, 2006
    #7
  8. Howard Guest

    "Jim Langston" <> wrote in message
    news:7EaGg.427$...

    > 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
     
    Howard, Aug 21, 2006
    #8
  9. Guest

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


    Howard wrote:
    > "Jim Langston" <> wrote in message
    > news:7EaGg.427$...
    >
    > > 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
     
    , Aug 21, 2006
    #9
  10. Default User Guest

    wrote:

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



    Please don't top-post. Your replies belong following or interspersed
    with properly trimmed quotes. See the majority of other posts in the
    newsgroup, or the group FAQ list:
    <http://www.parashift.com/c++-faq-lite/how-to-post.html>



    Brian
     
    Default User, Aug 21, 2006
    #10
  11. Jim Langston Guest

    "Howard" <> wrote in message
    news:kVmGg.281531$...
    >
    > "Jim Langston" <> wrote in message
    > news:7EaGg.427$...
    >
    >> 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.
     
    Jim Langston, Aug 21, 2006
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steffen Fiksdal

    void*, char*, unsigned char*, signed char*

    Steffen Fiksdal, May 8, 2005, in forum: C Programming
    Replies:
    1
    Views:
    625
    Jack Klein
    May 9, 2005
  2. Jeffrey Walton
    Replies:
    10
    Views:
    975
    Mathias Gaunard
    Nov 26, 2006
  3. Replies:
    3
    Views:
    8,890
  4. Ioannis Vranos
    Replies:
    11
    Views:
    789
    Ioannis Vranos
    Mar 28, 2008
  5. Alex Vinokur
    Replies:
    9
    Views:
    833
    James Kanze
    Oct 13, 2008
Loading...

Share This Page