[comp.lang.c] Converting ascii hex values to hex bytes

mpledger@cti1.UUCP (Mark Pledger) (10/17/90)

I have a little stumper of a question.  I am writing software that accesses
a configuration file that stores IP addresses.  The IP addresses are stored
as raw hex bytes.  For example, an IP address of say 122.10.10.44 is stored
in the configuration file as 4 bytes 7A-0A-0A-2C.  Now I am using fread()
and fwrite() to get a lot of different configuration data.  What I want to 
do is to be able to convert 122.10.10.44 into a character string of 4 bytes
that equals "\x7a\x0a\x0a\x2c".  How can I convert the ascii representation
into hex?  I tried using itoa(), but the result is in ascii character format
so if you used itoa(44,result,16), result[] = "2C".  When written to disk,
the result[] string is actually written to disk as an ascii 2 (32h) and an
ascii C (43h).  What I want is one byte equalling "\x2c".

Can anybody give me a hand?  Thanks in advance.









-- 
Sincerely,


Mark Pledger

--------------------------------------------------------------------------
CTI                              |              (703) 685-5434 [voice]
2121 Crystal Drive               |              (703) 685-7022 [fax]
Suite 103                        |              
Arlington, DC  22202             |              mpledger@cti.com
--------------------------------------------------------------------------

dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) (10/17/90)

In article <298@cti1.UUCP> mpledger@cti1.UUCP (Mark Pledger) writes:
>and fwrite() to get a lot of different configuration data.  What I want to 
>do is to be able to convert 122.10.10.44 into a character string of 4 bytes
>that equals "\x7a\x0a\x0a\x2c".  How can I convert the ascii representation
>into hex?  I tried using itoa(), but the result is in ascii character format

You don't want to convert anything into hex, you want to convert the
character string "122.10.10.44" into four one-byte integers, char
being a synonym for one-byte integers. Something like this 
will do it:

int
convert_data (const char *ascii, char *four_bytes)
{
  char *p;
  int bytenum;

  for (bytenum = 0, p = ascii; bytenum < 4; bytenum++)
    {
      four_bytes[bytenum] = atoi (p);
      if ((p = strchr (p, '.')) == NULL)   /* strchr is called index in BSD */
        return -1;
    }

  return 0;
}


Hex is only meaningful when you go to output the four bytes of data and
you need to convert it into a hex string.




--
Dave Eisen                      	    Home: (415) 323-9757
dkeisen@Gang-of-Four.Stanford.EDU           Office: (415) 967-5644
1447 N. Shoreline Blvd.
Mountain View, CA 94043

dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) (10/18/90)

In article <1990Oct17.162529.20096@Neon.Stanford.EDU> dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) writes:

That idiot Eisen had what appears to be a typo in his code:


int
convert_data (const char *ascii, char *four_bytes)
{
  char *p;
  int bytenum;

  for (bytenum = 0, p = ascii; bytenum < 4; bytenum++)
    {
      four_bytes[bytenum] = atoi (p);
      if ((p = strchr (p, '.')) == NULL)   /* strchr is called index in BSD */
        return -1;
      p++;  /* Omitted in the original posting */
    }

  return 0;
}

--
Dave Eisen                      	    Home: (415) 323-9757
dkeisen@Gang-of-Four.Stanford.EDU           Office: (415) 967-5644
1447 N. Shoreline Blvd.
Mountain View, CA 94043

msmith%peruvian.utah.edu@cs.utah.edu (Matthew Smith) (10/18/90)

In article <298@cti1.UUCP> mpledger@cti1.UUCP (Mark Pledger) writes:
>I have a little stumper of a question.  I am writing software that accesses
>a configuration file that stores IP addresses.  The IP addresses are stored
>as raw hex bytes.  For example, an IP address of say 122.10.10.44 is stored
>in the configuration file as 4 bytes 7A-0A-0A-2C.  Now I am using fread()
>and fwrite() to get a lot of different configuration data.  What I want to 
>do is to be able to convert 122.10.10.44 into a character string of 4 bytes
>that equals "\x7a\x0a\x0a\x2c".  How can I convert the ascii representation
>into hex?  I tried using itoa(), but the result is in ascii character format
>so if you used itoa(44,result,16), result[] = "2C".  When written to disk,
>the result[] string is actually written to disk as an ascii 2 (32h) and an
>ascii C (43h).  What I want is one byte equalling "\x2c".
>
>Can anybody give me a hand?  Thanks in advance.

Well, I'm not sure I understand you correctly, because if I do, then things
will be fairly simple.  In C, there is no difference in the way a char and an
integer are represented, except that a char only has 4 bits as opposed to 8.
As a matter of fact, chars are only integers that range from 0 to 255.  Maybe
the following piece of code will help clarify things:


char a;

a=64;
printf("%c, %x\n",a,a);

you'll get an output of "a" and "40" repectively.  "a" being the ascii 
value of 64, and "40" being the hex value of 64.

Using this idea, you should just read all of the numbers into char variables
and then print them out in hex.


>Sincerely,
>
>
>Mark Pledger
>


I hope this helps...

(I'm sure this is going to bring on a huge discussion on how having a "char"
variable is NOT the same thing as an integer between 0 and 255, and how K&R 
says this, and Joe says that, and the other thing.  So, please forgive me
for making such a statement and let's not bog down the net with such trivial
details)

Matt Smith

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (10/18/90)

In article <298@cti1.UUCP> mpledger@cti1.UUCP (Mark Pledger) writes:
>and fwrite() to get a lot of different configuration data.  What I want to 
>do is to be able to convert 122.10.10.44 into a character string of 4 bytes
>that equals "\x7a\x0a\x0a\x2c".  How can I convert the ascii representation
>into hex?  I tried using itoa(), but the result is in ascii character format

void convert_internet_address_to_binary(const char *inet_addr, char *bin)
    {
	int i[4];
	sscanf(inet_addr, "%d.%d.%d.%d", &i[0], &i[1], &i[2], &i[3]);
	bin[0] = i[0], bin[1] = i[1], bin[2] = i[2], bin[3] = i[3];
    }

Alas, the *scanf() family supports int*, short*, and long* arguments,
but not char*, which is why we need i[].
-- 
Fear most of all to be in error.	-- Kierkegaard, quoting Socrates.

brianh@hpcvia.CV.HP.COM (brian_helterline) (10/18/90)

Matthew Smith writes:
[(Mark Pledger) stuff deleted]

>Well, I'm not sure I understand you correctly, because if I do, then things
>will be fairly simple.  In C, there is no difference in the way a char and an
>integer are represented, except that a char only has 4 bits as opposed to 8.
                                        ^^^^^^^^^^^^^^^^^^^^
	WHAT?????? a char has 8 bits!!  4 bits yield values from 0-15.
    
>As a matter of fact, chars are only integers that range from 0 to 255.  Maybe
>the following piece of code will help clarify things:


>char a;

>a=64;
>printf("%c, %x\n",a,a);

>you'll get an output of "a" and "40" repectively.  "a" being the ascii 
>value of 64, and "40" being the hex value of 64.

>Using this idea, you should just read all of the numbers into char variables
>and then print them out in hex.

	This is *exactly* what the original poster did NOT want!  He did
	not want the hex value converted to 2 chars and output as a string,
	he wanted to output 1 char whose ascii value was the hex value
	he wanted.  (In this discussion, hex really isn't important, since
	it it just the integer value and it can be thought of in hex, octal
	binary, etc )

>I hope this helps...

>(I'm sure this is going to bring on a huge discussion on how having a "char"
>variable is NOT the same thing as an integer between 0 and 255, and how K&R 
>says this, and Joe says that, and the other thing.  So, please forgive me
>for making such a statement and let's not bog down the net with such trivial
>details)
	
	Calling a char 4 bits is not trival.

>Matt Smith
>----------

msmith%peruvian.utah.edu@cs.utah.edu (Matthew Smith) (10/19/90)

In article <31530022@hpcvia.CV.HP.COM> brianh@hpcvia.CV.HP.COM (brian_helterline) writes:
>Matthew Smith writes:
>[(Mark Pledger) stuff deleted]
>
>>Well, I'm not sure I understand you correctly, because if I do, then things
>>will be fairly simple.  In C, there is no difference in the way a char and an
>>integer are represented, except that a char only has 4 bits as opposed to 8.
>                                        ^^^^^^^^^^^^^^^^^^^^
>	WHAT?????? a char has 8 bits!!  4 bits yield values from 0-15.

Yeah yeah yeah.... I know...  I thought about it after I had sent it, and I 
figured I was gonna get flamed for it.  Bad day.

>>As a matter of fact, chars are only integers that range from 0 to 255.  Maybe
>>the following piece of code will help clarify things:
>
>
>>char a;
>
>>a=64;
>>printf("%c, %x\n",a,a);
>
>>Using this idea, you should just read all of the numbers into char variables
>>and then print them out in hex.
>
>	This is *exactly* what the original poster did NOT want!  He did
>	not want the hex value converted to 2 chars and output as a string,
>	he wanted to output 1 char whose ascii value was the hex value
>	he wanted.  (In this discussion, hex really isn't important, since
>	it it just the integer value and it can be thought of in hex, octal
>	binary, etc )
>

It doesn't put the output as a string.  You misunderstood what I was trying 
to get across.  A byte is stored as a series of 8 (yes, I AM awake today) bits
so whether or not you express them as a hex number of a decimal number makes
no difference to the machine.  If he reads in a number into a char, and then
does a printf %x, he'll get the decimal number in hex format, if he prints it
with a %c, he'll get the character with that ascii value.  So, all he has to
do is read in the numbers into chars.  If he is reading in the numbers as a 
string, ie: '1','2','2', all he has to do is do a atoi, which will return 
122 in a 16 bit integer, and then cast it into a char, and he'll have 122 in 
1 char.  ie:  The 1 character ascii value of a number.  

>
>>(I'm sure this is going to bring on a huge discussion on how having a "char"
>>variable is NOT the same thing as an integer between 0 and 255, and how K&R 
>>says this, and Joe says that, and the other thing.  So, please forgive me
>>for making such a statement and let's not bog down the net with such trivial
>>details)
>	
>	Calling a char 4 bits is not trival.

I agree.  It was downright sloppy.

Matt Smith

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (10/19/90)

In article <1990Oct18.144906.5278@hellgate.utah.edu> msmith%peruvian.utah.edu@cs.utah.edu (Matthew Smith) writes:
>does a printf %x, he'll get the decimal number in hex format, if he prints it
>with a %c, he'll get the character with that ascii value.  So, all he has to
>do is read in the numbers into chars.  If he is reading in the numbers as a 
>string, ie: '1','2','2', all he has to do is do a atoi, which will return 
>122 in a 16 bit integer, and then cast it into a char, and he'll have 122 in 
>1 char.  ie:  The 1 character ascii value of a number.  

To be picky, the cast is unnecessary, since chars are converted to ints
anyway when used as function arguments.  The following code works:

printf("%c%c\n",65,'a');

to print two a's.  I suggest putchar in this case, however.

--
Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD
And Dinsdale said, "You've been a naughty boy, Clement," and splits me nostrils
open, and saws me leg off, and pulls me liver out.  And I said, "My name's not
Clement."  And then he loses his temper.  And he nails me head to the floor.

unhd (Jonathan W Miner) (10/24/90)

In article <298@cti1.UUCP> mpledger@cti1.UUCP (Mark Pledger) writes:
>[... deleted stuff ...]
>and fwrite() to get a lot of different configuration data.  What I want to 
>do is to be able to convert 122.10.10.44 into a character string of 4 bytes
>that equals "\x7a\x0a\x0a\x2c".  How can I convert the ascii representation
>into hex?  I tried using itoa(), but the result is in ascii character format
>[... more deleted stuff ...]

I have not tested this but you should be able to take the string
"122.10.10.44" and run it through a sscanf to get four integers.  Then
stick the four integers into a character array.
       
        int  one,two,three,four;
        char ch[4]; 

        strcpy(s,"122.10.10.44\0");
 	sscanf(s,"%d.%d.%d.%d",&one,&two,&three,&four);
        ch[0] = one;
        ch[1] = two;
        ch[2] = three;
        ch[3] = four; 

The array 'ch' will now hold the values 7a,0a,0a,2c.  This should work
if your machine supports direct conversion from integers to characters.	

-----------------------------------------------------------------
Jonathan Miner        | I don't speak for UNH, and UNH does not 
jwm775@unhd.unh.edu   | speak for me! 
(603)868-3416         | Rather be downhill skiing... or hacking... 
-- 
-----------------------------------------------------------------
Jonathan Miner        | I don't speak for UNH, and UNH does not 
jwm775@unhd.unh.edu   | speak for me! 
(603)868-3416         | Rather be downhill skiing... or hacking... 

kkenny@wind.nrtc.northrop.com (Kevin B. Kenny KE9TV) (10/24/90)

In article <298@cti1.UUCP> mpledger@cti1.UUCP (Mark Pledger) writes:
>What I want to do is to be able to convert 122.10.10.44 into a
>character string of 4 bytes that equals "\x7a\x0a\x0a\x2c".  How can
>I convert the ascii representation into hex?  I tried using itoa(),
>but the result is in ascii character format

If you're on a 4.x BSD machine, or another one that has the `inet'
library, the accepted way to parse Internet addresses is:

----------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

...

	char * address_in_dotted_form;
	unsigned long parsed_address;

...

	parsed_address = inet_addr (address_in_dotted_form);
----------------------------------------

The manual page for this is inet(3n).

Kevin, KE9TV