Кто может помочь мне преобразовать этот небольшой PHP-код в Delphi?

Всем привет,

У меня есть небольшой код на PHP, который я хотел бы преобразовать в Delphi, и у меня есть некоторые проблемы …
Вот код PHP:

$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++; } 

И в Delphi я начал с этого:

 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; 

(Для функции Explode я использую: http://www.marcosdellantonio.net/2007/06/14/funcao-explode-do-php-em-delphi/ )

Кто-то может помочь мне сделать этот небольшой код в Delphi?

Заранее спасибо 🙂

Beny

Вот что я вижу, просто просматривая код:

Если вы думаете, что у вас есть параметры Explode в неправильном порядке. Сепаратор является вторым параметром в функции, с которой вы связаны. Поэтому вы должны написать:

 Arry1 := Explode(RangeFrom, '.'); Arry2 := Explode(RangeTo, '.'); 

Вы пропускаете память, не освобождая массивы, возвращаемые функцией Explode . Delphi отличается от PHP тем, что вам часто приходится управлять памятью объектов, которые вы создаете.


 a2 := Arry1[0]; b2 := Arry1[1]; c2 := Arry1[2]; d2 := Arry1[3]; 

Это должен быть Arry2 а не Arry1 .


Вы должны преобразовать строки в целые числа вперед. Поэтому объявите их следующим образом:

 a1, b1, c1, d1, a2, b2, c2, d2: Integer; 

и напишите присваивания следующим образом:

 a1 := StrToInt(Arry1[0]); b1 := StrToInt(Arry1[1]); //etc. etc. 

 while ($d2 >= $d1 || $c2 > $c1 || $b2 > $b1 || $a2 > $a1) 

переводит на:

 while ((d2 >= d1) or (c2 > c1) or (b2 > b1) or (a2 > a1)) 

Внутри цикла while вам нужен такой код:

 if d1 > 255 then begin d1 := 1; inc(c1); end; 

Преобразование 4 значений обратно в IP-адрес проще всего с помощью функции Format :

 ListBox1.Items.Add(Format('%d.%d.%d.%d', [a1, b1, c1, d1])); 

У вас есть неправильное понимание того, что StrToInt это функция, которая получает в качестве входных данных строку и возвращает целое число. Когда вы пишете:

 StrToInt(d1)+1 

вы не изменяете переменную d1 которая является только входной переменной. Эта проблема исчезает, когда вы делаете другие изменения, которые я описываю, но я хотел указать на вашу будущую выгоду.


Вы также можете заставить периодическую перерисовку окна списка, чтобы вы могли видеть, что происходит.


Поместите все это вместе, и у вас есть это:

 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; 

Я думаю, что причина в том, что он ничего не делает прямо сейчас, вы не можете иметь никаких значений в edit1.text или edit2.text.

Для тестирования (прежде чем делать этот фрагмент процедурой или функцией) вы можете просто назначить некоторые тестовые данные RangeFrom и RangeTo.

Ex. RangeFrom: = '121.198.0.0'; RangeTo: = '121.198.255.255';

Тестирование цели:

 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;