x
• Status: Solved
• Priority: Medium
• Security: Public
• Views: 920

# Convert input string in Little-endian

Hello,
I need to convert a string value to 4-byte BCD representation, in little-endian format.  How do I do that?
0
fareezaa
• 8
• 7
• 3
• +1
1 Solution

Commented:
Not sure how you mean to encode BCD as "little endian"
My guess is you want to see the string 12345678
stored as HEX: 87 65 43 21

This code should do that for you

#include <stdio.h>
#include <string.h>

typedef unsigned char BYTE;

int main(int argc, char *argv[])
{
char *c,*s = "45678";
BYTE *b,bcd[4];
int i;

for ( b=bcd,i=0 ; i<4 ; i++ )
*b++ = 0;
b = bcd;
for ( c=s+strlen(s)-1 ; s<=c ; c-=2 ) {
*b = (*c-'0') << 4;
if ( s<c )
*b |= (*(c-1)-'0');
b++;
}

for ( i=0 ; i<4 ; i++ )
printf("%2.2x,",bcd[i]);
}
0

Commented:
>> My guess is you want to see the string 12345678
>> stored as HEX: 87 65 43 21
That is big endian.
87 65 43 21

is little endian.

You can just reverse the final product.
0

Commented:
neitod, huh?
Isn't little endian the LSB first?
0

Commented:
Opps, I didn't reverse it!

Little endian means that the little part, the least significant part, appears at the end, at the highest address.  So a number like

12345678

would be stored as 4 bytes from low to high addresses that contain

0x12 0x34 0x56 0x78

0

Commented:
bummer!!!!

I guess that's why I always refer to "MSB first" or "LSB first". Never knew what "endian" meant - from your explanation I guess it means "end".
0

Author Commented:
ok.
but i need to prompt the user for the value.  From the example you showed, both pointers value has been been initialized with values.  Using that it works, but when i modify the code to get user input,  It gives me error.  This is the snippet of the code:
--
char *c, *s;
BYTE *b,bcd[4];
int i=0;

scanf("%s", &c);
printf("%s",&c);
--

how can i copy these value to s as well? or get this code to be working?
0

Author Commented:
and i forgot to include that the char *c, *s needs to be as unsigned char s[].
0

Commented:
You are using scanf() incorrecly.  When you read a string wiht scanf() you need to pass a pointer to an array of characters that will receive the result. Like

char c[100]; // Array to store a string of up to 99 characters.

scanf("%s", c);

However, it is a bad idea to be using C I/O in C++ programs.  As you can tell, it is easy to use it correctly adn make mistakes that cause crashes or other problems.

char c[100];

cin >> c;

Or better yet, use string objects like

string c;

cin >> string.
0

Author Commented:
Hello,
when i do it that way, i still get errors. the errors are:
1. error C2440: '=' : cannot convert from 'char *' to 'char [30]'.  There are no conversions to array types, although there are conversions to references or pointers to arrays
2. error C2106: '-=' : left operand must be l-value.

the code:

int main(int argc, char *argv[])
{
char *s ;
BYTE *b,bcd[4];
int i=0;
char c[30];

cin>>c;
s = c;  //i need to copy value of c to s

for ( b=bcd,i=0 ; i<4 ; i++ )
*b++ = 0;
b = bcd;
for ( c=s+strlen(s)-1 ; s<=c ; c-=2 ) {                        <- error 1 and 2
*b = (*c-'0') << 4;
if ( s<c )
*b |= (*(c-1)-'0');
b++;
}

for ( i=0 ; i<4 ; i++ )
printf("%2.2x ",bcd[i]);
}
0

Commented:
for ( s=c+strlen(c)-1 ; c<=s ; s-=2 ) {
*b = (*s-'0') << 4;
if ( c<s )
*b |= (*(s-1)-'0');
b++;
}
0

Commented:
>> 1. error C2440: '=' : cannot convert from 'char *' to 'char [30]'.  There are
>> no conversions to array types, although there are conversions to references
>> or pointers to arrays
You cannot copy NUl terminated strings with =.   You must use strcpy() or you must use a C++ string object that supports operator =.   (using string objects is definitely prefered!)

>> 2. error C2106: '-=' : left operand must be l-value.
You are trying to subtract 2 from "c".  That worked when c was a pointer.  It made "c" point to the character that was 2 characters before where it was pointing before.   But you made "C" into an array.  You can't do that with an array.

Here is the code that I use to pach data.  Note that it handles hexx values too (values outside of the digit range (0-9))  So for example  "AB"  is packed to a byte that stores OxAB.  Note also that if the number of source bytes is odd, the high nibble of the result is made 0.  so "123" is packed to 0x01,0x23

typedef unsigned char uByt;

// TITLE:  Convert ASCII Hex Digit to Binary                                                      //
//      This procedure converts a byte containing an ASCII character representing a Hex digit to  //
// the binary value it represents.                                                                //
uByt
Hex2Bin(uByt h)
{
if ('0' <= h && h <= '9')                     // If this is a decimal digit, then              //
return ((uByt)(h-'0'));                    // convert to binary.                            //
else if ('a' <= h && h <= 'f')                // If this is a lowercase hex digit letter,      //
return ((uByt)(h-'a'+10));                 // convert to binary.                            //
else if ('A' <= h && h <= 'F')                // If this is a uppercase hex digit letter,      //
return ((uByt)(h-'A'+10));                 // convert to binary.                            //
return 0;
}
// TITLE:  Pack ASCII Data                                                                        //
//      This procedure packs an array of ASCII characters to an array of packed bytes.  That is,  //
// the value in each byte of the source array is packed into a nibble of a byte in the            //
// destination array.  Since each pair of bytes in the source array is packed into one byte of    //
// the destination, the destination array must only be half the length of the source array.       //
// Hence the term packing.  Thus, the 4 byte array "1234" would be converted to the 2 byte array  //
// 0x12,0x34.                                                                                     //
//                                                                                                //
//      Each of the bytes in the source array must contain an ASCII digit ("0"-"9") or an         //
// uppercase or lowercase letter from "A" to "F".                                                 //
//                                                                                                //
//      The length specified is the number of unpacked bytes to be packed.  If this value is      //
// even, then the number of bytes in the destination array must be half of this value and each    //
// nibble in the destination will be packed from a byte in the source.  If this value is odd, the //
// destination array must be half this value rounded up and the high nibble of the first byte     //
// will be set to zero and the low nibble will be set from the first byte of the source.  Thus    //
// packing the 3 byte array "678" into a 2 byte array would yield 0x06,0x78.                      //
void
QMthPckASC(void       *Dst,                      // -> destination buffer.  Must be at least half //
// the number of bytes (rounded up) specified by //
// the Cnt parameter.                            //
const void *Src,                      // -> source buffer.  Must be at least the size  //
// specified by the Cnt parameter.               //
size_t      Cnt)                      // Number of unpacked bytes to pack.  If odd the //
// high nibble of the first byte will be zeroed. //
// May be zero.                                  //
{
uByt *D = (uByt *) Dst;                       // -> destination bytes.                         //
uByt *S = (uByt *) Src;                       // -> source bytes.                              //
uByt  u;                                      // Generic value.                                //
uByt  v;                                      // Generic value.                                //

if (Cnt & 1)                                  // If count is odd, then                         //
{
u = *S++;                                  // Get source byte.                              //
*D++ = Hex2Bin(u);                         // Set low nibble of destination byte.           //
--Cnt;                                     // Decrement the count.                          //
}
while (Cnt)                                   // While there are more destination bytes.       //
{
u = *S++;                                  // Get source byte.                              //
v = *S++;                                  // Get source byte.                              //
*D++ =  (uByt)(Hex2Bin(u) << 4) | Hex2Bin(v); // Set destination byte.                      //
Cnt -= 2;                                  // Decrement the count.                          //
}
}
0

Author Commented:
how to i print out the return value of Hex2Bin(uByt h) function?

i did this:
char c[30];

cin >> c;

printf("\nthe result is: \"%s\"\n", c);
s = c;
cout<<"\ns value: "<<s;

BYTE x = Hex2Bin(*c);
cout<<"\nx value: "<<x;
--
and i get weird output..a symbol of a smiling face.

0

Commented:
>> and i get weird output..a symbol of a smiling face.
That would be very likely.  Its a byte containing a packed BCD value.  its not necessarily going to be a valid ASCII character.

You can convert it to a number (int) then print the int.

cout << (int) Hex2Bin(*c);
0

Author Commented:
hello,
when i convert [the cout << (int) Hex2Bin(*c)],the answer is 1.  that is not what i am looking for.
When the user input :12345678,
the answer shud be {{0x87}, {0x65}, {0x43}, {0x21}}; but i don't know how to get this.
I've tried zebada's way but it's the other way around (87 65 43 21) and it is not working.
:(
0

Commented:
hex2Bin is not meant to do that conversion.  Read the comments about it It converts a single ASCII digit/letter to a  byte that contains the binary value represened by the ASCII value.  I.e. it converts the digit "1" to binary 1.  It converts "A" to binary 10 (0xA)  it converts "b" to 11 and so on.

The procedure is used by QMthPckASC()  That procedure  packs one string of ASCII digits/letters to a string of binary BCD bytes.

Read the commens on it.  it explains what it does and what each parameter is.
0

Author Commented:
when i use that way, it will return me 0x87 0x65 0x43 0x21.  the expected result is 0x78 0x56 0x34 0x12.   so i change some of the code and it works. But what if the input is odd, say 12345.  Should it be
a-(0x54 0x32 0x01)
or
b- (0x05 0x43 0x21)?
0

Commented:
>>  it will return me 0x87 0x65 0x43 0x21
If you feed it a string that is (from low to high address) "12345678" it will return to you a string that is (from low to high)
0x12, 0x34, ix56, 0x78.

>> Should it be
What do you want?  It should be what you need according to your needs.
0

Author Commented:
THANKS.  i think it shud be b+, not b
0

Commented:
You could have rounded it up to an A.  :-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.