convert string of hex characters to char

R

rtillmore

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,
 
U

user923005

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=
"2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b­2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040b­c3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3";
  char *toHex, *output[100];
The above addresses do not point to allocated space.
  unsigned long nVal;
  int i,j;

  for (i=0; i<100; i++){
    strcpy(toHex,&temp[j]);

strcpy() keeps going until it finds a null terminator. You are moving
201 characters into a random location in memory. Furthermore, j is
uninitialized.
    strcpy(toHex,&temp[j+1]);
See above.
    nVal = strtoul(toHex, NULL, 16);
    output = (char*)nVal;

The above cast is utter nonsense.
    j=j+2;
  }
  printf("output = %d \n", output);
Wrong format specifier.
  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?

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;
}
 
R

rtillmore

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=
"2b0000203032577ef6a7325629024b0b0a0abc0b75392040bc3c1a2be4b7d93129f3f1de7b­2a920000b73aedc3f247839cc3000000203032577ef6a7325629024b0b0a0abc0b75392040b­c3c1a2be4b7d93129f3f1de7b2a920000b73aedc3f247839cc3";
  char *toHex, *output[100];

The above addresses do not point to allocated space.

Ah, yes I see it now. It was starting right at me.
  unsigned long nVal;
  int i,j;
  for (i=0; i<100; i++){
    strcpy(toHex,&temp[j]);

strcpy() keeps going until it finds a null terminator.  You are moving
201 characters into a random location in memory.  Furthermore, j is
uninitialized.
    strcpy(toHex,&temp[j+1]);

See above.
    nVal = strtoul(toHex, NULL, 16);
    output = (char*)nVal;


The above cast is utter nonsense.
    j=j+2;
  }
  printf("output = %d \n", output);

Wrong format specifier.
  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?

Some diagnostic tools applied to the code:

c:\tmp>lin tt.c

output deleted
c:\tmp>splint tt.c > tt.spl
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.
 
R

rtillmore

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]);

     Bzzzt!  There are at least three things wrong here.  First, you
have not given any value to the pointer variable toHex, so its value
is indeterminate: it "contains garbage" or "points to a random place,"
and you have no idea where you're trying to store the data you copy
out of temp.

Yeah I see that now.
 Second, you have not given any value to the integer
variable j, so its value is also indeterminate: it "holds a random
value" and you have no idea where you're trying to copy from.

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.
 And
third, strcpy() is the wrong function to use if you're trying to copy
single characters: It will start with the first character you point it
at and just keep chugging along until it has copied a '\0' character.

     Suggested fix: Change toHex from a pointer to an array of three
characters, initialize j to zero before the loop, and replace the
two strcpy() calls with

        toHex[0] = temp[j];
        toHex[1] = temp[j+1];
        toHex[2] = '\0';

(There are snazzier ways to write this, but I'm trying to stick with
your original terminology for clarity's sake.)

Thank you for sticking to the original code.
    strcpy(toHex,&temp[j+1]);
    nVal = strtoul(toHex, NULL, 16);
    output = (char*)nVal;


     Here's another problem: output is an array of 100 pointer variables,
but your trying to store actual char values in them.  I imagine that the
compiler complained about an earlier version of the code, and that you
added the (char*) cast to silence it.  


That is exactly what I did.
Unfortunately, this is almost
always the wrong thing to do: The right thing is to step back and ask
why the compiler is complaining.

     Suggested fix: Change output to an array of char instead of an
array of char*.  Also, try to figure out what you intend to do with
all these characters; at the moment, you're doing almost nothing.


     Another problem: output is an array of char* (or an array of char
with the change suggested above), and the "%d" specifier wants ...
Right you are, it wants one integer.  Since when is a 100-place
array the same as one integer?

     Suggested fix: Get rid of output altogether, put the printf
call inside the loop (you may want to make adjustments to the format),
and print out each nVal as you compute it.


     For extra credit and another approach to the problem, study the
sscanf function and consider how you might use a "%2x" specifier.

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,
 
K

Keith Thompson

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.
[...]

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.
 
R

rtillmore

[...]> 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.

[...]

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.

I learned something new today.

Thanks,
 
R

rtillmore

For extra credit and another approach to the problem, study the
sscanf function and consider how you might use a "%2x" specifier.

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.
 
R

rtillmore

For extra credit and another approach to the problem, study the
sscanf function and consider how you might use a "%2x" specifier.

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.


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?
 
K

Keith Thompson

[...]> 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.

[...]

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.

I wrote the above.
I learned something new today.

When you post a followup, please leave the attribution lines (such as
the "(e-mail address removed) writes:" line above) in place. Quoting
someone else's words without giving them credit is considered rude.
 
R

rtillmore

The compiler threw a:
I find it difficult to believe that the code you've shown
could produce this error message. Are you sure this is your
actual code?

It did and still does.
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?

No. Or, "almost certainly not." You've been told at least twice
that using a cast to silence a compiler complaint is usually wrong,
so the fact that you persist in doing so suggests an unwillingness to
pay attention to the advice you ask for -- which in turn makes this
advisor wonder whether he's just wasting his time ...


This is why I asked.
To give a "for certain" answer, though, we need to see that
actual, complete code and not paraphrased snippets. And if you want
to show us compiler messages, please make sure they're rendered
accurately.

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
 
J

jameskuyper

(e-mail address removed) wrote:
....
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?

No. Or, "almost certainly not." You've been told at least twice
that using a cast to silence a compiler complaint is usually wrong,
so the fact that you persist in doing so suggests an unwillingness to
pay attention to the advice you ask for -- which in turn makes this
advisor wonder whether he's just wasting his time ...


This is why I asked.


That explains why you asked; it doesn't explain why you used the cast
after having been warned against using them.
To give a "for certain" answer, though, we need to see that
actual, complete code and not paraphrased snippets. And if you want
to show us compiler messages, please make sure they're rendered
accurately.

Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

unsigned char output[100];

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.
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 *'
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top