[Newbie] Once more on conversions

Discussion in 'C++' started by Barzo, Jan 27, 2009.

  1. Barzo

    Barzo Guest

    Hi,

    I'm sorry if my questions are banal...
    I have to this 'simple' work:

    INPUT: std::string buffer = [11][8E][CD][8D] --> <<CONVERSION>> -->
    OUTPUT: std::string = "12,345345"

    The buffer arrives from a device that use big-endian.

    [11][8E][CD][8D] = 294571405

    (294571405 * 90) / 0x80000000 = 12,34534496907....

    My routine is (after have readed some posts here..) but it doen't
    work:

    template< typename T >
    std::string ToString( const T& val )
    {
    try
    {
    return boost::lexical_cast<std::string>(val);
    }
    catch(const boost::bad_lexical_cast& e)
    {
    // std::cout << e.what();
    return 0;
    }
    }

    template<class T>
    void fromBytes(unsigned char const* bytes, T* t)
    {
    *t = 0;
    for(int i = 0; i != sizeof t; ++i)
    *t |= bytes << 8 * i;
    }

    float decode_lat(const std::string& buffer, char token_pos)
    {
    // VAL = ((L * (2^31))/90) => L = ((VAL * 90)/(2^31))
    // (2^31)=0x80000000

    float lat = 0;
    unsigned long val = 0;

    // Extract the 4 latitude octets from the buffer and
    // convert they into an long value
    fromBytes<unsigned long>(reinterpret_cast<const unsigned char*>
    (buffer.substr(token_pos, 4).c_str()), &val);

    if (val == 0x7FFFFFFF)
    lat = 90;
    else
    lat = ((unsigned long)(val * 90) / 0x80000000);

    // The MSBit indicates the sign
    return ( ((buffer[token_pos] & 0x80) == 0x80) ? -lat : lat );
    }

    void CallerFunction()
    {...
    std::string s = ToString<float>( decode_lat(buffer, token_pos) );
    }

    Could someone explain me what is wrong in this code?
    Is this code portable? If not, is there a method to accomplish this?

    Tnx in advance!
    Daniele.
     
    Barzo, Jan 27, 2009
    #1
    1. Advertising

  2. Barzo wrote:
    > Hi,
    >
    > I'm sorry if my questions are banal...
    > I have to this 'simple' work:
    >
    > INPUT: std::string buffer = [11][8E][CD][8D] --> <<CONVERSION>> -->
    > OUTPUT: std::string = "12,345345"
    >
    > The buffer arrives from a device that use big-endian.
    >
    > [11][8E][CD][8D] = 294571405
    >
    > (294571405 * 90) / 0x80000000 = 12,34534496907....
    >
    > My routine is (after have readed some posts here..) but it doen't
    > work:
    >
    > template< typename T >
    > std::string ToString( const T& val )
    > {
    > try
    > {
    > return boost::lexical_cast<std::string>(val);
    > }
    > catch(const boost::bad_lexical_cast& e)
    > {
    > // std::cout << e.what();
    > return 0;


    Here you return a string with NULL as parameter.
    This is a candidate for segfault.

    Perhaps you where thinking of:
    return "0";

    > }
    > }
    >
    > template<class T>
    > void fromBytes(unsigned char const* bytes, T* t)
    > {
    > *t = 0;
    > for(int i = 0; i != sizeof t; ++i)
    > *t |= bytes << 8 * i;
    > }
    >
    > float decode_lat(const std::string& buffer, char token_pos)
    > {
    > // VAL = ((L * (2^31))/90) => L = ((VAL * 90)/(2^31))
    > // (2^31)=0x80000000
    >
    > float lat = 0;
    > unsigned long val = 0;
    >
    > // Extract the 4 latitude octets from the buffer and
    > // convert they into an long value
    > fromBytes<unsigned long>(reinterpret_cast<const unsigned char*>
    > (buffer.substr(token_pos, 4).c_str()), &val);
    >
    > if (val == 0x7FFFFFFF)
    > lat = 90;
    > else
    > lat = ((unsigned long)(val * 90) / 0x80000000);


    perhaps could you consider modifying your expression to:
    lat = unsigned long( val * (90.0/0x80000000) ) );

    It would save you possible overflow.

    >
    > // The MSBit indicates the sign
    > return ( ((buffer[token_pos] & 0x80) == 0x80) ? -lat : lat );
    > }
    >
    > void CallerFunction()
    > {...
    > std::string s = ToString<float>( decode_lat(buffer, token_pos) );
    > }
    >
    > Could someone explain me what is wrong in this code?
    > Is this code portable? If not, is there a method to accomplish this?


    What doesn't work ?

    --
    Michael
     
    Michael DOUBEZ, Jan 27, 2009
    #2
    1. Advertising

  3. Victor Bazarov wrote:
    > Barzo wrote:
    >> I'm sorry if my questions are banal...
    >> I have to this 'simple' work:
    >>
    >> INPUT: std::string buffer = [11][8E][CD][8D] --> <<CONVERSION>> -->
    >> OUTPUT: std::string = "12,345345"
    >>
    >> The buffer arrives from a device that use big-endian.


    Big-endian, so 0x8D goes into bit 7 to bit 0 (with bit 0 = LSB).

    >> [11][8E][CD][8D] = 294571405

    [...]
    >> template<class T>
    >> void fromBytes(unsigned char const* bytes, T* t)
    >> {
    >> *t = 0;
    >> for(int i = 0; i != sizeof t; ++i)
    >> *t |= bytes << 8 * i;
    >> }


    0x8D is read in the 4th loop cycle, so
    *t |= 0x8D << 8 * 3;
    is executed. 0x8D is stored at bit 31 to bit 24.

    Conclusion: This function reads from little-endian and doesn't do what
    you want.

    >> float decode_lat(const std::string& buffer, char token_pos)
    >> {
    >> // VAL = ((L * (2^31))/90) => L = ((VAL * 90)/(2^31))
    >> // (2^31)=0x80000000
    >>
    >> float lat = 0;
    >> unsigned long val = 0;
    >>
    >> // Extract the 4 latitude octets from the buffer and
    >> // convert they into an long value
    >> fromBytes<unsigned long>(reinterpret_cast<const unsigned char*>
    >> (buffer.substr(token_pos, 4).c_str()), &val);


    The explicit template argument is not needed, since the type is deduced
    from the second parameter.
    The substr() call constructs a temporary string and is also not needed.

    fromBytes(reinterpret_cast<const unsigned char*>(buffer.c_str() +
    token_pos, &val);

    However, you should check if buffer is large enough.

    [...]
    >> // The MSBit indicates the sign
    >> return ( ((buffer[token_pos] & 0x80) == 0x80) ? -lat : lat );


    You might have to set the sign bit to 0 in val before the conversion:

    float lat = (val & 0x7FFFFFFF) * (90.0 / 1<<31);

    Then negate lat if the sign bit is set.

    --
    Thomas
     
    Thomas J. Gritzan, Jan 27, 2009
    #3
    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. Michael
    Replies:
    4
    Views:
    465
    Matt Hammond
    Jun 26, 2006
  2. Replies:
    10
    Views:
    720
    Jasen Betts
    Aug 5, 2005
  3. d3x0xr
    Replies:
    0
    Views:
    307
    d3x0xr
    Nov 30, 2006
  4. keith
    Replies:
    0
    Views:
    144
    keith
    Nov 5, 2004
  5. Gancy
    Replies:
    4
    Views:
    240
    Rasto Levrinc
    Feb 3, 2005
Loading...

Share This Page