www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - read Hexadecimal value from string

reply Gilles G. <schaouette free.fr> writes:
Hello,
I try to read hexadecimal values from a file.
I tryed to use toInt, for example:
auto i = toInt("C");
but this doesn't work.
What is the method to read hexadecimal value?

Thanks.
Jul 17 2007
next sibling parent Regan Heath <regan netmail.co.nz> writes:
Gilles G. wrote:
 Hello,
 I try to read hexadecimal values from a file.
 I tryed to use toInt, for example:
 auto i = toInt("C");
 but this doesn't work.
 What is the method to read hexadecimal value?
 
 Thanks.

Oddly, std.conv doesn't have a routine for it, as far as I am aware. Here's how I would do it. /* http://www.opensource.org/licenses/cpl1.0.php */ import std.string, std.stdio; import std.c.stdlib; long hexToLong(string s) { long v = strtoul(toStringz(s), null, 16); if (getErrno() == ERANGE) throw new Exception("Out of range"); return v; } void main() { writefln("%d",hexToLong("0xC")); }
Jul 17 2007
prev sibling next sibling parent David L. Davis <SpottedTiger yahoo.com> writes:
Gilles G. Wrote:

 Hello,
 I try to read hexadecimal values from a file.
 I tryed to use toInt, for example:
 auto i = toInt("C");
 but this doesn't work.
 What is the method to read hexadecimal value?
 
 Thanks.

Hi Gilles, You're welcome to used some D code I wrote that's Public Domain listed below: /+ ' Module : hexconv.d ' Author : David L. 'SpottedTiger' Davis ' Tested : dmd v2.002 (WinXP OS/ Intel CPU) ' Licence : Public Domain / Contributed to Digital Mars ' ===================================================== ' To complie for a unittest: ' dmd hexconv.d -debug=hexconv -unittest ' ' To compile a D program that uses hexconv.d: ' dmd MySource.d hexconv.d +/ module hexconv; debug( hexconv ) private import std.stdio; // Function : xtoul() - Hex string to an unsigned decimal whole number // Author : David 'SpottedTiger' L. Davis // Created : 03.May.05 // CPU : Intel x86 (Numercials stored as "Low byte to High byte") // Last Test: dmd v2.002 // ---------------------------------------- // Converts a Hex string from 0x0 to 0xFFFFFFFFFFFFFF // into a ulong value 0 to 18,446,744,073,709,551,615 // also it handles the lowercase 'a' thru 'f'. ulong xtoul(string sx) { ulong ul = 0L; int j = 7; char c, c1, c2; char[] st = cast(char[])sx; int len = st.length; const char[] zeros = "0000000000000000"c; union u { ulong ul; char[8] c; } u U; if (len == 0 || len > 16) throw new Exception( "xtoul() the string parameter is either an empty string,"c ~ " or its length is greater than 16 characters."c ); // isHex() for (int i = 0; i < st.length; i++) { //c = ( sx[i] > 'F' ? sx[i] - 32 : sx[i] ); c = st[i]; if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) continue; else throw new Exception("xtoul() invalid hex character used."c); } if (len < 16) st = zeros[0..16 - len] ~ st; j = 7; for (int i = 0; i < 16; i += 2) { c1 = (st[i] > 'F' ? st[i] - 32 : st[i]); c2 = (st[i + 1] > 'F' ? st[i + 1] - 32 : st[i + 1]); c1 = cast(int)(c1 > 52 ? c1 - 55 : c1 - 48) << 4; U.c[j--] = c1 + cast(int)(c2 > 52 ? c2 - 55 : c2 - 48); } return U.ul; } unittest { debug( hexconv ) writefln( "hexconv.xtoul( string ).unittest"c ); ulong ul; ul = xtoul("0"c); assert( ul == 0x0 ); ul = xtoul("FF"c); assert( ul == 0xFF ); ul = xtoul("eea"c); assert( ul == 0xEEA ); ul = xtoul("AB"c); assert( ul == 0xAB ); ul = xtoul("ABCD"c); assert( ul == 0xABCD ); ul = xtoul("A12CD00"c); assert( ul == 0xA12CD00 ); ul = xtoul("FFFFFFFFFFFFFFFF"c); assert( ul == 0xFFFFFFFFFFFFFFFF ); } // Function : ultox() - Decimal unsigned whole number to Hex string // Author : David 'SpottedTiger' L. Davis // Created : 04.May.05 // CPU : Intel x86 (Numercials stored as "Low byte to High byte") // Last Test: dmd v2.002 // ----------------------------------------- // Accepts any positive number from 0 to 18,446,744,073,709,551,615 // and the returns an even number of hex strings up to 16 characters // (from 0x0 to 0xFFFFFFFFFFFFFF). string ultox(in ulong ul) { char[16] sx; char c1, c2; union u { ulong ul; char[8] c; } int i = 0, j = 0, k = 0; bit z = true; u U; U.ul = ul; for (i = 7; i >= 0; i--) { c1 = U.c[i] >> 4; c1 = cast(char)(c1 > 9 ? c1 + 55 : c1 + 48); c2 = U.c[i] & 0x0F; c2 = cast(char)(c2 > 9 ? c2 + 55 : c2 + 48); if (z && c1 == '0' && c2 == '0') continue; z = false; sx[j++] = c1; sx[j++] = c2; } if (j > 0) //Copying a fixed array into a dynamic array, must COW. return sx[0..j].dup; else return "00"c; } unittest { debug( hexconv ) writefln( "hexconv.ultox( in ulong ).unittest"c ); string sx; sx = ultox(0); //0x0 assert( sx == "00"c ); sx = ultox(255); //0xFF assert( sx == "FF"c ); sx = ultox(171); //0xAB assert( sx == "AB"c ); sx = ultox(43981); //0xABCD assert( sx == "ABCD"c ); sx = ultox(169004288); //0xA12CD00 assert( sx == "0A12CD00"c ); sx = ultox(0xA12CD00); //169004288 assert( sx == "0A12CD00"c ); sx = ultox(ulong.max); //0xFFFFFFFFFFFFFFFF assert( sx == "FFFFFFFFFFFFFFFF"c ); } bool isHex(string sx) { char c; for (int i = 0; i < sx.length; i++) { c = sx[i]; if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) continue; else return false; } return true; } unittest { debug( hexconv ) writefln( "hexconv.isHex( string ).unittest"c ); assert( isHex("00"c) ); assert( isHex("FF"c) ); assert( isHex("Ffae0"c) ); assert( isHex("AB"c) ); assert( isHex("abdef"c) ); assert( isHex("ABCD"c) ); assert( isHex("0A12CD00"c) ); assert( isHex("FFFFFFFFFFFFFFFF"c) ); assert( isHex("00ER"c) == false ); assert( !isHex("0xW"c) ); } debug( hexconv ) { int main() { auto i = xtoul("C"); writefln("i=%d, xtoul(\"C\")=%d, ultox(i)=\"%s\"", i, xtoul("C"), ultox(i)); writefln( "unittest done"c ); return 0; } } Best Regards, David L. Davis
Jul 17 2007
prev sibling parent reply Frank Benoit <keinfarbton googlemail.com> writes:
When using Tango, this can be done like this:

import tango.text.convert.Integer;
int  i = toInt( "12AB", 16 );
long l = toLong( "ffffFFFFAAAA", 16 );

see also:
http://www.dsource.org/projects/tango/wiki/ChapterConversions
and the source at
http://www.dsource.org/projects/tango/browser/trunk/tango/text/convert/Integer.d

Frank
Jul 17 2007
parent reply David L. Davis <SpottedTiger yahoo.com> writes:
Frank Benoit Wrote:

 When using Tango, this can be done like this:
 
 import tango.text.convert.Integer;
 int  i = toInt( "12AB", 16 );
 long l = toLong( "ffffFFFFAAAA", 16 );
 
 see also:
 http://www.dsource.org/projects/tango/wiki/ChapterConversions
 and the source at
 http://www.dsource.org/projects/tango/browser/trunk/tango/text/convert/Integer.d
 
 Frank

Yep, Tango has some very kool functions. But I do want to point out that Phobos does have a radix parameter in the toString functions for converting a number to a string...sadly not the other way around. Here's an example: // Using Phobos you can convert a long or a ulong value, // using any base from 2 to 36 into a string private import ss = std.string; private import io = std.stdio; void main() { auto s = ss.toString(12uL, 16u); io.writefln("ss.toString(12uL, 16u)=\"%s\"", s); } /+ Output: C:\dmd>dmd strex1.d C:\dmd\bin\..\..\dm\bin\link.exe strex1,,,user32+kernel32/noi; C:\dmd>strex1 ss.toString(12uL, 16u)="C" C:\dmd> +/ David L. Davis
Jul 17 2007
parent reply BCS <ao pathlink.com> writes:
Reply to David,

 Yep, Tango has some very kool functions. But I do want to point out
 that Phobos does have a radix parameter in the toString functions for
 converting a number to a string...sadly not the other way around.
 

OK, brute force it is ;-b |T fromString(T)(char[] str, uint r) |{ | T v = T.min; | goto start; | do | { | v++; | start: | if(toString(v,r) == str) return v; | }while(v != T.max); |} (bonus points if you can find more than three things to object to.)
Jul 17 2007
next sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
BCS wrote:
 Reply to David,
 
 Yep, Tango has some very kool functions. But I do want to point out
 that Phobos does have a radix parameter in the toString functions for
 converting a number to a string...sadly not the other way around.

OK, brute force it is ;-b |T fromString(T)(char[] str, uint r) |{ | T v = T.min; | goto start; | do | { | v++; | start: | if(toString(v,r) == str) return v; | }while(v != T.max); |}

:P
 (bonus points if you can find more than three things to object to.)

Without actually compiling that, I'll list some objections: 1) Let's get this one out of the way first: it's brute force. I mean, come on! 2) Since toString outputs uppercase characters (for digits > 9), this doesn't work for strings containing lowercase characters as digits. 3) It generates a lot of heap activity for anything that doesn't happen to be close to T.min (one string per iteration). Probably especially problematic for applications with small signed numbers or big numbers. This will probably mean lots of GC cycles. Arguably a symptom of (1). 4) It doesn't allow a redundant '+' at the start :P. 5) It appears from the Phobos source that toString(long value, uint radix) doesn't properly handle negative numbers when radix != 10. Though I guess that's a Phobos issue, not an issue in your code this cause the return value (if any[1]) answer given to be negative for T == long. After compiling (and verifying all above issues): 6) Doesn't compile for T other than long or ulong due to overload resolution issues (those are the only two types toString(T, uint radix) is defined for). 7) Very bad error checking. Out-of-range or plain invalid input (and input triggering (2), (4) and/or (5)) results in a failed assertion at the end of the function due to no return statement being executed. And if compiled in release mode it segfaults (executing a 'hlt' instruction put there by the implicit assert(0) at the end of the function). Did I miss anything? [1]: Due to some of the other issues, control may reach the end of the function without returning anything.
Jul 17 2007
parent BCS <ao pathlink.com> writes:
Reply to Frits,

 BCS wrote:
 
 Reply to David,
 
 Yep, Tango has some very kool functions. But I do want to point out
 that Phobos does have a radix parameter in the toString functions
 for converting a number to a string...sadly not the other way
 around.
 

|T fromString(T)(char[] str, uint r) |{ | T v = T.min; | goto start; | do | { | v++; | start: | if(toString(v,r) == str) return v; | }while(v != T.max); |}

 (bonus points if you can find more than three things to object to.)
 

1) Let's get this one out of the way first: it's brute force. I mean, come on!

i++
 2) Since toString outputs uppercase characters (for digits > 9), this
 doesn't work for strings containing lowercase characters as digits.

i++
 3) It generates a lot of heap activity for anything that doesn't
 happen
 to be close to T.min (one string per iteration). Probably especially
 problematic for applications with small signed numbers or big numbers.
 This will probably mean lots of GC cycles. 

 Arguably a symptom of (1).

i += 0
 4) It doesn't allow a redundant '+' at the start :P.

i++
 5) It appears from the Phobos source that toString(long value, uint
 radix) doesn't properly handle negative numbers when radix != 10.
 Though

 I guess that's a Phobos issue, not an issue in your code this cause
 the return value (if any[1]) answer given to be negative for T == long.
 After compiling (and verifying all above issues):

i+=0
 6) Doesn't compile for T other than long or ulong due to overload
 resolution issues (those are the only two types toString(T, uint
 radix)
 is defined for).

 7) Very bad error checking. Out-of-range or plain invalid input (and
 input triggering (2), (4) and/or (5)) results in a failed assertion at
 the end of the function due to no return statement being executed. And
 if compiled in release mode it segfaults (executing a 'hlt'
 instruction
 put there by the implicit assert(0) at the end of the function).

i += ulong.max i>3 => bonus points <g>
 Did I miss anything?
 

goto!!!
 [1]: Due to some of the other issues, control may reach the end of the
 function without returning anything.
 

Jul 17 2007
prev sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
BCS wrote:
 Reply to David,
 
 Yep, Tango has some very kool functions. But I do want to point out
 that Phobos does have a radix parameter in the toString functions for
 converting a number to a string...sadly not the other way around.

OK, brute force it is ;-b |T fromString(T)(char[] str, uint r) |{ | T v = T.min; | goto start; | do | { | v++; | start: | if(toString(v,r) == str) return v; | }while(v != T.max); |} (bonus points if you can find more than three things to object to.)

1. Using a for loop would be much clearer. 2. Using a goto is generally frowned upon; local gotos, though, especially in such simple cases, are usually readable. However, most programmers react viscerally to gotos. It is recommended that you avoid them unless you want your viscera removed. 3. In general, you shouldn't use != for loop boundaries unless *all* possible values other than that single value is still valid for the guts of the loop. If you were to refactor and make v into a real for all cases, for instance, you'd do a lot more work than necessary. 4. There is not guaranteed to be a toString(T, uint) method. T is not guaranteed to have increment and decrement overloads. On the plus side, this executes in constant time and is a good example of code reuse. For this, though, I think I'd use annealing. It's probably a bit faster, especially if I had several annealings executing in parallel.
Jul 17 2007
parent BCS <BCS pathlink.com> writes:
Christopher Wright wrote:
 BCS wrote:
 
 Reply to David,

 Yep, Tango has some very kool functions. But I do want to point out
 that Phobos does have a radix parameter in the toString functions for
 converting a number to a string...sadly not the other way around.

OK, brute force it is ;-b |T fromString(T)(char[] str, uint r) |{ | T v = T.min; | goto start; | do | { | v++; | start: | if(toString(v,r) == str) return v; | }while(v != T.max); |} (bonus points if you can find more than three things to object to.)

1. Using a for loop would be much clearer.

i++
 2. Using a goto is generally frowned upon; local gotos, though, 
 especially in such simple cases, are usually readable. However, most 
 programmers react viscerally to gotos. It is recommended that you avoid 
 them unless you want your viscera removed.

i++ //AAAaahh!!! ;)
 3. In general, you shouldn't use != for loop boundaries unless *all* 
 possible values other than that single value is still valid for the guts 
 of the loop. If you were to refactor and make v into a real for all 
 cases, for instance, you'd do a lot more work than necessary.

 4. There is not guaranteed to be a toString(T, uint) method. T is not 
 guaranteed to have increment and decrement overloads.
 

 On the plus side, this executes in constant time and is a good example 
 of code reuse.
 
 For this, though, I think I'd use annealing. It's probably a bit faster, 
 especially if I had several annealings executing in parallel.

i-= large_number // that's even worse then mine!! //nice breakdown (bonus points to you)
Jul 18 2007