I have a string like '10011011001', And I wish to convert this string into Hex string, what is the best way to do that.
The OP clarified that the input string's length is <= 32. Then the problem becomes simpler.
There are many possible solutions. One of them is this:
function BinStrToHex32(const S: string): string;
begin
var LValue: UInt32 := 0;
for var i := 1 to S.Length do
case S[i] of
'0', '1':
LValue := LValue shl 1 or Ord(S[i] = '1');
else
raise Exception.CreateFmt('Invalid binary number: %s', [S]);
end;
Result := IntToHex(LValue);
end;
which IMHO is quite readable and performs some validation. (For bonus points, you can add overflow checking.)
If there were no restriction to the input string length, then I'd do something like this:
function BinStrToHexStr(const S: string): string;
const
HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
begin
if S.Length mod 8 <> 0 then
raise Exception.Create('Invalid binary string.');
SetLength(Result, S.Length div 4);
var LNibble: Byte := 0;
var c := 0;
for var i := 1 to S.Length do
begin
LNibble := LNibble shl 1 or Ord(S[i] = '1');
if i mod 4 = 0 then
begin
Inc(c);
Result[c] := HexDigits[LNibble];
LNibble := 0;
end;
end;
end;
I have this simple operation in Java, where the string is split by new line and break.
String i= "Holidays
Great.
Bye";
String []linesArray = i.split("\\r?\\n");
I would like to obtain the same result in Delphi 2006.
Is it valid to use the following steps?
charArray[0] := '\\r';
charArray[1] := '\\n';
strArray := strA.Split(charArray);
I interpret your request like this: "Split a string at both CR and LF." which implies that CR+LF gives an empty string element. For instance, 'alpha'#13'beta'#10'gamma'#13#10'delta' yields the five elements 'alpha', 'beta', 'gamma', '', and 'delta'.
If so, and if you are using a non-ancient version of Delphi, this is really simple:
var S := 'alpha'#13'beta'#10'gamma'#13#10'delta';
var Parts := S.Split([#13, #10]);
for var Part in Parts do
ShowMessage(Part);
For old Delphi versions
The code above requires TStringHelper (crucially) and also makes use of inline variable declarations, for in loops, and generics.
For old Delphi versions, you can do it manually:
type
TStringArray = array of string;
function Split(const S: string): TStringArray;
var
Count: Integer;
const
Delta = 512;
procedure Add(const Part: string);
begin
if Length(Result) = Count then
SetLength(Result, Length(Result) + Delta);
Result[Count] := Part;
Inc(Count);
end;
var
p, i: Integer;
begin
Result := nil;
Count := 0;
p := 0; // previous delim
for i := 1 to Length(S) do
if S[i] in [#13, #10] then
begin
Add(Copy(S, Succ(p), i - p - 1));
p := i;
end;
Add(Copy(S, Succ(p)));
SetLength(Result, Count);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
S: string;
Parts: TStringArray;
i: Integer;
begin
S := 'alpha'#13'beta'#10'gamma'#13#10'delta';
Parts := Split(S);
for i := 0 to High(Parts) do
ShowMessage(Parts[i]);
end;
This question already has answers here:
Converting decimal/integer to binary - how and why it works the way it does?
(6 answers)
Closed 4 years ago.
I have done some Example to convert a string to binary but i couldn't find a way to walk on each character in the string and complete the whole calculations process and then step to the next character in the string, Here is my code:
var i,j, rest, results :integer;
restResult : string;
begin
results := 1;
for i := 1 to length(stringValue) do
begin
while (results > 0) do
begin
results := ord(stringValue[i]) div 2;
rest := ord(stringValue[i]) mod 2;
restResult := restResult + inttostr(rest);
end;
end;
// Get The Rests Backwards
for i := length(restResult) downto 1 do
begin
result := result + restResult[i];
end;
The application always get into infinite loop, any suggestions?
Your results := ord(stringValue[i]) div 2; remains the same, because stringValue[i] does not change, so while loop is infinite.
To solve this mistake:
for i := 1 to length(stringValue) do
begin
t := ord(stringValue[i]);
repeat
restResult := restResult + inttostr(t mod 2);
t := t div 2;
until t = 0;
end;
But note that you cannot divide resulting string into pieces for distinct chars, because length of binary representation will vary depending on char itself.
This is example of code with fixed length for representation of char (here AnsiChar):
function AnsiStringToBinaryString(const s: AnsiString): String;
const
SBits: array[0..1] of string = ('0', '1');
var
i, k, t: Integer;
schar: string;
begin
Result := '';
for i := 1 to Length(s) do begin
t := Ord(s[i]);
schar := '';
for k := 1 to 8 * SizeOf(AnsiChar) do begin
schar := SBits[t mod 2] + schar;
t := t div 2
end;
Result := Result + schar;
end;
end;
'#A z': (division bars are mine)
01000000|01000001|00100000|01111010
# A space z
function AddNumStrings (Str1, Str2 : string): string;
var
i : integer;
carryStr : string;
worker : integer;
workerStr,s : string;
begin
Result := inttostr (length(Str1));
Result := '';
carryStr := '0';
// make numbers the same length
s:=StringofChar('0',Length(Str1)-1);
Str2:=s+Str2;
i := 0;
while i < length(Str1) do
begin
worker := strtoint(copy(Str1, length(str1)-i, 1)) +
strtoint(copy(Str2, length(str2)-i, 1)) +
strtoint (carryStr);
if worker > 9 then
begin
workerStr := inttostr(worker);
carryStr := copy(workerStr, 1, 1);
result := copy(workerStr, 2, 1) + result;
end
else
begin
result := inttostr(worker) + result;
carryStr := '0';
end;
inc(i);
end; { while }
if carryStr <> '0' then
result := carryStr + result;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
s,z:String;
begin
s:='1000';
repeat
s:=AddNumStrings(s,'1');
until
Length(s)=1000;
ShowMessage(s);
end;
end.
But this codes takes too time. Is there any options to fastest way for my codes?
I m working huge number so I have to write "Inc()" procedure manually for huge number billion digits. I know what you think about it bu I have to do it. Thank you..
INT128 lib for FPC
GNURZ lib (for FPC but should be compatible with Delphi)
GMP (FPC supports it, Delphi also)
BigInt and BigFloat
BigInt Delphi Library
Another BigInt
TPMath
DeHL for Delphi
BigNumbers BigInteger, BigDecimal and BigRational for Delphi
Hopefully one of those will be faster...
I have a problem with a Delphi 7 string-decoder function ("Decrypt") I found online. It takes a string and four numeric values between 1 and 120 to decode it. Putting the function within an executable and running it works great. However, I want to run this within a DLL. I'm using an extra function to receive the necessary values from the calling task and call the decrypt function from there. For some reason I can't put my finger on, the host app crashes every time the dll calls the decrypt-function. For the last few hours I have been trying everything I could come up with to get this to work, but without success. I'm new to Delphi and Pascal in general, so may be I just overlooked something obvious. Either way, I'm lost. Any help would be greatly appreciated.
Edit: Here's the windows error that pops up upon crash:
Fault Module Name: StackHash_0a9e
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 00000000
Exception Code: c0000005
Exception Offset: 00000000
OS Version: 6.1.7600.2.0.0.256.1
Locale ID: 1031
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
Here's the code that I use:
library decrypt_test_dll;
uses
SysUtils,
Classes,
Dialogs;
{$R *.res}
function callfunction(externalstring, value1, value2, value3, value4: PAnsiChar):integer; cdecl;
var
convkey1, convkey2, convkey3, convkey4 : string;
convstring, decodedstring : string;
Decrypt : function(Text : string; Key1, Key2, Key3, Key4 : Integer) : string;
begin
convkey1 := value1;
convkey2 := value2;
convkey3 := value3;
convkey4 := value4;
convstring := externalstring;
decodedstring := Decrypt(externalstring, strtoint(convkey1), strtoint(convkey2), strtoint(convkey3), strtoint(convkey4));
showmessage(decodedstring);
end;
function Decrypt(Text : string; Key1, Key2, Key3, Key4 : Integer) : string;
var
BufS, Hexa1, Hexa2 : string;
BufI, BufI2, Divzr, Sc, Sl, Num1, Num2, Num3, Num4, Res1, Res2, Res3, Res4 : Integer;
begin
showmessage('within decryption function');
Sl := Length(Text);
Sc := 0;
BufS := '';
if (Key1 in [1 .. 120]) and (Key2 in [1 .. 120]) and (Key3 in [1 .. 120]) and (Key4 in [1 .. 120]) then
begin
Divzr := Key1 * Key4;
BufI2 := Key3 * Key2;
Divzr := Divzr - BufI2;
if Divzr = 0 then
begin
Result := '';
Exit;
end;
end
else
begin
Result := '';
Exit;
end;
repeat
for BufI := 1 to 4 do
begin
Inc(Sc);
Hexa1 := IntToHex(Ord(Text[Sc]), 2);
Inc(Sc);
Hexa2 := IntToHex(Ord(Text[Sc]), 2);
if Hexa1 = 'FF' then
begin
Hexa1 := '00';
Hexa2 := '00';
end;
if Hexa1 = 'FE' then Hexa1 := '00';
if Hexa1 = 'FD' then
begin
Hexa1 := Hexa2;
Hexa2 := '00';
end;
case BufI of
1 : Res1 := StrToInt('$' + Hexa1 + Hexa2);
2 : Res2 := StrToInt('$' + Hexa1 + Hexa2);
3 : Res3 := StrToInt('$' + Hexa1 + Hexa2);
4 : Res4 := StrToInt('$' + Hexa1 + Hexa2);
end;
end;
BufI := Res1 * Key4;
BufI2 := Res2 * Key3;
Num1 := BufI - BufI2;
Num1 := Num1 div Divzr;
BufI := Res2 * Key1;
BufI2 := Res1 * Key2;
Num2 := BufI - BufI2;
Num2 := Num2 div Divzr;
BufI := Res3 * Key4;
BufI2 := Res4 * Key3;
Num3 := BufI - BufI2;
Num3 := Num3 div Divzr;
BufI := Res4 * Key1;
BufI2 := Res3 * Key2;
Num4 := BufI - BufI2;
Num4 := Num4 div Divzr;
BufS := BufS + Chr(Num1) + Chr(Num2) + Chr(Num3) + Chr(Num4);
until Sc >= Sl;
Result := BufS;
end;
exports
Decrypt index 1,
callfunction index 2;
begin
end.
This code is all wrong:
function callfunction(externalstring, value1, value2, value3, value4: PAnsiChar):integer; cdecl;
var
convkey1, convkey2, convkey3, convkey4 : string;
convstring, decodedstring : string;
Decrypt : function(Text : string; Key1, Key2, Key3, Key4 : Integer) : string;
begin
convkey1 := value1;
convkey2 := value2;
convkey3 := value3;
convkey4 := value4;
convstring := externalstring;
decodedstring := Decrypt(externalstring, strtoint(convkey1), strtoint(convkey2), strtoint(convkey3), strtoint(convkey4));
showmessage(decodedstring);
end;
The local variable Decrypt is never assigned to. So when you call Decrypt, anything can happen. You need to move callfunction to the bottom of the unit so that it appears after the real Decrypt. And you need to remove the function pointer variable.
function callfunction(externalstring, value1, value2, value3, value4: PAnsiChar):integer; cdecl;
var
convkey1, convkey2, convkey3, convkey4 : string;
convstring, decodedstring : string;
begin
convkey1 := value1;
convkey2 := value2;
convkey3 := value3;
convkey4 := value4;
convstring := externalstring;
decodedstring := Decrypt(externalstring, strtoint(convkey1), strtoint(convkey2), strtoint(convkey3), strtoint(convkey4));
showmessage(decodedstring);
end;
You also should not use string as a parameter (or indeed a return value) in an exported DLL function. It's not a valid type for interop since it relies on both sides of the interface using the same string implementation, and the same memory manager. You need to find a different way to define the Decrypt interface, if you are going to export it. Or possibly you should not be exporting that function at all. Impossible for me to know with any certainty. My guess is that you are actually calling callfunction rather than Decrypt from the calling code. Anyway, in its current state, you must not export Decrypt.
One other point to make. When you ask a question that involves a module interface, you should always show both sides of the interface. Here you have shown the DLL, but not the code that calls into the DLL. The error could be there. Indeed, there could be an error there in addition to the errors I have pointed out.
If the string manipulation code works as shown in an exe but not from a DLL check that the DLL has the delphi memory manager as the FIRST uses item.
uses
ShareMem
This is implicitt in a Dephi exe, but not in its DLLs.
This is always a favorite problem with Delphi 6 DLLs and strings, cant say if its still applicable in Delphi 7 however!