Solved

Convert input string in Little-endian

Posted on 2001-07-05
19
823 Views
Last Modified: 2010-08-05
Hello,
  I need to convert a string value to 4-byte BCD representation, in little-endian format.  How do I do that?
0
Comment
Question by:fareezaa
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
  • 3
  • +1
19 Comments
 
LVL 6

Expert Comment

by:zebada
ID: 6258313
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
 
LVL 22

Expert Comment

by:nietod
ID: 6259200
>> 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
 
LVL 6

Expert Comment

by:zebada
ID: 6260771
neitod, huh?
Isn't little endian the LSB first?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:nietod
ID: 6260882
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
 
LVL 6

Expert Comment

by:zebada
ID: 6261037
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 Comment

by:fareezaa
ID: 6261144
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;

printf("\n\nPlease enter your PIN to log in or 'q' to quit:\n");
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 Comment

by:fareezaa
ID: 6261147
and i forgot to include that the char *c, *s needs to be as unsigned char s[].
0
 
LVL 22

Expert Comment

by:nietod
ID: 6261509
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.

Instead use C++ i/O like


char c[100];

cin >> c;


Or better yet, use string objects like

string c;

cin >> string.
0
 

Author Comment

by:fareezaa
ID: 6262115
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];

printf("\n\nPlease enter your PIN to log in or 'q' to quit:\n");
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
 
LVL 84

Expert Comment

by:ozo
ID: 6262129
for ( s=c+strlen(c)-1 ; c<=s ; s-=2 ) {  
    *b = (*s-'0') << 4;
     if ( c<s )
    *b |= (*(s-1)-'0');
     b++;
}
0
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
ID: 6262249
>> 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 Comment

by:fareezaa
ID: 6263902
how to i print out the return value of Hex2Bin(uByt h) function?

i did this:
char c[30];
     
printf("\n\nPlease enter your PIN to log in or 'q' to quit:\n");
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
 
LVL 22

Expert Comment

by:nietod
ID: 6264543
>> 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 Comment

by:fareezaa
ID: 6267493
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
 
LVL 22

Expert Comment

by:nietod
ID: 6267508
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 Comment

by:fareezaa
ID: 6268003
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
 
LVL 22

Expert Comment

by:nietod
ID: 6268547
>>  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 Comment

by:fareezaa
ID: 6275389
THANKS.  i think it shud be b+, not b
0
 
LVL 22

Expert Comment

by:nietod
ID: 6276616
You could have rounded it up to an A.  :-)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question