问题是这样的,我的一个网络应用程序,需要从服务器端保存用户列表,于是我声明了一个动态数组来保存用户 列表
有用户登录时,就添加一个,有用户下线时就删除一个 TUser=record
UserName:string[20];
Context:TIdContext;
LastTick: Cardinal; //最后一次时钟节拍
end;OnlineUser:array of TUser;//添加用户
procedure AddUser(UserData:TUser);
begin
cs.Enter;
//Memo1.Lines.Add('添加用户');
//ShowOnlineUser;
try
try
if High(OnlineUser)=-1 then
SetLength(OnlineUser,2) //第2个参数应该写1或2?
else
SetLength(OnlineUser,High(OnlineUser)+2); //此处+1还是+2?
OnlineUser[High(OnlineUser)]:=UserData;
//SDIForm.WriteLog('添加到在线用户成功');
except
on e:Exception do
SDIForm.WriteLog('添加在线用户失败:'+e.Message)
end;
//ShowOnlineUser;
finally
cs.Leave;
end;
end;procedure DelUser(UserData:string);
var i:integer;
begin
cs.Enter;
//Memo1.Lines.Add('删除用户');
//ShowOnlineUser;
try
try
for I := 0 to High(OnlineUser) do begin
if OnlineUser[i].UserName=UserData then begin
OnlineUser[i].Context.Connection.Disconnect;
OnlineUser[i]:=OnlineUser[High(OnlineUser)];
SetLength(OnlineUser,High(OnlineUser)-1);
Break;
end;
end;
//SDIForm.WriteLog('删除在线用户成功');
except
on e:Exception do
SDIForm.WriteLog('删除在线用户失败:'+e.Message);
end;
//ShowOnlineUser;
finally
cs.Leave;
end;
end;
//按现在的写法,在调用
for i:=0 to high(OnlineUser) do
onlineuser[i].connection.iohandler.write....//方法时提示越界,应该就是这面那地方的原因//另外显示用户数据时,假设一个用户在线,总是显示
//0:
//1:user_a
//所以数组元素0应该是空的,所以越办,上面那个设置数组长度应该如何写呢?
procedure ShowOnlineUser;
var i:Integer;
begin
try
cs.Enter;
Memo1.Lines.Add('--------online user--------');
Memo1.Lines.Add('online user length:'+IntToStr(Length(OnlineUser)));
try
for I := 0 to High(OnlineUser) do begin
Memo1.Lines.Add(IntToStr(i)+':'+onlineuser[i].UserName);
end;
except
on e:Exception do
ShowMsg('获得在线列表失败:'+e.Message);
end;
Memo1.Lines.Add('-------------------------');
finally
cs.Leave;
end;
end;
有用户登录时,就添加一个,有用户下线时就删除一个 TUser=record
UserName:string[20];
Context:TIdContext;
LastTick: Cardinal; //最后一次时钟节拍
end;OnlineUser:array of TUser;//添加用户
procedure AddUser(UserData:TUser);
begin
cs.Enter;
//Memo1.Lines.Add('添加用户');
//ShowOnlineUser;
try
try
if High(OnlineUser)=-1 then
SetLength(OnlineUser,2) //第2个参数应该写1或2?
else
SetLength(OnlineUser,High(OnlineUser)+2); //此处+1还是+2?
OnlineUser[High(OnlineUser)]:=UserData;
//SDIForm.WriteLog('添加到在线用户成功');
except
on e:Exception do
SDIForm.WriteLog('添加在线用户失败:'+e.Message)
end;
//ShowOnlineUser;
finally
cs.Leave;
end;
end;procedure DelUser(UserData:string);
var i:integer;
begin
cs.Enter;
//Memo1.Lines.Add('删除用户');
//ShowOnlineUser;
try
try
for I := 0 to High(OnlineUser) do begin
if OnlineUser[i].UserName=UserData then begin
OnlineUser[i].Context.Connection.Disconnect;
OnlineUser[i]:=OnlineUser[High(OnlineUser)];
SetLength(OnlineUser,High(OnlineUser)-1);
Break;
end;
end;
//SDIForm.WriteLog('删除在线用户成功');
except
on e:Exception do
SDIForm.WriteLog('删除在线用户失败:'+e.Message);
end;
//ShowOnlineUser;
finally
cs.Leave;
end;
end;
//按现在的写法,在调用
for i:=0 to high(OnlineUser) do
onlineuser[i].connection.iohandler.write....//方法时提示越界,应该就是这面那地方的原因//另外显示用户数据时,假设一个用户在线,总是显示
//0:
//1:user_a
//所以数组元素0应该是空的,所以越办,上面那个设置数组长度应该如何写呢?
procedure ShowOnlineUser;
var i:Integer;
begin
try
cs.Enter;
Memo1.Lines.Add('--------online user--------');
Memo1.Lines.Add('online user length:'+IntToStr(Length(OnlineUser)));
try
for I := 0 to High(OnlineUser) do begin
Memo1.Lines.Add(IntToStr(i)+':'+onlineuser[i].UserName);
end;
except
on e:Exception do
ShowMsg('获得在线列表失败:'+e.Message);
end;
Memo1.Lines.Add('-------------------------');
finally
cs.Leave;
end;
end;
解决方案 »
- 一个控件问题
- GetMem这样用为什么不暴错
- ? 为什么 if (ADOQuery1.FieldByName('密码').AsString = temppwd) then 括号中一定是错呢?
- 向窗口传递动态数组
- TNMHTTP的get方法怎么传入参数?
- 高手请入,关于adoquery。
- dexexpress dxdbgrid 的问题
- Delphi中如何利用RES文件?
- 急问用table1.batchMove(Asource:TBDEDateSet;AMode:TBatchMode):longint移动数据时提示destination must be indexed.table.我建索引后还
- 数据库问题
- 谁来讲讲聊天通讯的工作原理,如QQ。。
- 能否对函数名称加密解密调用呢?
SetLength(OnlineUser,2) //第2个参数应该写1或2?
else
SetLength(OnlineUser,High(OnlineUser)+2); //此处+1还是+2?
OnlineUser[High(OnlineUser)]:=UserData;改成下面2句就可以了SetLength(OnLineUser, Length(OnLineUser) + 1);
OnlineUser[High(OnlineUser)]:=UserData;
PUser = ^TUser;
TUser=record
UserName:string[20];
Context:TIdContext;
LastTick: Cardinal; //最后一次时钟节拍
end;ConnectList : TList;
//需要初始化...
//添加用户
procedure AddUser(UserData:TUser);
var
P : PUser;
begin
cs.Enter;
New(P);
P^ := UserData;
ConnectList.Add(P);//增加就完成了
....
end;procedure DelUser(UserData:string);
begin
cs.Enter;
for i:=0 to ConnectList.Count-1 do begin
if PUser(ConnectList.Items[i]).UserName=UserData then begin
Dispose(PUser(ConnectList.Items[i]));
ConnectList.Delete(i);
Break;
end;
end;
...
end;不过我有点没搞明白,连接断开的时候,你怎么得到UserName的?难道先查连接表?
既然是先查了连接表,为什么不在直接根据断开是的条件删除连接呢?这样就只需要一次循环,一个Lock
High(Tarr)等于-1;这时想增加一条, SetLength(Tarr,1);
这里 High(Tarr) 等于0;
当然最好是用 SetLength(Tarr,High(Tarr)+2); //这样写就可以在任何情况下增加一条数据对于High(Tarr)来说是从0开始的... 所以每新增一条数据, 重设长度为 High(Tarr)+1+1.. 如果要删去一条数据.. SetLength(Tarr,High(Tarr));
这样就删除了最后一条数据
如果要册是不是最后一条, 就先把最后一条数据,保存到你要删掉的那条数据的位置, 再执行SetLength操作
如果要清除数组内容, 就用 SetLength(Tarr,0); 这时就清空了数据,,并从内存中释放数组信息