Thread: converting a hex value into a string

  1. #1
    Embedded in C...
    Join Date
    Sep 2008
    Location
    Basingstoke, Hampshire
    Posts
    83

    converting a hex value into a string

    Hi,

    In a section of my code I have a number in hex (in the range 0x00 to 0xFE) and I need to get this into an ASCII string. Also, because I don't have printf (or its variations) I can't use snprintf.

    Could anyone give me a tip or example to get me going?

    Thanks
    Dave

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by droseman View Post
    Could anyone give me a tip or example to get me going?
    This is going to be difficult because their are no "hexadecimal numbers" in C. If you mean this:
    Code:
    int num = 0x42;
    Which the value of this in decimal is 66, but in any case the number is stored in binary, (1000010).

    Without printf (which is quite a weird situation), you will need to do something like:

    num/16 = 4
    num%16 = 2

    To get a value for each column, and if that value is more than 9 assign the appropriate letter.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Embedded in C...
    Join Date
    Sep 2008
    Location
    Basingstoke, Hampshire
    Posts
    83
    that makes a bit of sense, but why modulo division for the lower nibble?

    Without printf (which is quite a weird situation)
    On microcontrollers, functions like printf are not included in the library since they are too resource hungry. Makes a difference when your whole application needs to fit into 16 or 32k...

    Could there be a method using bitwise functions?

    --dave

  4. #4
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    One simple way to do this is to create an array, fill in that array backwards with your string (that'd be "print" it to the buffer as 24x0), then reverse it. You'll use the same code that MK27 shows to do that math portion.

    BTW, to get the your "numbers" for Hex, you'll need an if else statement that will get you (0 >= num <= 9) num + '0' (zero), (num >= 9) num % 10 + 'A'
    Last edited by Kennedy; 11-11-2009 at 09:09 AM.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Thumbs up

    Quote Originally Posted by droseman View Post
    that makes a bit of sense, but why modulo division for the lower nibble?
    Well, doesn't that make sense? C division rounds down to whole numbers, which is appropriate here, and then the remainder would be the next order of magnitude down. Anyway, try a few numbers, it does work.

    On microcontrollers, functions like printf are not included in the library since they are too resource hungry. Makes a difference when your whole application needs to fit into 16 or 32k...
    Could there be a method using bitwise functions?
    Neat, I've never done embedded stuff. So you want to optimize this as much as possible processor wise too.

    Vis, bitwise, well, if you shift right 4, that is the same as /16. For the less significant column, you want to mask out everything BUT the last four bits:

    Code:
    #include <stdio.h> 
    
    int main() {
            const unsigned int x = sizeof(int)*8-4;
    	unsigned int n = 66, one = n>>4, 
    		tmp = n<<x, two = tmp>>x;
    	
            printf("%u %u\n", one,two);
    
    	return 0;
    }
    You only have two columns to deal with, so that's it (I tried this on a few numbers, it works). I suppose this will be less expense than the division and modulus.

    No matter what, you are still going to need a small table mechanism to map 10-16 to a-f.
    Last edited by MK27; 11-11-2009 at 09:22 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    >> No matter what, you are still going to need a small table mechanism to map 10-16 to a-f.

    Nah, just the simple if else above.
    Code:
    void num2hexstr(int num, char *buf)
    {
            char tmp[8]; // assuming a 32-bit int.
            int i, j;
    
            for (i = 0; i < 8; i++){
                    j = num & 0xf;
                    if (j < 10){
                            tmp[i] = '0' + j;
                    } else {
                            j -= 10;
                            tmp[i] = 'A' + j;
                    }
                    num >>= 4;
            }
            buf[0] = '0';
            buf[1] = 'x';
            for (i = 2, j = 7; i < 11; i++, j--){
                    buf[i] = tmp[j];
            }
            buf[i] = '\0';
    }
    Now, I just hurried through this, but this should do what you are attempting.

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Kennedy View Post
    >> No matter what, you are still going to need a small table mechanism to map 10-16 to a-f.

    Nah, just the simple if else above.
    Not to whine, but that is what I meant by "small table mechanism".
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    Quote Originally Posted by MK27 View Post
    Not to whine, but that is what I meant by "small table mechanism".
    Sorry, I think of table as in
    Code:
    char[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    Which is just as valid, and could be quicker than generating it on the fly. One just uses ~16 bytes of data while the other does some math operations.

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Kennedy View Post
    Sorry, I think of table as in
    Yeah, you're right, I guess "table" does have a specific technical meaning. I kind of meant the "concept" of a table like you would draw on paper kind-of-thing...which looks like an actual table array might be the most efficient way, as you point out.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    See this post for a thorough example of converting hex to printable.

    dump array into file in "hex format"
    Mainframe assembler programmer by trade. C coder when I can.

  11. #11
    Embedded in C...
    Join Date
    Sep 2008
    Location
    Basingstoke, Hampshire
    Posts
    83
    thanks to kennedy and mk for your ideas. Both would work for me. In your opinion, which of these approaches is likely to have a smaller code footprint?

    I went to put this in a test program, but my printf statements have no results. It seems like I have passed my references correctly, could anyone see what I may have missed?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void num2hexstr(int, char *);
    
    int main(void)
    {
        char buffer[3];
        char* buffer_ptr = &buffer[0];
        int number = 31;
        
        num2hexstr(number, buffer_ptr);
        
        printf("array[0]: \n", buffer[0]);
        printf("array[1]: \n", buffer[1]);
        printf("array[2]: \n", buffer[2]);
        printf("array[3]: \n", buffer[3]);    
    
        
      system("PAUSE");	
      return 0;
    }
    
      void num2hexstr(int num, char *buf)
    {
            char tmp[8]; // assuming a 32-bit int.
            int i, j;
    
            for (i = 0; i < 8; i++)
            {
                j = num & 0xf;
                
                if (j < 10)
                {
                   tmp[i] = '0' + j;              // gives hex number if less than 'A'
                } 
                else 
                {
                    j -= 10;
                    tmp[i] = 'A' + j;             // gives correct hex letter
                }
                num >>= 4;                        // move to next nibble
            }
            
            buf[0] = '0';
            buf[1] = 'x';
            for (i = 2, j = 7; i < 11; i++, j--)
            {
                buf[i] = tmp[j];
            }
            buf[i] = '\0';
            
    }
    --dave
    Last edited by droseman; 11-12-2009 at 10:11 AM. Reason: extra information

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by droseman View Post
    thanks to kennedy and mk for your ideas. Both would work for me. In your opinion, which of these approaches is likely to have a smaller code footprint?

    --dave
    It looks to me like the table. You can just take the output of your operation for each column (whether you use division and modulus or bit-shifting) and go:
    Code:
    char table[] = "0123456789abcdef";
    int n = 66, tens = n/16, ones = n%16;
    char hex[5]="0x";
    hex[2] = table[tens];
    hex[3] = table[ones];
    hex[4] = '\0';
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    Embedded in C...
    Join Date
    Sep 2008
    Location
    Basingstoke, Hampshire
    Posts
    83
    that certainly looks much simpler, but I got the other method working and its integrated into my code, with the correct addresses happily being sent to my serial port, so I am a happy camper all round.

    Thanks to all of you, as always its simple when you work it through..

    Dave

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 04-25-2008, 02:45 PM
  2. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  3. string converting upper/lower
    By jlamn in forum C Programming
    Replies: 9
    Last Post: 09-24-2002, 06:01 PM
  4. ........ed off at functions
    By Klinerr1 in forum C++ Programming
    Replies: 8
    Last Post: 07-29-2002, 09:37 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM