Thread: No atoh() function in C ( Ascii To Hex )? - Well, Let's Create One

  1. #1
    Registered User
    Join Date
    Mar 2006
    Location
    dedham, MA
    Posts
    10

    No atoh() function in C ( Ascii To Hex )? - Well, Let's Create One

    Hi, I'm new to the board and appreciate any input anyone has reguarding this problem of which I've been wrestling of late.

    My goal is to have the user enter a Hex depicted input ( ie. "ff0077554433" ) which of course gets interpreted as ascii characters, and then convert the hex depicted ascii characters to actual hex values. Therefore, upon the user entering "ff00775533", after the conversion over to hex, I'd should have a character string in my program that contains the following values:

    UserInput[0]=0xff
    UserInput[1]=0x00
    UserInput[2]=0x77
    UserInput[3]=0x55
    UserInput[4]=0x44
    UserInput[5]=0x33

    One may so, "Oh, well that's easy!".

    However, after reading various C references as well as searching over the Internet to find code that does this, the only code that I've found so far that works is as follows:

    Code:
    unsigned long int UserInput = 0;
    
    int main()
    {
    
       /* Get user HEX input */
      Printf ( "Please enter hex value\n");
      scanf("%x", &UserInput ); 
      
      /* User then input's something like "ff008877" */
      printf("The converted hex text decimal value is now %d", 
                 UserInput );
    
      return 0;
    
    }
    Resulting output from this program:

    Code:
    The converted hex text decimal value is now 4278225015


    And so this works fine. The conversion is made from the ascii hex input to actual hex values as confirmed by the decimal output.

    However, the problem here is that the user is limited to an input of only 4 HEX BYTES.

    I REALLY WISH there were a function that took an input such as:

    ff008877663344 - ( Ascii Input of course )

    and returned a string with each byte containing the following values:

    OutPutString[0] = 0xff
    OutPutString[1] = 0x00
    OutPutString[2] = 0x88
    OutPutString[3] = 0x77
    OutPutString[4] = 0x66
    OutPutString[5] = 0x33
    OutPutString[6] = 0x44


    Such a function would logically be called atoh ( Ascii to Hex ) and have the following signature:

    Code:
     int atoh(char*, char*)
    where the first arg is the string of ascii chars depicting the hex value and the second arg being a buffer of bytes that containes the actual hex values depicted in the user input - BUT THE PROBLEM IS, AS FAR AS I'VE RESEARCHED, SUCH A FUNCTION DOESN'T EXIST in C .

    Therefore, in trying to create my own version of atoh( char*, char* ) I've written the following program. Please note that for now, instead of implementing this code inside of a function called int atoh(char *, char* ), for testing purposes, the code is contained in a main() program for now.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    union IntCharUnion
    {
    
       unsigned long int UserInputInt;
        char UserInputChar[4];
    };
    
    int main()
    {
    
       /* Union Containing an integer and char of 4 bytes */
       IntCharUnion IntCharVar;
    
       /* Used to reference each element of user input */
       int InputIndex = 0;
    
       /* String that captures user input of up to 12 chars. Could
        make it larger, but let's keep it simple for now. */
       char UserInput[12] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
    
       /* The resulting string containing the Converted Ascii --->
          Hex Chars. */
       char OutputBuffOfHex[7];
    
       /* Used to temporarily store 4 hex values that ultimately get
          appended to the output string */
       char PreConversionBuff[4];
    
       printf ( "Please enter hex value\n");
       scanf("%s", UserInput );
    
       /* At this point, user then input's something like "ff008877554422" */
    
       /* Set up loops that peform the conversion to actual hex */
       while( UserInput[InputIndex] != '0' )
       {
    
           /* Every 4 bytes, convert the latest 4 bytes from ascii to hex via.
              the %x specifier. We can only do this 4 bytes at a time using the
              %x specifier. */
           if( ( InputIndex != 0) && ( ( InputIndex % 4 ) == 0 ) )
           {
              /* Perform the conversion for this grouping of 4 bytes */
              sscanf( PreConversionBuff, "%x",
                      &IntCharVar.UserInputInt );
    
              /* And Now, append the new Hex values inside of the Union
                 to the output string */
              strcat( OutputBuffOfHex, IntCharVar.UserInputChar);
    
              InputIndex++;
    
           }
           /* Else, transfer this byte to the buffer. */
           else
           {
              PreConversionBuff[InputIndex] = UserInput[InputIndex];
              InputIndex++;
           }
           /* end if */
    
       }/* end while */
    
       printf("\nThe value of the OutputBuffOfHex is %x\n", OutputBuffOfHex );
    }

    Program output:

    Code:
    Please enter hex value
    1122
    
    The value of the OutputBuffOfHex is ffbef301


    After investingating this closely, the problem appears to be in using the union.
    That is, after the following line of code gets executed:

    Code:
    /* Perform the conversion for this grouping of 4 bytes */
              sscanf( PreConversionBuff, "%x",
                      &IntCharVar.UserInputInt );
    IntCharVar.UserInputInt DOES CONTAIN the proper value. But, when examining IntCharVar.UserInputChar, the value stored in there is completely different.


    So, then, I wrote a smaller program to see how I could get the union to work the way I wanted.
    The program is as follows:


    Code:
    union IntCharUnion
    {
        unsigned long int UserInputInt;
        char UserInputChar[4];
    };
    
    int main()
    {
    
        IntCharUnion IntCharVar;
    
        Printf ( "Please enter hex value\n");
        scanf("%x", &IntToStringOfHex.UserInputInt );
    
        /* User then input's something like "ff008877" */
        
    
        /* Then, just as a sanity check, print out what's in the Char 
            String portion of the UnionVar */
       printf( "Hex values now stored in the char string portion of
                   the Union are as follows: %x", IntToStringOfHex.
                   UserInputChar ); 
    
       return 0;
    }
    Output of this program:

    Code:
    Please enter hex value
    ff008877
    
    Hex values now stored in the char string portion of the Union are
    as follows: ffbef316


    Of course the desired result is:

    Code:
    Hex values now stored in the char string portion of the Union are
    as follows: ff008877
    Then, I got desperate and decided to completely ditch the whole Union idea. You see, all I'm trying to do is to get the frigin' 4 bytes stored in the integer transferred over to a 4 byte character string. So I then wrote the following simple program to once again attempt to transfer what's stored in the 4 byte integer var over to a 4 byte character string:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    
       char UserInput[10];
       char DestinationBuffer[4];
       int intBuff = 0;
    
       DestinationBuffer[0] = 0;
       DestinationBuffer[1] = 0;
       DestinationBuffer[2] = 0;
       DestinationBuffer[3] = 0;
    
       /* Get the entire ascii hex digit input and store into a char array */
       printf("Please enter the the hex packet of data\n", UserInput );
       scanf("%s", UserInput );
    
       /* Convert the ascii input to Hex via. the "%x" specifier */
       sscanf(UserInput, "%x", &intBuff );
       printf ("The int value is now %d\n", intBuff);
    
       /* And finally, move the 4 byte hex value from the integer to
           the desired output string. */
       memmove( DestinationBuffer, &intBuff, 4);
       printf("%x\n", DestinationBuffer );
    
       return 0;
    
    }

    Program output:

    Code:
    Please enter the the hex packet of data
    1122
    The int value is now 4386
    ffbef316


    Again, the conversion from ascii hex depicted input to hex actual hex worked:

    Code:
    /* Convert the ascii input to Hex via. the "%x" specifier */
       sscanf(UserInput, "%x", &intBuff );
       printf ("The int value is now %d\n", intBuff);
    But, the next line of code that attempts to move what's now inside of the 4 byte integer over to the 4 byte array of characters still fails at this line of code:

    Code:
    * And finally, move the 4 byte hex value from the integer to
           the desired output string. */
       memmove( DestinationBuffer, &intBuff, 4);
       printf("%x\n", DestinationBuffer );
    Any ideas on what I'm doing wrong here - in trying to transfer the 4 bytes in the integer over to the 4 byte character string? Or more importantly, does anyone have any better ideas on converting ascii ( hex depicted chars ) input over to the actual hex values depicted - period?

    Thanks in advance,
    dedham_ma_man
    Last edited by dedham_ma_man; 03-18-2006 at 12:58 PM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    All you really need is to convert each 2 characters entered into a single character, and to display each character in your new array as its decimal value. You can't treat the second array as a string, in case they enter 00.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Like this?
    Code:
    #include <stdio.h>
    
    int main ( ) {
      char buffer[] = "ff008877554422\n";
      int res, pos = 0;
      unsigned int byte;
      printf( "Scanning %s", buffer );
      while ( (res=sscanf( &buffer[pos], "%2x", &byte )) == 1 ) {
        printf( "res=%d, byte=%d(%02x)\n", res, byte, byte );
        pos += 2;
      }
      return 0;
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Sorry, long post, I only skimmed after a bit.
    Quote Originally Posted by dedham_ma_man
    However, the problem here is that the user is limited to an input of only 4 HEX BYTES.

    I REALLY WISH there were a function that took an input such as:

    ff008877663344 - ( Ascii Input of course )

    and returned a string with each byte containing the following values:

    OutPutString[0] = 0xff
    OutPutString[1] = 0x00
    OutPutString[2] = 0x88
    OutPutString[3] = 0x77
    OutPutString[4] = 0x66
    OutPutString[5] = 0x33
    OutPutString[6] = 0x44
    Wouldn't simply limiting the input size for *scanf do what you want?
    Code:
    #include <stdio.h>
    #include <stdint.h>
    #include <inttypes.h>
    
    int main( void )
    {
       char input[] = "ff008877663344", *ptr = input;
       unsigned int byte;
       unsigned char array[8];
       size_t i, j;
       for ( i = 0; i < sizeof array; ++i )
       {
          if ( sscanf(ptr, "%2x", &byte) != 1 )
          {
             break;
          }
          array[i] = byte;
          ptr += 2;
       }
       for ( j = i, i = 0; i < j; ++i )
       {
          printf("array[%lu] = %02X\n", (long unsigned)i, (unsigned)array[i]);
       }
       return 0;
    }
    
    /* my output
    array[0] = FF
    array[1] = 00
    array[2] = 88
    array[3] = 77
    array[4] = 66
    array[5] = 33
    array[6] = 44
    */
    Last edited by Dave_Sinkula; 03-18-2006 at 01:29 PM. Reason: D'oh! Pokey again. :(
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I can't argue that this is simpler than what's already been suggested, but it's probably faster with larger strings:

    Code:
    char *
    atohx(char * dst, const char * src)
    {	
    	char 
    		* ret = dst;
    	for(int lsb, msb; *src; src += 2)
    	{	
    		msb = tolower(*src);
    		lsb = tolower(*(src + 1));
    		msb -= isdigit(msb) ? 0x30 : 0x57;
    		lsb -= isdigit(lsb) ? 0x30 : 0x57;
    		if((msb < 0x0 || msb > 0xf) || (lsb < 0x0 || lsb > 0xf))
    		{
    			*ret = 0;
    			return NULL;
    		}
    		*dst++ = (char)(lsb | (msb << 4));  
    	}
    	*dst = 0;
    	return ret;
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Mar 2006
    Location
    dedham, MA
    Posts
    10
    Thanks all - this has helped tremendously - ie. converting from Ascii depicted Hex to char string.

    As mentioned in the second part of this long post of mine, how would one go from a 4byte char string back to an int.

    In other words, if I have:

    CharString[0] = 0x00
    CharString[1] = 0x88
    CharString[2] = 0x00
    CharString[3] = 0x00

    and want to move those 4 bytes into an Integer, how would I do that?

    Among other things, I've tried the following:

    Code:
    char BitBuffer[4] = { 0x00, 0x88, 0x00, 0x00 };
       int IntBits = 0;
       unsigned int byte = 0;
    
       //printf( "The value of BitBuffer is %2x\n", BitBuffer[1]);
    
       sscanf(BitBuffer, "%d", &IntBits );
    
       printf("\nThe integer value of IntBits is %d\n", IntBits );
    output of this program:

    Code:
    The integer value of IntBits is 0
    Any other ideas? Thanks again.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Is this the output you expect?
    Code:
    #include <stdio.h>
    
    int main( void )
    {
       char BitBuffer[4] = { 0x00, 0x88, 0x00, 0x00 };
       int IntBits = *(int*)BitBuffer;
       printf("The integer value of IntBits is %d\n", IntBits );   
       return 0;
    }
    
    /* my output
    The integer value of IntBits is 34816
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Registered User
    Join Date
    Mar 2006
    Location
    dedham, MA
    Posts
    10
    Beautiful, thank you.

  9. #9
    Registered User
    Join Date
    Mar 2006
    Location
    dedham, MA
    Posts
    10
    Quote Originally Posted by Dave_Sinkula
    Is this the output you expect?
    Code:
    #include <stdio.h>
    
    int main( void )
    {
       char BitBuffer[4] = { 0x00, 0x88, 0x00, 0x00 };
       int IntBits = *(int*)BitBuffer;
       printf("The integer value of IntBits is %d\n", IntBits );   
       return 0;
    }
    
    /* my output
    The integer value of IntBits is 34816
    */
    Ok, so when I initiate BitBuffer to { 0x99, 0x88, 0x77, 0x00 } instead of { 0x00, 0x88, 0x00, 0x00 } in the above example, my output is now -1719109888.

    So, I've tried the following:

    Code:
    char BitBuffer[4] = { 0x99, 0x88, 0x77, 0x00 };
      unsigned int IntBits = *(unsigned int*)BitBuffer;
       printf("The integer value of IntBits is %d\n", IntBits );   
       return 0;
    I still get the signed output -1719109888

    So, I became desperate, I've tried this:

    Code:
    char BitBuffer[4] = { 0x99, 0x88, 0x77, 0x00 };
      unsigned long int IntBits = *(unsigned long int*)BitBuffer;
       printf("The integer value of IntBits is %d\n", IntBits );   
       return 0;
    I still get the signed output -1719109888.

    The output should be 10061943

    Any ideas what I'm missing?
    Thanks again

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    How about
    Code:
     char BitBuffer[4] = { 0x00, 0x99, 0x88, 0x77 };
    Also, use %lu, not %d for printing unsigned longs.

    Also, casting in this way is likely to get you a bus error on some machines, if the alignment doesn't match.
    memcpy( &IntBits, BitBuffer, sizeof IntBits );
    is a much safer way
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Mar 2006
    Location
    dedham, MA
    Posts
    10
    Quote Originally Posted by Salem
    How about
    Code:
     char BitBuffer[4] = { 0x00, 0x99, 0x88, 0x77 };
    Also, use %lu, not %d for printing unsigned longs.

    Also, casting in this way is likely to get you a bus error on some machines, if the alignment doesn't match.
    memcpy( &IntBits, BitBuffer, sizeof IntBits );
    is a much safer way
    OK Thank you.
    Last edited by dedham_ma_man; 03-24-2006 at 11:32 AM.

  12. #12
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Another option that could do what you want:
    Code:
    union 
    {
        unsigned int ival;
        unsigned char bval[4];
    } un;
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Troubleshooting Input Function
    By SiliconHobo in forum C Programming
    Replies: 14
    Last Post: 12-05-2007, 07:18 AM
  2. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  3. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 06:44 PM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. Replies: 4
    Last Post: 11-07-2001, 02:46 PM