Beny
Beny

Reputation: 900

Who can help me to convert this small PHP code to Delphi?

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

Answers (3)

Daniel Luyo
Daniel Luyo

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

David Heffernan
David Heffernan

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

Gary Mueller
Gary Mueller

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

Related Questions