Problem z zakresem liczb..

0

OK.. wiec na poczatek mam sobie funkcje inet_addr, ktroa wymaga jako argumentu adresu IP w formie "kropkowanej" (np. 192.160.0.127) .. a zwraca adres w formie "internetowej" czyli liczby typu Cardinal.. przynajmniej tak jest napisane w helpie :) ale wszystko jest spoko dopoki ostatni oktet adresu IP jest mniejszy niz 128.. po przekroczeniu tej wartosci funkcje zwraca ujemne adresy!! Na pewno przyjdze wam do glowy napisac ze trzeba zmienic typ zmiennej przechowujacej ten adres bo wykracza on poza obszar odwzorowania.. czy jakos tak.. :) ale nic z tego.. zmienialem juz na wszystko od byte :P poprzez u_long, dword, po int64 .. i wszystko zwraca ta sama wartosc, ujemna!! Probowalem nawet uzyc typu stworzanego specjalnie na potrzeby tej funkcji przez programistow (z Microsoftu chyba) .. :) ale to nic nie zmienia.. efekt zawsze ten sam.. Range check Error.. :( ponizej napisze kilka linijek tego kodu (te najwazniejsze) zeby moze ktos mi pomogl.. :)

function GetMAC(IP:string):string;
var  dwResult : DWord;
     ulIPAddr : DWord;
     //ulIPAddr  : TSockAddrIn;
     ulMACAddr : array [0..5] of Byte;
     ulAddrLen : ULONG;
const INADDR_NONE = $FFFFFFFF;
begin
  ulIPAddr := inet_addr(PChar('192.168.0.128'));
//  ulIPAddr.sin_addr.S_addr:= inet_addr('192.168.0.128');
  ShowMessage(IntToHex(ulIPAddr,8)+': ciagle dziala :'+inttostr(ulIPAddr));
//  ShowMessage(IntToHex(ulIPAddr.sin_addr.s_addr,8)+': dziala :'+inttostr(ulIPAddr.sin_addr.s_addr));
  if ulIPAddr = INADDR_NONE then exit;
//  if ulIPAddr.sin_addr.s_addr = INADDR_NONE then exit;
  ulAddrLen := 6;
  dwResult := SendARP(ulIPAddr,0,@ulMACAddr,@ulAddrLen);
//  dwResult := SendARP(ulIPAddr.sin_addr.S_addr,0,@ulMACAddr,@ulAddrLen);
  ShowMessage('dwResult: '+IntToStr(dwResult)); // if 0, then ok
  result:=(IntToHex(ulMACAddr[0],2)+':'+IntToHex(ulMACAddr[1],2)+':'+
           IntToHex(ulMACAddr[2],2)+':'+IntToHex(ulMACAddr[3],2)+':'+
           IntToHex(ulMACAddr[4],2)+':'+IntToHex(ulMACAddr[5],2));
end;

Te wykomentowane czesci to wlasnie uzycie tego specjalnego tylu.. :( pomocy!!

0

Moze sie myle ale wg mnie numery zaczynajace sie na: 192. i 10. to sa numery wew. Jak na razie nie spotkalem zew. Wiec mozliwe ze adresiki sa ograniczone, a przekroczenie prowadzi do ujemnej wartosci (przekroczony cardinal?:)). Albo w sieci nie ma 129 :) Sprobuj napisac IP zew. Moze wtedy bedzie dobrze.
Przepraszam jesli nie pomoglem za bardzo

0

wpisz:

zmienna:=cardinal(inet_addr(...))

Tak przy okazji: dword, cardinal, longword, ULONG ... i cała masa innych typów to wcąż to samo... 32 nieoznaczone bity o zakresie 0-2^32-1.

poza tym jest jeszcze jedna rzecz, inttostr to dwa overlołdy:

function IntToStr(Value: Integer): string; overload;
function IntToStr(Value: Int64): string; overload;

typ int to 32 bity oznaczone, ale 32 bity więc kompilator na siłę próbuje podstawić Twoją zmienną, więc aby zawsze miec wartośc dodatnią musisz zadbac aby wywoływana była ta z argumentem int64...

inttostr(int64(Your_ipaddr))

albo mozesz jeszcze popróbować wyłączając sprawdzanie zakresu:

{$r-}
inttostr(Your_idaddr)
{$r+}

Sorry, że tak po kawałku...
Inttohex to też dwa takie overlołdy int/int64, ale tu lepiej jest wyłączyc zakres niz konwertować, bo hex nie ma znaku, a i łykniesz mniej stosu.

//flabra loguj sie na przyszlosc to nie bedzie paru postow pod spodem.. - lofix

0

poza tym jest jeszcze jedna rzecz, inttostr to dwa overlołdy:

function IntToStr(Value: Integer): string; overload;
function IntToStr(Value: Int64): string; overload;

typ int to 32 bity oznaczone, ale 32 bity więc kompilator na siłę próbuje podstawić Twoją zmienną, więc aby zawsze miec wartośc dodatnią musisz zadbac aby wywoływana była ta z argumentem int64...

hmmmm....
LW := LongWord(-1);
IntToStr(LW) - daje 4294967295

To właśnie ten overload wartości LongWord większe od połowy zakresu traktuje jak Int64.

0

To właśnie ten overload wartości LongWord większe od połowy zakresu traktuje jak Int64.

Chcesz powiedzieć...

  1. sprawdz zakres liczby...
  2. wyszukaj najodpowiedniejszą pod względem dopasowania funkcję
  3. wywołaj funkcję...

że te trzy punkty są wykonywane podczas działania programu? Mnie uczono, że pascal/delphi to kompilator nie interpreter i że jest to wykonywane podczas procesu kompilacji. Tylko raz.

Nie masz racji co do tego, że longłord jest konwertowany wtedy, gdy ma wartośc większą od zakresu longinta (możliwe tylko w interpreterze)... Ale masz rację, że do int64, a to dlatego, że int64 całkowicie pokrywa zakres. Oczywiście w czasie kompilacji.

Sprawdziłem i faktycznie masz rację (thnx)... Bład w całym tym galimatiasie nie nie tkwi w zakresie wywołania strtoint, ale w zakresie wyniku inet_addr

0

Moze sie myle ale wg mnie numery zaczynajace sie na: 192. i 10. to sa numery wew. Jak na razie nie spotkalem zew. Wiec mozliwe ze adresiki sa ograniczone, a przekroczenie prowadzi do ujemnej wartosci (przekroczony cardinal?:)). Albo w sieci nie ma 129 :) Sprobuj napisac IP zew. Moze wtedy bedzie dobrze.

No i niestety sie mylisz.. adresy 192, 10 itd.. maja hosty o numerach nawet 254.. :) a adresy zewnetrzne tez sie wysypuja po osiagnieciu hosta wiekszego od 127.. :( sprobuj nawet 255.255.255.128.. :( ciagle wysypa.. :(

0

zmienna:=cardinal(inet_addr(...))
Powtórzę się. Działa niezależnie od sprawdzania zakresu. A w ogóle to po kiego czorta masz sprawdzanie zakresu? Przecież to jest potrzebne tylko do odpluskwiania.

0

zmienna:=cardinal(inet_addr(...))

DZIALA!!! DZIALA!!! DZIALA!!! :) dzieki wielkie.. :) nie wpadlem na to.. :P :) sprawdzalem dla int64 a dla cardinal juz zapomnialem.. :) dla int64 nie dzialalo.. :) ale dla cardinal zadzialalo.. :)

Powtórzę się. Działa niezależnie od sprawdzania zakresu. A w ogóle to po kiego czorta masz sprawdzanie zakresu? Przecież to jest potrzebne tylko do odpluskwiania.

Wlasnie po to mam wlaczone zeby wiedziac czemy funkcja zwraca mi adresy MAC w postaci: 000000:00 :) gdybym mial {$r-} to nigdy bym pewnie nie wpadl dlaczego funkcja nie dziala.. :) a juz na pewno nie wpadl bym na rozwiazanie :P :) ;-> jeszcze raz dzieki.. :) !!

0

Niezamaco. :-D

Tak na prawde mógłbyś sobie tą funkcję sam napisać...
IP: aaa.bbb.ccc.ddd

aaa- najmniej znaczący bajt w wyniku
...
ddd- najbardziej znaczący bajt wyniku.
A wynik jest przecież czterobajtowy.

// Do odpluskwiania wystarczy mieć $D, $L, ...
// $R jest potrzebne tylko przy jakichś ostrych sytuacjach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1