Reputation: 900
Hello everybody,
I have a small code in PHP that I would like to convert in Delphi and I have some troubles...
Here is the PHP code :
$from = "121.198.0.0";
$to = "121.198.255.255";
$arry1 = explode(".", $from);
$arry2 = explode(".", $to);
$a1 = $arry1[0];
$b1 = $arry1[1];
$c1 = $arry1[2];
$d1 = $arry1[3];
$a2 = $arry2[0];
$b2 = $arry2[1];
$c2 = $arry2[2];
$d2 = $arry2[3];
while ($d2 >= $d1 || $c2 > $c1 || $b2 > $b1 || $a2 > $a1) {
if ($d1 > 255) {
$d1 = 1;
$c1++;
}
if ($c1 > 255) {
$c1 = 1;
$b1++;
}
if ($b1 > 255) {
$b1 = 1;
$a1++;
}
echo "$a1.$b1.$c1.$d1<br>";
$d1++;
}
And in Delphi I started with that :
procedure TForm1.Button1Click(Sender: TObject);
var
Arry1, Arry2: TStringList;
RangeFrom, RangeTo: string;
a1, b1, c1, d1, a2, b2, c2, d2: string;
begin
RangeFrom := Edit1.Text;
RangeTo := Edit2.Text;
Arry1 := Explode('.', RangeFrom);
Arry2 := Explode('.', RangeTo);
a1 := Arry1[0];
b1 := Arry1[1];
c1 := Arry1[2];
d1 := Arry1[3];
a2 := Arry1[0];
b2 := Arry1[1];
c2 := Arry1[2];
d2 := Arry1[3];
while (StrToInt(d2) >= StrToInt(d1))
//and StrToInt(c2) > (StrToInt(c1)
//and StrToInt(b2) > (StrToInt(b1)
//and StrToInt(a2) > (StrToInt(a1)
do
begin
if (StrToInt(d1) > 255) then
begin
d1 := '1';
StrToInt(c1)+1;
end;
if (StrToInt(c1) > 255) then
begin
c1 := '1';
StrToInt(b1)+1;
end;
if (StrToInt(b1) > 255) then
begin
b1 := '1';
StrToInt(a1)+1;
end;
ListBox1.Items.Add(a1+'.'+b1+'.'+c1+'.'+d1);
StrToInt(d1)+1;
end;
end;
(For the Explode function, I use : http://www.marcosdellantonio.net/2007/06/14/funcao-explode-do-php-em-delphi/)
Someone can help me to make working this small code in Delphi ?
Thanks in advance :)
Beny
Upvotes: 2
Views: 900
Reputation: 1336
Testing the goal:
procedure TForm1.Button1Click(Sender: TObject);
var
AddrList: TStringList;
StartAddress,
EndAddress: Cardinal;
a, b, c, d: PByte;
x: Cardinal;
begin
AddrList := TStringList.Create;
AddrList.Delimiter := '.';
AddrList.DelimitedText := Edit1.Text;
StartAddress := (Cardinal(StrToInt(AddrList.Strings[0])) shl 24 ) +
(Cardinal(StrToInt(AddrList.Strings[1])) shl 16) +
(Cardinal(StrToInt(AddrList.Strings[2])) shl 8) +
StrToInt(AddrList.Strings[3]);
AddrList.DelimitedText := Edit2.Text;
EndAddress := (Cardinal(StrToInt(AddrList.Strings[0])) shl 24 ) +
(Cardinal(StrToInt(AddrList.Strings[1])) shl 16) +
(Cardinal(StrToInt(AddrList.Strings[2])) shl 8) +
StrToInt(AddrList.Strings[3]);
AddrList.Free;
for x := StartAddress to EndAddress do begin
a := @x;
b := a;
Inc(a);
c := a;
Inc(a);
d := a;
Inc(a);
Memo1.Lines.Add(Format('%d.%d.%d.%d', [a^,d^,c^,b^]));
end;
end;
Upvotes: 0
Reputation: 613053
Here's what I can see just by looking at the code:
If think you have the parameters to Explode
in the wrong order. The separator is the second parameter in the function to which you linked. So you should write:
Arry1 := Explode(RangeFrom, '.');
Arry2 := Explode(RangeTo, '.');
You are leaking memory by not freeing the arrays returned by the Explode
function. Delphi is different from PHP in that you often have to manage the memory of objects that you create.
a2 := Arry1[0];
b2 := Arry1[1];
c2 := Arry1[2];
d2 := Arry1[3];
These should be Arry2
rather than Arry1
.
You should convert the strings to integers up front. So declare them like this:
a1, b1, c1, d1, a2, b2, c2, d2: Integer;
and write the assignments like this:
a1 := StrToInt(Arry1[0]);
b1 := StrToInt(Arry1[1]);
//etc. etc.
while ($d2 >= $d1 || $c2 > $c1 || $b2 > $b1 || $a2 > $a1)
translates to:
while ((d2 >= d1) or (c2 > c1) or (b2 > b1) or (a2 > a1))
Inside the while loop you want code like this:
if d1 > 255 then
begin
d1 := 1;
inc(c1);
end;
Converting the 4 values back to an IP address is easiest with the Format
function:
ListBox1.Items.Add(Format('%d.%d.%d.%d', [a1, b1, c1, d1]));
You have a mis-understanding of what StrToInt
does it is a function that receives as input a string and returns an integer. When you write:
StrToInt(d1)+1
you are not modifying the variable d1
which is just an input variable. That issue disappears when you make the other changes I describe, but I wanted to point it out for your future benefit.
You may also want to force a periodic repaint of the list box so that you can see what is happening.
Put it all together and you have this:
var
Arry1, Arry2: TStringList;
RangeFrom, RangeTo: string;
Count: Integer;
a1, b1, c1, d1, a2, b2, c2, d2: Integer;
begin
RangeFrom := Edit1.Text;
RangeTo := Edit2.Text;
Arry1 := Explode(RangeFrom, '.');
try
a1 := StrToInt(Arry1[0]);
b1 := StrToInt(Arry1[1]);
c1 := StrToInt(Arry1[2]);
d1 := StrToInt(Arry1[3]);
finally
Arry1.Free;
end;
Arry2 := Explode(RangeTo, '.');
try
a2 := StrToInt(Arry2[0]);
b2 := StrToInt(Arry2[1]);
c2 := StrToInt(Arry2[2]);
d2 := StrToInt(Arry2[3]);
finally
Arry2.Free;
end;
Count := 0;
while ((d2 >= d1) or (c2 > c1) or (b2 > b1) or (a2 > a1)) do
begin
if d1 > 255 then
begin
d1 := 1;
inc(c1);
end;
if c1 > 255 then
begin
c1 := 1;
inc(b1);
end;
if b1 > 255 then
begin
b1 := 1;
inc(a1);
end;
ListBox1.Items.Add(Format('%d.%d.%d.%d', [a1, b1, c1, d1]));
inc(Count);
if Count mod 1000=0 then begin
ListBox1.Repaint;
ListBox1.TopIndex := ListBox1.Items.Count-1;
end;
inc(d1);
end;
end;
Upvotes: 6
Reputation: 122
I think the reason it is not doing anything right now is you may not have any values in edit1.text or edit2.text.
For testing (before making this snippet a procedure or function) you could just assign some test data to RangeFrom and RangeTo.
Ex. RangeFrom := '121.198.0.0'; RangeTo := '121.198.255.255';
Upvotes: 0