convert string of hex characters to char

Discussion in 'C Programming' started by rtillmore, Oct 7, 2008.

  1. rtillmore

    rtillmore Guest

    Hello,

    I did a quick google search and nothing that was returned is quite
    what I am looking for. I have a 200 character hexadecimal string that
    I need to convert into a 100 character string.

    This is what I have so far:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main ()
    {
    char *temp=
    "2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3";
    char *toHex, *output[100];
    unsigned long nVal;
    int i,j;

    for (i=0; i<100; i++){
    strcpy(toHex,&temp[j]);
    strcpy(toHex,&temp[j+1]);
    nVal = strtoul(toHex, NULL, 16);
    output = (char*)nVal;
    j=j+2;
    }
    printf("output = %d \n", output);
    return 0;
    }

    This program is supposed to take the first two characters from temp
    and convert the hex 2b to char which is +. Then it gets the next two
    characters and repeats.

    I compiled with gcc test.c -o test
    When I run test I get:
    segmentation fault

    What did I do wrong?
    Thanks,
     
    rtillmore, Oct 7, 2008
    #1
    1. Advertisements

  2. rtillmore

    user923005 Guest

    The above addresses do not point to allocated space.
    strcpy() keeps going until it finds a null terminator. You are moving
    201 characters into a random location in memory. Furthermore, j is
    uninitialized.
    See above.

    The above cast is utter nonsense.
    Wrong format specifier.
    Some diagnostic tools applied to the code:

    c:\tmp>lin tt.c

    c:\tmp>"C:\Lint\Lint-nt" +v -i"C:\Lint" std.lnt -os(_LINT.TMP)
    tt.c
    PC-lint for C/C++ (NT) Vers. 8.00u, Copyright Gimpel Software
    1985-2006

    --- Module: tt.c (C)

    c:\tmp>type _LINT.TMP | more

    --- Module: tt.c (C)

    _

    "2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b¡2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040b¡c3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f2478
    39cc3";
    tt.c(8) : Info 1776: Converting a string literal to char * is not
    const safe
    (initialization)
    _
    strcpy (toHex, &temp[j]);
    tt.c(16) : Warning 530: Symbol 'toHex' (line 9) not initialized ---
    Eff. C++
    3rd Ed. item 4
    tt.c(9) : Info 830: Location cited in prior message
    _
    strcpy (toHex, &temp[j]);
    tt.c(16) : Warning 530: Symbol 'j' (line 11) not initialized --- Eff. C
    ++ 3rd
    Ed. item 4
    tt.c(11) : Info 830: Location cited in prior message
    _
    printf ("output = %d \n", output);
    tt.c(22) : Warning 626: argument no. 2 inconsistent with format
    _
    }
    tt.c(24) : Note 953: Variable 'toHex' (line 9) could be declared as
    const ---
    Eff. C++ 3rd Ed. item 3
    tt.c(9) : Info 830: Location cited in prior message
    _
    }
    tt.c(24) : Note 953: Variable 'temp' (line 7) could be declared as
    const ---
    Eff. C++ 3rd Ed. item 3
    tt.c(7) : Info 830: Location cited in prior message
    _
    }
    tt.c(24) : Note 954: Pointer variable 'temp' (line 7) could be
    declared as
    pointing to const --- Eff. C++ 3rd Ed. item 3
    tt.c(7) : Info 830: Location cited in prior message

    ---
    output placed in _LINT.TMP

    c:\tmp>splint tt.c > tt.spl
    Splint 3.1.1 --- 12 Mar 2007

    Finished checking --- 3 code warnings

    c:\tmp>type tt.spl
    tt.c: (in function main)
    tt.c(16,28): Variable j used before definition
    An rvalue is used that may not be initialized to a value on some
    execution
    path. (Use -usedef to inhibit warning)
    tt.c(16,15): Unallocated storage toHex passed as out parameter to
    strcpy: toHex
    tt.c(22,29): Format argument 1 to printf (%d) expects int gets char *
    [100]:
    output
    Type of parameter is not consistent with corresponding code in
    format string.
    (Use -formattype to inhibit warning)
    tt.c(22,22): Corresponding format code


    c:\tmp>type tt.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main()
    {
    char *temp =

    "2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b¡2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040b¡c3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f2478
    39cc3";
    char *toHex, *output[100];
    unsigned long nVal;
    int i, j;


    for (i = 0; i < 100; i++)
    {
    strcpy (toHex, &temp[j]);
    strcpy (toHex, &temp[j + 1]);
    nVal = strtoul (toHex, NULL, 16);
    output = (char *) nVal;
    j = j + 2;
    }
    printf ("output = %d \n", output);
    return 0;
    }

    c:\tmp>

    Perhaps something like this:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main ()
    {
    const unsigned char temp[]=
    "2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b­
    2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040b­
    c3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3";
    unsigned char toHex[3]={0}, output[((sizeof temp) >> 1) + 1];
    unsigned long nVal;
    int i,j;

    for (i=0, j=0; i<100; i++, j+=2){
    toHex[0] = temp[j];
    toHex[1] = temp[j+1];
    nVal = strtoul(toHex, NULL, 16);
    output = (unsigned char)nVal;
    printf("%02x ", output);
    if ((i+1) % 26 == 0) putchar('\n');
    }
    putchar('\n');
    return 0;
    }
     
    user923005, Oct 7, 2008
    #2
    1. Advertisements

  3. rtillmore

    rtillmore Guest

    I did a quick google search and nothing that was returned is quite
    Ah, yes I see it now. It was starting right at me.

    output deleted
    output deleted

    It looks like there is a linux version of splint. I will start to use
    it.

    Thank you for the fixed code. I will try it tomorrow and let you know
    if I get it working.
     
    rtillmore, Oct 7, 2008
    #3
  4. rtillmore

    rtillmore Guest

    I did a quick google search and nothing that was returned is quite
    Yeah I see that now.
    I could have sworn that when you use gcc to compile a program the
    variables are initialized to zero or Null. I read the linux-kernel
    mail list and see messages that say NOT to initialize variables as it
    isn't needed and just adds bloat to the executable. Oh well.
    Thank you for sticking to the original code.


    That is exactly what I did.
    I use sprintf elsewhere to store the hex version of something. I am
    not in front of my PC at the moment.

    Thanks for the tips. I will post when I figure it all out.

    Thanks,
     
    rtillmore, Oct 8, 2008
    #4
  5. [...]

    Objects with static storage duration, if they're not explicitly
    initialized, are implicitly initialized to 0 with the appropriate type
    (0 for integers, 0.0 for floating-point, NULL (not Null) for pointers,
    applied recursively to struct and union members and array elements).
    This applies to objects declared outside any function, and to objects
    declared within a function with the "static" keyword.

    Objects with automatic storage duration, if they're not explicitly
    initialized, are not implicitly initialized. Their initial values
    will be garbage.
     
    Keith Thompson, Oct 8, 2008
    #5
  6. rtillmore

    rtillmore Guest

    [...]> I could have sworn that when you use gcc to compile a program the
    I learned something new today.

    Thanks,
     
    rtillmore, Oct 8, 2008
    #6
  7. break this habit
     
    Nick Keighley, Oct 8, 2008
    #7
  8. rtillmore

    rtillmore Guest

    For extra credit and another approach to the problem, study the
    You mean something like this:
    for (i=0, j=0; i<76; i++, j+=2){
    sscanf(&temp[j], "%2x", &output);
    printf("%02x ", output);
    }

    Thank you to everyone for your help.
     
    rtillmore, Oct 8, 2008
    #8
  9. rtillmore

    rtillmore Guest



    The compiler threw a:
    warning: format '%2x' expects type 'unsigned int *', but argument 3
    has type 'unsigned int'

    so I did the following:
    sscanf(&temp[j], "%2x", (unsigned int*)&output);

    It silences the compiler and the output is the same but I wanted to
    post to make sure this was the right way to handle the warning.

    So is this right?
     
    rtillmore, Oct 8, 2008
    #9
  10. I wrote the above.
    When you post a followup, please leave the attribution lines (such as
    the " writes:" line above) in place. Quoting
    someone else's words without giving them credit is considered rude.
     
    Keith Thompson, Oct 8, 2008
    #10
  11. rtillmore

    rtillmore Guest

    The compiler threw a:
    It did and still does.


    This is why I asked.
    Here is the code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main ()
    {
    const char temp[] =
    "2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3";

    unsigned char output[100];
    int i,j;

    for (i=0, j=0; i<100; i++, j+=2){
    sscanf(&temp[j], "%2x", &output);
    printf("%02x ", output);
    if ((i+1) % 26 == 0) putchar('\n');
    }
    printf("\n");
    return 0;
    }

    # gcc -Wall test.c -o test
    test.c: In function 'main':
    test.c:14: warning: format '%2x' expects type 'unsigned int *', but
    argument 3 has type 'unsigned char *'

    # ./test
    2b 00 00 20 30 32 57 7e f6 a7 32 56 29 02 4b 0b 0a 0a bc 0b 75 39 20
    40 bc 3c
    1a 2b e4 b7 d9 31 29 f3 f1 de 7b 2a 92 00 00 b7 3a ed c3 f2 47 83 9c
    c3 00 00
    00 20 30 32 57 7e f6 a7 32 56 29 02 4b 0b 0a 0a bc 0b 75 39 20 40 bc
    3c 1a 2b
    e4 b7 d9 31 29 f3 f1 de 7b 2a 92 00 00 b7 3a ed c3 f2 47 83 9c c3
     
    rtillmore, Oct 8, 2008
    #11
  12. rtillmore

    jameskuyper Guest

    wrote:
    ....


    That explains why you asked; it doesn't explain why you used the cast
    after having been warned against using them.
    This should be declared as "unsigned int", not "unsigned char". Eric
    suggested using unsigned char, and also suggested using sscanf() with
    a "%2x" format specifier, but those two suggestions weren't mean to go
    together.
     
    jameskuyper, Oct 8, 2008
    #12
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.