求最佳效率算法(100分)

  • 主题发起人 主题发起人 jingtao
  • 开始时间 开始时间
202.103.224.68
102.103.23.88
我找到的结果
 
要是觉得方法行的话我说下算法,感觉还可以,基本上可能的错误都能排除
 
说一下算法吧.希望有更多算法高手加入讨论.
 
如果没到字串尾,
读取字符
如果是数字
num[k] 处理,
如果num[k]>255,清空数据,继续
如果是 '.'
如果下一个字符为数字 k+1
else
如果k=4,表示获取了ip串,存储在num 数组中,处理
楼主的问题如果只要第一个的话结束就行了,遍历的话请空,继续循环


可以优化下
找到'.'
i从pos('.',mystring)-3开始循环
 
还是看看正则表达式吧。
 
正则表达式才是王道
 
你要高效率自然不能用字符串的方式来存储ip地址了。
aaa.bbb.ccc.ddd -> aaa*255*255*255 + bbb*255*255 + ccc*255 + ddd
排序后进行保存。 程序启动后读入到数组,使用二分法进行查找。

如果使用字符串保存ip地址,程序启动后读入到HashStringList,使用IndexOf进行哈希查找。
 
type
TDotPosInfo = record
Postion: integer;
strBefore: string[3];
strAfter: string[3];
end;

function FindFirstIP(sBuffer: string): string;
var
sStrBefore, sStrAfter: string;
iLen, iDotCount, iTemp, iLastDotPos,
i, k: integer;
Dots: array[1..3] of TDotPosInfo;

procedure CheckDotsInfo;
begin
if (Length(Dots[1].strBefore) = 3) and
(StrTointDef(Dots[1].strBefore, 256) > 255) then //288.1.1.1 --> 88.1.1.1
Delete(Dots[1].strBefore, 1, 1);
if (Length(Dots[1].strBefore) = 2) and
(Dots[1].strBefore[1] = '0') then //08.1.1.1 --> 8.1.1.1
Delete(Dots[1].strBefore, 1, 1);

if (Length(Dots[3].strAfter) = 3) and
(StrTointDef(Dots[3].strAfter, 256) > 255) then //1.1.1.288 --> 1.1.1.28
Delete(Dots[3].strAfter, 3, 1);

Result := Dots[1].strBefore + '.' + Dots[1].strAfter + '.' +
Dots[2].strAfter + '.' + Dots[3].strAfter;
end;

begin
iLen := Length(sBuffer);
if iLen < 7 then Exit;

iDotCount := 0;
iLastDotPos := 0;
for i := 2 to iLen do
//遇到一个'.' ,判断前后数据是否有效
if sBuffer = '.' then begin
if (iDotCount > 0) then
//两个'.' 之间字符数超过 3 ,重新开始
if (i - iLastDotPos - 1 > 3) then
iDotCount := 0
else begin
iTemp := StrToIntDef(Copy(sBuffer, iLastDotPos + 1, i - iLastDotPos - 1), 256);
//两个'.' 之间不是有效值,重新开始
if (iTemp < 0) or (iTemp > 255) then
iDotCount := 0;
end;

//取 '.' 前面的值
sStrBefore := '';
for k := i - 1 downto 1 do
if (sBuffer[k] in ['0'..'9']) then begin
sStrBefore := sBuffer[k] + sStrBefore;
if Length(sStrBefore) >= 3 then
Break;
end else begin
Break;
end;
//取 '.' 后面的值
sStrAfter := '';
for k := i + 1 to i + 4 do
if (k <= iLen) and (sBuffer[k] in ['0'..'9']) then begin
sStrAfter := sStrAfter + sBuffer[k];
if Length(sStrAfter) >= 3 then
Break;
end else begin
Break;
end;

//'.' 前面和后面都是有效值,则找到一个符合要求的,否则重新开始
if (sStrBefore <> '') and (sStrAfter <> '') then begin
Inc(iDotCount);
Dots[iDotCount].Postion := i;
Dots[iDotCount].strBefore := sStrBefore;
Dots[iDotCount].strAfter := sStrAfter;
end else
iDotCount := 0;

//按要求凑齐了 3 个 '.' 则找到 IP
if iDotCount = 3 then begin
//对前后处理一下
CheckDotsInfo;
Break
end;

iLastDotPos := i;
end;
end;
 
正则表达式的解释器太大了.所以觉得没有必要用到啊...
function checkIP2(sIPAddress)
{
var exp=/^(/d{1,2}|1/d/d|2[0-4]/d|25[0-5])/.(/d{1,2}|1/d/d|2[0-4]/d|25[0-5])/.(/d{1,2}|1/d/d|2[0-4]/d|25[0-5])/.(/d{1,2}|1/d/d|2[0-4]/d|25[0-5])$/;
var reg = sIPAddress.match(exp);
var ErrMsg="你输入的是一个非法的IP地址段!/nIP段为::xxx.xxx.xxx.xxx(xxx为0-255)!"
var Msg="你输入的是一个合法的IP地址段!"
if(reg==null)
{
alert(ErrMsg);
}
else
{
alert(reg);
}
}
 
anso:
你在IP地址前面加上一个%3A看看. strText:='sefs92345kmzxcasdfl;;asdasfbgtrthrthrth202.103.628.76oplasasdhjghsdAm,SDSFGNNZASDFB111.345.sxdsdsddf%3A202.103.224.68zsdffghntghtrtrt%3A102.103.23.88sasSDG90234';
 
看了大家的代码,主要麻烦在
不知道取出来的是否是ip地址
可以这样,取出ip段
用inet_addr(use winsock,参考MSDN)
如果能转换为网络字节,就是真正的ip地址
否则函数返回-1(INADDR_NONE),我们找下一个。
 
我本来想取个巧,修改下,主要原因是数字后的字符处理问题,
133202.103.23.88同时,如果有这样的字串,取的是2.103.23.88
var
myString: string;
i,j,k : integer;
num :array[1..4] of integer;
begin
memo7.Clear;
myString :=Memo6.text;//'sefs92345kmzxcasdfl;;asdasfbgtrthrthrth202.103.628.76oplasasdhjghsdAm,SDSFGNNZASDFB111.345.sxdsdsddf202.103.224.68zsdffghntghtrtrt102.103.23.88sasSDG90234';
//init num array
for k :=1 to 4 do
begin
num[k] :=0;
end;
k:=0;
//¼ÓËÙËã·¨£¬ÕÒµ½'.',i =pos-3
for i:=pos('.',mystring)-3 to length(mystring) do
begin
if ( mystring in ['0'..'9']) then
begin
if k=0 then
k:=1;
num[k] :=num[k]*10+ord(mystring)-ord('0');
if num[k]>255 then
begin
for j :=1 to k do
begin
num[j] :=0;
end;
k:=0;
end;
end
else if mystring ='.' then
begin
if ( mystring[i+1] in ['0'..'9']) then
k :=k+1;
end
else
begin
if k=4 then //»ñÈ¡ÁË¿ÉÄܵÄip ´¦Àí
begin
memo7.Lines.Add(IntTostr(num[1])+'.'+IntTostr(num[2])+'.'+IntTostr(num[3])+'.'+IntTostr(num[4]));
//Çå¿Õ
end;
for j :=1 to k do
begin
num[j] :=0;
end;
k:=0;
end;
end;
 
多人接受答案了。
 
后退
顶部