JonaGik
JonaGik

Reputation: 1573

Converting a four character string to a long

I want to convert a four character string (i.e. four characters) into a long (i.e. convert them to ASCII codes and then put them into the long).

As I understand it, this is done by writing the first character to the first byte of the long, the second to the adjacent memory location, and so on. But I don't know how to do this in C++.

Can someone please point me in the right direction?

Thanks in advance.

Upvotes: 3

Views: 2143

Answers (3)

Alexander Drichel
Alexander Drichel

Reputation: 515

#include <string>
#include <iostream>

std::string fourCharCode_toString ( int value )
{
    return std::string( reinterpret_cast<const char*>( &( value ) ), sizeof(int) );
}

int fourCharCode_toInt ( const std::string & value )
{
    return *( reinterpret_cast<const int*>( value.data() ) );
}

int main()
{
    int a = 'DROW';
    std::string str = fourCharCode_toString( a );
    int b = fourCharCode_toInt( str );

    std::cout << str << "\n";
}

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 477700

Here's your set of four characters:

const unsigned char buf[4] = { 'a', '0', '%', 'Q' };

Now we assemble a 32-bit unsigned integer:

const uint32_t n = (buf[0]) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);

Here I assume that buf[0] is the least significant one; if you want to go the other way round, just swap the indices around.

Let's confirm:

printf("n = 0x%08X\n", n); // we get n = 0x51253061
                           //               Q % 0 a

Important: Make sure your original byte buffer is unsigned, or otherwise add explicit casts like (unsigned int)(unsigned char)(buf[i]); otherwise the shift operations are not well defined.


Word of warning: I would strongly prefer this algebraic solution over the possibly tempting const uint32_t n = *(uint32_t*)(buf), which is machine-endianness dependent and will make your compiler angry if you're using strict aliasing assumptions!


As was helpfully pointed out below, you can try and be even more portable by not making assumptions on the bit size of a byte:

const unsigned very long int n = buf[0] |
              (buf[1] << (CHAR_BIT)     |
              (buf[2] << (CHAR_BIT * 2) |
              (buf[3] << (CHAR_BIT * 3)   ;

Feel free to write your own generalizations as needed! (Good luck figuring out the appropriate printf format string ;-) .)

Upvotes: 8

jcoder
jcoder

Reputation: 30055

If your bytes are in the correct order for a long on your machine then use memcpy, something like this -

#include <cstdlib>
#include <iostream>

int main()
{
    char data[] = {'a', 'b', 'c', 'd'};
    long result;

    std::memcpy(&result, data, 4);
    std::cout << result << "\n";
}

Note that this will be platform dependent for byte ordering in the long which may or may not be what you need. And the 4 is hard coded as the size in bytes of the long for simplicty. You would NOT hard code 4 in a real program of course. All the compilers I've tried this on optimize out the memcpy when optimization is enabled so it's likely to be efficient too.

EDIT: Go with the shift and add answer someone else posted unless this meets your specific requirements as it's much more portable and safe!

Upvotes: 1

Related Questions