Is there a simpler way?

F

Fred Hebert

I am trying to learn VC.NET and convert some Borland C++ applications. The
syntax differences are killing me...

Is there an easy way to convert a hex string, entered by the user, to a
binary string and back? This is the actual code I am trying to convert.

HexToBin(KeyEdit->Text.c_str(), BinKey, sizeof(BinKey));

HexToBin is a generic function that converts a string like "1b34c38d" to
it's binary equivalent. There is also a BinToHex which reverses the
process.

I know I could write a function to do it, but I threw all those routines
away 10 years ago when I started using Borland.

I am hoping that someone can help, because I really don't want to have to
go back to writing all of those little conversion routines.
 
G

Guest

Please see the methods of Int32. Int32->Parse can convert hex string to
binary, and Int32->ToString can convert from binary to hex string. Have fun!
 
D

doug mansell

sscanf might suit your purposes.

int nHex;
if (1 == sscanf(KeyEdit->Text.c_str(), "%x", &nHex)) {
// converted
}
 
M

Martin Richter [MVP]

Hallo Fred!
I am trying to learn VC.NET and convert some Borland C++ applications. The
syntax differences are killing me...

Why? Its C++
Is there an easy way to convert a hex string, entered by the user, to a
binary string and back? This is the actual code I am trying to convert.

HexToBin(KeyEdit->Text.c_str(), BinKey, sizeof(BinKey));

HexToBin is a generic function that converts a string like "1b34c38d" to
it's binary equivalent. There is also a BinToHex which reverses the
process.

I know I could write a function to do it, but I threw all those routines
away 10 years ago when I started using Borland.

Even than you should be able to program and learn! SCNR...
I am hoping that someone can help, because I really don't want to have to
go back to writing all of those little conversion routines.

static inline TCHAR ByteToHex(int c)
{
return static_cast<TCHAR>((c<10) ? (c)+_T('0') : (c)-10+_T('A'));
}


void BinToString(PCVOID pData, PTSTR pszOut, int iLen)
{
int iPos=0;
const BYTE *pszStr = (const BYTE *)pData;
while (iLen--)
{
BYTE byte = *pszStr++;
BYTE uByte = (byte & 0xF0) >> 4,
lByte = byte & 0xF;
pszOut[iPos++] = ByteToHex(uByte);
pszOut[iPos++] = ByteToHex(lByte);
}
pszOut[iPos] = '\0';
}

static inline int HexToByte(TCHAR c)
{
return (c>=_T('0') && c<=_T('9')) ? (c)-_T('0') :
(c>=_T('A') && c<=_T('F')) ? (c)-_T('A')+10 :
(c>=_T('a') && c<=_T('f')) ? (c)-_T('a')+10 : 0;
}

static inline bool IsHexDigit(TCHAR c)
{
return c>=_T('0') && c<=_T('9') ||
((c>=_T('a') && c<=_T('f')) ||
(c>=_T('A') && c<=_T('F')));
}

int StringToBin(PCTSTR pIn, PVOID pOut, int iLen)
{
if (iLen==-1)
iLen = _tcslen(pIn)/2;
memset(pOut,0,iLen);
if (!pIn)
return 0;

TCHAR uByte, lByte;
int iPos=0;
PBYTE pszStr = static_cast<PBYTE>(pOut);
while (iPos<iLen && IsHexDigit(uByte=pIn[0]) && IsHexDigit(lByte=pIn[1]))
{
*pszStr++ = static_cast<BYTE>(HexToByte(uByte)<<4 | HexToByte(lByte));
++iPos;
pIn += 2;
}

return *pIn ? 0 : iPos;
}

HTH
 
S

Severian

I am trying to learn VC.NET and convert some Borland C++ applications. The
syntax differences are killing me...

Is there an easy way to convert a hex string, entered by the user, to a
binary string and back? This is the actual code I am trying to convert.

HexToBin(KeyEdit->Text.c_str(), BinKey, sizeof(BinKey));

HexToBin is a generic function that converts a string like "1b34c38d" to
it's binary equivalent. There is also a BinToHex which reverses the
process.

I know I could write a function to do it, but I threw all those routines
away 10 years ago when I started using Borland.

I am hoping that someone can help, because I really don't want to have to
go back to writing all of those little conversion routines.

Binary value or binary string?

To convert a value <= ULONG_MAX to an unsigned long binary value:

val = strtoul(strval, NULL, 0); // If strval as 0x1234abcd
val = strtoul(strval, NULL, 16); // if strval as 12341bcd

I'm sure there are STL and MFC classes that can do this too.

If you need to convert a hex string to a binary strings, I would use a
table For efficiency (sample below), though some languages may provide
built-in functions or extra formatting specifications.

Converting from hex to a binary value then to binary text might be
faster, but this will handle arbitrarily-long hex and binary values.

Sample ANSI C code:

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>

#define TESTING

#undef TRUE
#define TRUE 1
#undef FALSE
#define FALSE 0

/* Error codes */

#define eDIGIT 1
#define eTRUNC 2
#define eSEPAR 4

static int setdigit(int c, char *binval, int pos);

/* SevStrHexToBin()

Parameters:
hexval - Hex value to convert. May be prefixed with h, H,
x, X, 0x or 0X.
May be suffixed with h, H, x, or X.
groupchar - Group digits by this char (0 for no sep)
groupchar is also ignored in the input string
(groupchar cannot be any hex digit)
binval - Where to place the binary string
binmaxlen - Size of binval (with room for terminating \0)

Return values:
0 - Success
eTRUNC - binval not large enough
eDIGIT - invalid hex character in input string
eSEPAR - invalid groupchar
*/

int SevStrHexToBin(const char *hexval, int groupchar,
char *binval, int binmaxlen)
{
static const char hexdig[] = "0123456789abcdef";
int e = 0, pos, c, diglen = groupchar ? 5 : 4;
size_t hexlen = strlen(hexval);

memset(binval, 0, binmaxlen); /* In case of error */
if (!hexval || hexlen < 1)
return eDIGIT;
if (groupchar && strchr(hexdig, tolower((unsigned char)groupchar)))
return eSEPAR;
if (hexlen >= 2 && hexval[0] == '0' && tolower(hexval[1]) == 'x')
hexval += 2; /* Skip 0x if prepended */
else if ( (c = tolower(hexval[0])) == 'x' || c == 'h')
hexval++; /* Skip x or h if prepended */
hexlen = strlen(hexval);
if (hexlen &&
(((c = tolower(hexval[hexlen-1])) == 'x') || c == 'h'))
hexlen--; /* Ignore trailing "hHxX" */
for (pos = 0; hexlen-- && ((c =*hexval++) != 0); pos += diglen) {
if (pos + diglen - (groupchar && (hexlen == 0)) > binmaxlen)
return e | eTRUNC;
e |= setdigit(c, binval, pos);
if (groupchar && hexlen != 0)
binval[pos+4] = (char)groupchar;
}
return e;
}

static int setdigit(int c, char *binval, int pos)
{
static const char errdig[] = "****";
static const char bindig[] =
"0000 0001 0010 0011 " /* Spaces for readability */
"0100 0101 0110 0111 "
"1000 1001 1010 1011 "
"1100 1101 1110 1111 ";
int e = 0;

if (c >='0' && c <= '9')
memcpy(binval+pos, bindig + 5*(c-'0'), 4); /* Decimal */
else {
c = tolower((unsigned char)c);
if (c >= 'a' && c <= 'f')
memcpy(binval+pos, bindig + 5*(c-'a'+10), 4); /* Alpha */
else {
memcpy(binval+pos, errdig, 4);
e = eDIGIT; /* Invalid digit */
}
}
return e;
}

#ifdef TESTING

static char *hexbinerrmsg(int e)
{
switch (e) {
case eDIGIT: return " (invalid)";
case eTRUNC: return " (truncated)";
case eDIGIT|eTRUNC: return " (invalid & truncated)";
case eSEPAR: return " (invalid separator)";
default: return "";
}
}

int main(int argc, char *argv[])
{
char binval[82] = "";
int e = 0;

if (argc < 2) {
printf("%s\n", hexbinerrmsg(eDIGIT));
return EXIT_FAILURE;
}

/* Simple conversion */

e = SevStrHexToBin(argv[1], 0, binval, sizeof binval);
printf("%s: %s%s\n", argv[1], binval, hexbinerrmsg(e));

/* Space separators */

e = SevStrHexToBin(argv[1], ' ', binval, sizeof binval);
printf("%s: %s%s\n", argv[1], binval, hexbinerrmsg(e));

/* Colon separators */

e = SevStrHexToBin(argv[1], ':', binval, sizeof binval);
printf("%s: %s%s\n", argv[1], binval, hexbinerrmsg(e));

/* Invalid separators */

e = SevStrHexToBin(argv[1], '0', binval, sizeof binval);
printf("%s: %s%s\n", argv[1], binval, hexbinerrmsg(e));

return EXIT_SUCCESS;
}

#endif
 
F

Fred Hebert

Not dealing with an integer. These are encryption keys, 128 and 256 byte
strings that are entered by the user in hex.

Thanks anyway.
 
F

Fred Hebert

Not dealing with an integer. These are encryption keys, 128 and 256 byte
strings that are entered by the user in hex.

Thanks anyway.
 
F

Fred Hebert

Thanks for the response. I realize it is C++, but the differences in
syntax be Borland C++ and Microsoft C++ .NET are significant enough to be
annoying. Couple this with the fact that many of the functions and
components I am used to using are missing or different, and ... Well it's
a pain.

Case in point: 1 line of code in Borland C++ requires 54 lines of code
(your example) in MS C++ .NET. Before you get all excited, I realize this
is just one routine and not a fair comparison of the two environments. It
wasn't intend as a comparison.

From my perspective though, I feel that the evolution of programming
languages should be making programming easier. Than's why we evolved from
hand coded assembly to these higher level language compilers. I just find
it frustrating to have to go back to writing all kinds of what I consider
low level support routines.

Everyone is free to disagree, but what if you bought the latest BMW and
found that power windows were no longer an option, or the only sound system
was a mono AM radio?

I mean this is not a show stopper, and there are a lot of neat things, but
there are also a few holes.
 
I

Ioannis Vranos

Fred said:
Thanks for the response. I realize it is C++, but the differences in
syntax be Borland C++ and Microsoft C++ .NET are significant enough to be
annoying. Couple this with the fact that many of the functions and
components I am used to using are missing or different, and ... Well it's
a pain.

Case in point: 1 line of code in Borland C++ requires 54 lines of code
(your example) in MS C++ .NET. Before you get all excited, I realize this
is just one routine and not a fair comparison of the two environments. It
wasn't intend as a comparison.

From my perspective though, I feel that the evolution of programming
languages should be making programming easier. Than's why we evolved from
hand coded assembly to these higher level language compilers. I just find
it frustrating to have to go back to writing all kinds of what I consider
low level support routines.

Everyone is free to disagree, but what if you bought the latest BMW and
found that power windows were no longer an option, or the only sound system
was a mono AM radio?

I mean this is not a show stopper, and there are a lot of neat things, but
there are also a few holes.


..NET API is more >=high level than VCL/CLX (more high level in some
parts, about equally high level in other parts).


What you need is to read some up to date VC++ .NET book.


For VC++ 2003, a nice beginner to intermediate level book that you can
read, and covers all .NET facilities, including multithreading, is
"Visual C++ .NET How To Program" by Deitel.

http://vig.prenhall.com/catalog/academic/product/0,1144,0134373774,00.html



About your Borland C++ applications, why do you want to port them to
..NET, since they can run as they are?


I would create my new applications in .NET and keep the old ones as they
are.
 
F

Fred Hebert

I found an old program I wrote back in 1991 that still had a hex to binary
routine from the old days. It was only 5 lines long, and of course it
didn't work in VC.NET, but after 20 minutes I figured out the syntax
issues.

Anyhow, I took a look at your example and decided to see how it would work.
So I created a new Windows forms .NET project. Added an edit box, a button
and a label.

In the OnClick of the button I tried to use your code to convert the hex
string "46726564" to it's binary equivalent "Fred" and put it into the
label.

First of all I got 12 errors just trying to compile your code starting off
with "PCVOID :undeclared identifier", a few syntax errors, some "{ missing
function hearer (old-style formal list?)" and other fun things...

I am sure you are a fantastic programmer, but this is exactly what I am
talking about. The environment has changed, and the documentation is
horrible. I couldn't even find PCVOID in the help index.

I know what I want to do and usually can knock out code pretty quickly. I
also usually learn pretty quickly, but it is ridiculous when you have to
spent 5 minutes to an hour just trying to find the correct syntax.
 
I

Ioannis Vranos

Fred said:
First of all I got 12 errors just trying to compile your code starting off
with "PCVOID :undeclared identifier", a few syntax errors, some "{ missing
function hearer (old-style formal list?)" and other fun things...

I am sure you are a fantastic programmer, but this is exactly what I am
talking about. The environment has changed, and the documentation is
horrible. I couldn't even find PCVOID in the help index.

I know what I want to do and usually can knock out code pretty quickly. I
also usually learn pretty quickly, but it is ridiculous when you have to
spent 5 minutes to an hour just trying to find the correct syntax.


The one that Martin provided was using Win32 facilities and not .NET ones.
 
F

Fred Hebert

The reason for the port, is that we seldom write new programs, but rather
evolve existing applications. We are an OEM for automation controllers,
and our software allows the end user to control, program and monitor our
hardware. I am purposely being a little fuzzy because I don't wan to be
accused of advertising our products here.

Anyhow, one of my current tasks, apart from evaluating the switch to MS
compilers, is to add some additional functionally to the PC control
program to correspond to enhancements in one of our automation
controllers.

I am not going to spend 2 years redeveloping the app when I can spend a
few days or a couple of weeks just adding a few new dialogs. We strongly
embrace the concept of modular reusable code and I don't want to switch
to a new environment which makes 16 years of reusable code obsolete.

I am not sure .NET has any real advantage for us. I was looking at the
standard MSC and found the environment to be extremely primitive compared
to the RAD environment to which I have become accustomed. I started
looking at .NET because it was closer to the Borland stuff I was used to.
(Probably has something to do with all of the Borland programmers that
Microsoft hired.)

The main reason I am even looking at Visual Studio is that one of the
senior management, who does a little programming, read something about
the reusability and cross platform capabilities of .NET. So far I am not
impressed.

You are not the first person who has recommended that we start over from
scratch rather than try to convert old code to .NET. How is this
protecting our investment?

Also I don't think .NET is going to resolve our Windows/Unix/Linux
synchronization issues either. I mean I am having difficulty with the
Windows conversion but am making some progress. Trying to get one of
these apps to compile and run in a Linux environment is a non starter.
At least now in our current environment we can share most of the tricky
internal code (protocols, encryption, etc.). I think the device layer
and the GUI are always going to be problematic.

The myth of "one size fits all" only works if everyone wants poorly
fitting clothes. IMHO.

Perhaps in a business software (forms that update databases and basic
reports) environment .NET works better.

Anyhow I really am trying to do a fair evaluation. I am asking for help
just in case I am missing something. It wouldn't be the first time
someone pointed out that I was looking in the wrong place and when I was
directed the the right place things looked much better. I was hoping for
something like "look under string conversion functions" and not "roll
your own"...

I didn't think it was going to be this different and the built in docs
were going to be this inadequate. I'll take your advice and get the book
and go back to basics. Perhaps it will help me see the light. I just
hope it's not a freight train ;-)
 
F

Fred Hebert

To keep it simple, the basic question was, or should have been:

Aren't there built in functions for simple things like this?

The correct answer is "NO, you have to do it the hard way".

Here's my quick and dirty solution:

#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ?
(c)-'A'+10 : (c)-'0')

....

char BinKey[16];
for(int i=0; i < textBox1->Text->Length; i=i+2)
{
BinKey[i>>1] = (unsigned int)(hextobin(textBox1->Text->get_Chars(i)) <<
4) +
hextobin(textBox1->Text->get_Chars(i+
1));
}


The input has been previously validated. Again, in my old environment this
was done with a hex mask edit component that validated the length, took out
the dashes, converted the case. Basically no code. Then 1 line to convert
to binary.

After spending 30 minutes adding the missing functionality of the mask
edit, which I thought should already be there, I just wanted to convert it
to binary. I thought surely this basic function is built in? I mean the
hex mask edit didn't show up until 1999, I could understand something that
"advanced" being missing, but...

I ask again, is everything this difficult?
 
I

Ioannis Vranos

Fred said:
The reason for the port, is that we seldom write new programs, but rather
evolve existing applications. We are an OEM for automation controllers,
and our software allows the end user to control, program and monitor our
hardware. I am purposely being a little fuzzy because I don't wan to be
accused of advertising our products here.

Anyhow, one of my current tasks, apart from evaluating the switch to MS
compilers, is to add some additional functionally to the PC control
program to correspond to enhancements in one of our automation
controllers.

I am not going to spend 2 years redeveloping the app when I can spend a
few days or a couple of weeks just adding a few new dialogs. We strongly
embrace the concept of modular reusable code and I don't want to switch
to a new environment which makes 16 years of reusable code obsolete.

I am not sure .NET has any real advantage for us. I was looking at the
standard MSC and found the environment to be extremely primitive compared
to the RAD environment to which I have become accustomed. I started
looking at .NET because it was closer to the Borland stuff I was used to.
(Probably has something to do with all of the Borland programmers that
Microsoft hired.)

The main reason I am even looking at Visual Studio is that one of the
senior management, who does a little programming, read something about
the reusability and cross platform capabilities of .NET. So far I am not
impressed.


Well, .NET is a CLI compliant VM and here you may download the CLI standard:

http://www.ecma-international.org/publications/standards/Ecma-335.htm


The CLI standard also defines its assembly language. A book for it:

http://www.amazon.com/exec/obidos/t...f=sr_1_7/102-2992266-3703320?v=glance&s=books


The main benefits of .NET, apart from garbage collection is that it
provides a common API for all languages, and you can write different
parts of a program in different languages.


C++ currently takes advantage of .NET by using the "managed extensions",
however there is an upcoming C++/CLI standard and VC++ 2005 will use it
instead of "managed extensions" (while the API remains the same of course).


C++/CLI design ideals, are not only C++ to be used for application
programming as a first class citizen CLI (.NET) citizen, but *also* for
..NET library writing (managed dlls).


With C++/CLI and VC++ 2005, C++ becomes the systems programming language
of CLI (and .NET).


You may take a look at these:

http://msdn.microsoft.com/msdnmag/issues/05/01/COptimizations/default.aspx

http://pluralsight.com/blogs/hsutter/archive/2004/10/05/2672.aspx

http://blogs.msdn.com/branbray/archive/2003/11/07/51007.aspx

http://www.accu.org/conference/pres...Relevant_on_Modern_Environments_(keynote).pdf


And a page of mine:

http://www23.brinkster.com/noicys/cppcli.htm



With C++/CLI, C++ has two worlds: The unmanaged world and the managed world.

In the managed world every CLI (.NET) feature is provided separately
from the unmanaged world features.


You are not the first person who has recommended that we start over from
scratch rather than try to convert old code to .NET. How is this
protecting our investment?


With C++ on .NET you can compile in mixed mode, that is combine
unmanaged and managed code in the same application (for example you can
extend an existing unmanaged application with managed code).

The problem in your case is that you are using a third party API
(VCL/CLX) and Borland does not provide a .NET C++ compiler so far.


So you will have either rewrite everything that uses Borland stuff in
..NET, wait for Borland to produce a .NET enabled C++ compiler and then
simply extend your application from there, or use Delphi .NET, in the
case that Delphi can work with C++ Builder dlls (I do not know). Also
CLX was QT licensed by Trolltech: http://www.trolltech.com and they
provide a VC++ .NET version as far as I know, in case you are using CLX
and not VCL.


So in summary, the problem here is that you are using an API that VC++
does not come bundled with.


Myself have started windows programming with .NET directly (I do not
know any Win32, MFC) and had checked VCL sometime in the past, so I do
not know what happens in the case of unmanaged dlls. Perhaps it is
possible to encapsulate your entire application as a dll that VC++ can
work with, and then extend that application using VC++?


Also I don't think .NET is going to resolve our Windows/Unix/Linux
synchronization issues either. I mean I am having difficulty with the
Windows conversion but am making some progress. Trying to get one of
these apps to compile and run in a Linux environment is a non starter.
At least now in our current environment we can share most of the tricky
internal code (protocols, encryption, etc.). I think the device layer
and the GUI are always going to be problematic.


If you want complete *binary* portability to other CLI VMs (like Mono)
you will have to rewrite your application in pure managed mode (possible
only under upcoming VC++ 2005) for C++.

For source code portability only, there aren't any other C++ compilers
supporting .NET so far in other platforms. .NET is relatively new after
all (and will become the main Windows API after Longhorn, with its
official name being WinFX).


The myth of "one size fits all" only works if everyone wants poorly
fitting clothes. IMHO.

Perhaps in a business software (forms that update databases and basic
reports) environment .NET works better.

Anyhow I really am trying to do a fair evaluation. I am asking for help
just in case I am missing something. It wouldn't be the first time
someone pointed out that I was looking in the wrong place and when I was
directed the the right place things looked much better. I was hoping for
something like "look under string conversion functions" and not "roll
your own"...

I didn't think it was going to be this different and the built in docs
were going to be this inadequate. I'll take your advice and get the book
and go back to basics. Perhaps it will help me see the light. I just
hope it's not a freight train ;-)


No it is not a freight train, in the contrary it is very high level API. :)


However if you can do so, you had better wait for VC++ 2005 that will
use the new C++/CLI syntax (the switch from current "managed extensions"
to C++/CLI is not that difficult, you will have to use just a different
keyword for a current "managed extensions" keyword while also learn new
keywords since C++/CLI replaces and extends managed extensions).


Plus, C++/CLI feels more C++ than current managed extensions. :)


In summary, .NET is about this:


There is a CLI standard that defines the basics of a VM along with its
assembly language. .NET is a CLI-compliant VM.

http://www.ecma-international.org/publications/standards/Ecma-335.htm


The benefits of a CLI VM is garbage collection, and that source code of
all languages get compiled to an exe consisting of an Intermediate
Language (IL), and is not a native exe.

The VM translates this IL to native code when the application is executed.


This also means that you can write different parts of an application in
different languages (saved as managed dlls) and also use run-time
libraries (dlls) from various languages in different languages. :)

In summary, you save something as a dll library and use it from whatever
language you want.


In C++ you can work in mixed mode (managed and unmanaged) and you can
encapsulate unmanaged code with a managed interface and use it, thus
making it possible to use the unmanaged code with managed-only languages
(like VB).


Also with the upcoming C++/CLI, C++ becomes the systems programming
language of .NET.


You can download the latest C++/CLI draft from here:

http://www.plumhall.com/C++-CLI draft 1.10.pdf
 
S

Severian

To keep it simple, the basic question was, or should have been:

Aren't there built in functions for simple things like this?

The correct answer is "NO, you have to do it the hard way".

Here's my quick and dirty solution:

#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ?
(c)-'A'+10 : (c)-'0')

...

char BinKey[16];
for(int i=0; i < textBox1->Text->Length; i=i+2)
{
BinKey[i>>1] = (unsigned int)(hextobin(textBox1->Text->get_Chars(i)) <<
4) +
hextobin(textBox1->Text->get_Chars(i+
1));
}


The input has been previously validated. Again, in my old environment this
was done with a hex mask edit component that validated the length, took out
the dashes, converted the case. Basically no code. Then 1 line to convert
to binary.

After spending 30 minutes adding the missing functionality of the mask
edit, which I thought should already be there, I just wanted to convert it
to binary. I thought surely this basic function is built in? I mean the
hex mask edit didn't show up until 1999, I could understand something that
"advanced" being missing, but...

I ask again, is everything this difficult?

Well I don't think it was entirely clear what you wanted. It noew
appears you want to create some kind of binary *value* of 16 bytes
from 32 hex characters. My code provided binary *text* from hex
*text*, of arbitrary length with error checking.

The task I assume you're looking for (to convert a max of 32 bytes of
hex to 16 bytes of binary) is doable several simple ways:

/* C; Assumes hex digits always valid, in pairs and little-endian */

void hex32tobin16(char *hex, unsigned char *binkey)
{
int i;
memset(binkey, 0, 16);
char digs[]="0123456789abcdef";
for (i=0; i<16 && hex[i*2]; i++)
binkey = strchr(digs, tolower(hex[i*2]))<<4 +
strchr(digs, tolower(hex[i*2+1]));

/* C; Assumes hex digits always valid, in pairs */

void hex32tobin16(char *hex, unsigned char *binkey)
{
int v, i, j;
memset(binkey, 0, 16);
for (i=0, j=0; i<32 && hex; i+=2) {
sscanf(hex+i, "%2x", &v);
binkey[j++] = (unsigned char)v;
}
}

/* C; Assumes hex digits always valid, in pairs, little-endian */
/* Also assumes ASCII order (0-9...A-F...a-f) */

#define xtob(c) (((c)<=9)?((c)-'0'):(((c)<='F')?((c)-'A'):((c)-'a')));
void hex32tobin16(char *hex, unsigned char *binkey)
{
int i
memset(binkey, 0, 16);
for (i=0; i<32; i+=2)
binkey[i>>1] = (xtob(hex) << 4) + xtob(hex[i+1]);
}
 
M

Martin Richter [MVP]

Hallo Fred!
First of all I got 12 errors just trying to compile your code starting off
with "PCVOID :undeclared identifier", a few syntax errors, some "{ missing
function hearer (old-style formal list?)" and other fun things...

Sorry PCVOID is a define in one of my headers ans is simply a "const
void *" PVOID is defined in Win32 and a lot of LPC... but this one is
missing so I definedit by myself and didn't include it in the sample.
I am sure you are a fantastic programmer, but this is exactly what I am
talking about. The environment has changed, and the documentation is
horrible. I couldn't even find PCVOID in the help index.

Yes my mistake.
Anyhow, the typename itsself should lead you into the correct direction.
I know what I want to do and usually can knock out code pretty quickly. I
also usually learn pretty quickly, but it is ridiculous when you have to
spent 5 minutes to an hour just trying to find the correct syntax.

I am sorry, but what is your problem?
To think about the Win32 type syntax?
Use your head and a little logic!
If LPSTR is a pointer to string and LPCSTR is a const pointer to string?
If PVOID is a pointer to void, what could PCVOID be?

Again I am sory that I just cut&paste a code snipplet that wasn't 100%
complete. Again: The code sniplet showed a way, its not the bible!
 
S

Severian

To keep it simple, the basic question was, or should have been:

Aren't there built in functions for simple things like this?

The correct answer is "NO, you have to do it the hard way".

Here's my quick and dirty solution:

#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ?
(c)-'A'+10 : (c)-'0')

...

char BinKey[16];
for(int i=0; i < textBox1->Text->Length; i=i+2)
{
BinKey[i>>1] = (unsigned int)(hextobin(textBox1->Text->get_Chars(i)) <<
4) +
hextobin(textBox1->Text->get_Chars(i+
1));
}


The input has been previously validated. Again, in my old environment this
was done with a hex mask edit component that validated the length, took out
the dashes, converted the case. Basically no code. Then 1 line to convert
to binary.

After spending 30 minutes adding the missing functionality of the mask
edit, which I thought should already be there, I just wanted to convert it
to binary. I thought surely this basic function is built in? I mean the
hex mask edit didn't show up until 1999, I could understand something that
"advanced" being missing, but...

I ask again, is everything this difficult?

Well I don't think it was entirely clear what you wanted. It noew
appears you want to create some kind of binary *value* of 16 bytes
from 32 hex characters. My code provided binary *text* from hex
*text*, of arbitrary length with error checking.

The task I assume you're looking for (to convert a max of 32 bytes of
hex to 16 bytes of binary) is doable several simple ways:

/* C; Assumes hex digits always valid, in pairs and little-endian */

void hex32tobin16(char *hex, unsigned char *binkey)
{
int i;
memset(binkey, 0, 16);
char digs[]="0123456789abcdef";
for (i=0; i<16 && hex[i*2]; i++)
binkey = strchr(digs, tolower(hex[i*2]))<<4 +
strchr(digs, tolower(hex[i*2+1]));

^
I forgot parens here
v
binkey = (strchr(digs, tolower(hex[i*2]))<<4) +
strchr(digs, tolower(hex[i*2+1]));
}

/* C; Assumes hex digits always valid, in pairs */

void hex32tobin16(char *hex, unsigned char *binkey)
{
int v, i, j;
memset(binkey, 0, 16);
for (i=0, j=0; i<32 && hex; i+=2) {
sscanf(hex+i, "%2x", &v);
binkey[j++] = (unsigned char)v;
}
}

/* C; Assumes hex digits always valid, in pairs, little-endian */
/* Also assumes ASCII order (0-9...A-F...a-f) */

#define xtob(c) (((c)<=9)?((c)-'0'):(((c)<='F')?((c)-'A'):((c)-'a')));

^
Forgot +10 here
v
#define xtob(c) (((c)<=9)?((c)-'0'):((((c)<='F')?((c)-'A'):((c)-'a'))+10));
void hex32tobin16(char *hex, unsigned char *binkey)
{
int i
memset(binkey, 0, 16);
for (i=0; i<32; i+=2)
binkey[i>>1] = (xtob(hex) << 4) + xtob(hex[i+1]);
}


Sorry, I was sleepy.

Here's my favorite, that makes damn nearly every assumption about the
architecture possible, and assumes hexkey is always exacly 32
characters. It is horrible code:

#define hex32tobin16(h,b) \
(sscanf((h),"%4x%4x%4x%4x".(b),(b)+4,(b)+8,(b)+12)

I'm not quite sure why you think there should be some built-in
function to convert 32-byte hex valies to 16 binary bytes?
 
S

Severian

The one that Martin provided was using Win32 facilities and not .NET ones.

If the OP really is looking for .NET stuff, perhaps he should have a
look at Byte.Parse.
 
F

Fred Hebert

I'm not quite sure why you think there should be some built-in
function to convert 32-byte hex valies to 16 binary bytes?

This thing has really gotten blown out of proportion, but...

The reason I think this should be a standard function is that it is a
very common function in my world. Converting arbitrary length hex
strings to their binary equivalent and back is something I do ever day.
Wether it's an encryption key, 80 char line of code in a Motorola S file,
checksum from a serial communications session, hex dump for the e-prom
programmer, etc.

Yes the checksum is usually a 16 bit or 32 bit integer, so why use
HexToBin? Well it is also usually not an Intel integer and the normal
integer conversions don't work.

By the way, I found a similar function that is supposed to be part of
some "security" library, but the docks are fuzzy and it doesn't appear to
be installed on my system.

This is just one example. In my "standard library" of string handling
routines I am used to having hundreds of formatting and conversion
routines. Now I find myself rewriting InitialCaps routines. One of my
programmers who I asked to help with some of this got frustrated and
actually derived his own "String" class. I think that was a bad idea.
It did solve an immediate problem, but I can see it biting us big time
later. Also I think he just copied some of the Borland source because
he's just not that fast, so I told him to get rid of it...

Please don't take my comments personally (unless you are the one at
Microsoft who decided to not include these routines, or created the help
text). I appreciate the help and code fragments. They were useful if
only to see a .NET approach to the problem.

My comment about "probably an excellent programmer" was sincere, and I
was able to deduce what was meant, even with a few typos. Do you think I
have never made a typo?

I guess it is really hard to appreciate my perspective, if you don't
write the type of programs I write, and have never used these other
environments. Before .NET we had cross platform Windows/Linux, and mixed
language GNU C++, Borland C++ and Borland Delphi, Borland Kylix. There
are annoying things in my environment too, but I guess I am just used to
them.

If we wish to transition to .NET it is going to be difficult, and I am
really surprised at how many things are missing from what I think should
be the standard library. The other thing I am surprised about is poor
performance. This may not be noticeable to the typical user, but when
you are talking to devices and millisecond timing is important it is an
issue.

As I stated in one of my other messages .NET may not be right for us. I
looked at the standard MSC/MFC and it is worse as far as trying to
convert existing code.

Before this experience I thought that the differences between Microsoft
and Borland were more like the differences between Ford and Chevrolet.
That is 6 of one or half a dozen of the other, and it mostly came down to
user preference. Now I see the difference is much more dramatic.

I have been using the Delphi .NET stuff to try to become more familiar
with the environment. This is helping, but for most of the .NET stuff
they just use the Microsoft help, which I think is the biggest problem.

I mean it would be a lot easier with better docs. I have ordered a few
books suggested by others and am hoping this will also help.

In final summation, IMHO:

- The documentation sucks.
- A lot of basic functions are missing. I am digging up my old code and
creating our own addendum to the standard library just like in the old
days.
- I will eventually become accustomed to the syntax.
- I will survive...
 
T

Tim Robinson

Fred Hebert said:
In final summation, IMHO:

- The documentation sucks.

Agreed. However, Microsoft Visual C++ (mostly) conforms to the C++ standard,
so plenty of other people have written better documentation.
- A lot of basic functions are missing. I am digging up my old code and
creating our own addendum to the standard library just like in the old
days.

Your standard library != The Standard Library.
- I will eventually become accustomed to the syntax.
- I will survive...

You've been spoiled on Borland C++. They included a stack of non-standard
functions. VC++ basically conforms to the C++ standard, and includes a
couple of non-standard functions (their names start with an _). However,
when moving to a new compiler, you can't assume the existence of anything
except the C++ Standard Library.

HexToBin is very much a non-standard, Borland-Special function. If you want
that, stick to Borland. If you want to move compilers, then feel free to,
but don't assume you'll retain anything that's not standard.
 

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

Top