Currently on this Super Star Destroyer being telekinetically strangled to death by Darth Vader
Posts
78
Some useful functions for you guys!
I have some useful code attached herein.
Somebody who just read it a few minutes ago called it sh%&^y, but, hey, I'm still a newbie. It converts a decimal string to a hexadecimal string, and vice versa. Perhaps you guys can help me clean it up a bit.
- Justin Patrick Butler
Comme je trouve. "As I find."
- Butler family quote
Beneficia sumptos procul superant. "The benefits far exceed the costs."
- Myself
hey its not too bad ... it is kind of sloppy but its a good start for a newbie.
its not really useful to other programmers though because there are standard libraries which contain those functions, but its great coding practice for you nonetheless. keep it up!
Actually there are no functions that do this highlife...
It's not bad (the formatting went to hell when you copied it to the textfile), here are some comments:
It is useless to copy the string to the "here" buffer. It only is a stability hazard (because a string can easily be longer than 128 characters) and wastes speed and memory.
The usual method to traverse a string is this:
for(char* p = str; *p; p++)
{
// (*p) is current character
}
Refer to charcters by their real look, the numbers are hard to read. Like: instead of 65, write 'A'. It means exactly the same but is far more readable.
hexs = 0; (or decs = 0
Not only does it not work (a change to a parameter value is not seen outside the function), it is a VERY bad idea too. What if the buffer passed to the function is allocated dynamically with malloc or new (or HeapAlloc or whatever)? Once it's a NULL pointer, the memory referred to would be lost! People would get very mad at you.
The loop in hextodec is inefficient. pow operates on floating point numbers and is slow. It is better to start at the beginning and do this:
Code:
int total = 0;
for(char *p = here; ishexdigit(*p); p++)
{
if(isdigit(*p))
temp = (*p) - '0';
else if(tolower(*p) >= 'a' && tolower(*p) <= 'f') // saves time
temp = tolower(*p) - 'a';
total <<= 4; // this is the same as "total *= 16;", but faster
total += temp;
}
Whenever this loop encounters a new character, it multiplies the current total with 16 (effectively shifting all hex digits left one position). Then it adds the new rightmost position.
Memory access is a little faster this way, and the loop body is WAY faster (could be even faster if a char variable temporarily holds the character at (*p), but a good compiler will optimize this disadvantage away)
All the buzzt CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
Currently on this Super Star Destroyer being telekinetically strangled to death by Darth Vader
Posts
78
CornedBee, this code just went way over my head. Is it possible you can make it a little simpler? It may make it less efficient, but I may be able to understand it.
- Justin Patrick Butler
Comme je trouve. "As I find."
- Butler family quote
Beneficia sumptos procul superant. "The benefits far exceed the costs."
- Myself
CornedBee's code simply loops through the string (the for loop). For each character, it checks to see what value it has (the two if statements), and converts a regular integer. It then multiplies the total by 16(total <<= 4 does this), and adds the value of the character to total.
int atoihex(char* str)
{
int total = 0; // the total sum
int temp; // the numerical value of the current character
// let i be the index to the first character (0)
// for each loop, check whether the character at position
// i is a hexadecimal digit using the
// ishexdigit macro defined in ctype.h
// then advance to the next character (increment i)
for(int i = 0; ishexdigit(str[i]); i++)
{
if(isdigit(str[i])) // if it is a digit ('0' to '9')
temp = str[i] - '0'; // get the numerical value by substracting
// the ASCII code of '0' from the character, this works because
// all numbers have adjacent places in the ASCII table
// if it is not a digit, check whether it is something between
// 'a' and 'f' or 'A' and 'F' (the letters allowed in hex digits)
// to make it case insensitive, convert every character to lowercase
// using the tolower macro from ctype.h
// if the character was uppercase it's converted, if not nothing
// happens
// if the result is within the range 'a' to 'f', enter the if block
else if(tolower(str[i]) >= 'a' && tolower(str[i]) <= 'f') // saves time
// I had an error here...
// again: get the numerical value by substracting the ASCII
// value of the first letter in the series, but because 'a' already
// means 10 in hex digits, add 10
temp = tolower(str[i]) - 'a' + 10;
// we just decoded another digit, that means that those we had
// before are at higher positions -> multiply them by 16 (the radix
// of hexadecimal numbers)
total *= 16;
// and add the new digit to the total
total += temp;
}
// return the result
return total;
}
Here is a scheme how this function works:
Code:
Let's say we pass this string to the function:
7d3A
First loop: character at position 0
7d3A
^
ishexdigit returns true, so execute the body:
isdigit returns true:
'7' - '0' (55 - 48) = 7, this value is stored in temp
multiply total with 16:
0 * 16 = 0
then add temp:
0 + 7 = 7
advance to the next character and repeat:
7d3A
^
ishexdigit: true
isdigit: false
the next if part: tolower returns 'd', which is both >= 'a' and <= 'f'
therefore, get the numerical value: 'd' - 'a' (100 - 97) + 10 = 13
then multiply: 7 * 16 = 112
and add: 112 + 13 = 125
next digit:
7d3A
^
ishexdigit: true
isdigit: true
'3' - '0' (51 - 48) = 3
125 * 16 = 2000
1664 + 3 = 2003
7d3A
^
ishexdigit: true
isdigit: false
tolower: 'a', if applies
'a' - 'a' (97 - 97) + 10 = 10
2003 * 16 = 32048
32048 + 10 = 32058
7d3A
^
ishexdigit: false
jump out of loop and return 32058
you can check that with windows calculator, it is right
All the buzzt CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
Currently on this Super Star Destroyer being telekinetically strangled to death by Darth Vader
Posts
78
Thank you so much CornedBee! I did include ctype.h in my program, but the compiler said I still had to define ishexdigit, but since, thanks to you, I understood it so well, it wasn't a problem!
the right name (the one defined in ctype.h) is isxdigit. You can use it or you can use yours. The one in ctype.h is faster because it uses a lookup table. It's only a memory address calculation and one & (AND) operation. Your code needs in worst case 8 comparisons.
All the buzzt CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.