菜鸟问题:看看这个进制为什么这样转换(20分)

  • 主题发起人 主题发起人 publicnews
  • 开始时间 开始时间
P

publicnews

Unregistered / Unconfirmed
GUEST, unregistred user!
一个读取考勤卡的程序,里面将卡号数据读出来后是这样转换的
CardNo:=ord(Rdata[0])*16777216+ord(Rdata[1])*65536+ord(Rdata[2])*256+ord(Rdata[3]);
想问一下这样转换是为什么,想把一个卡号转换成存储的数据,就是反过来转换,那要怎么转,谢了
 
其实用移位完全可以的,这个人可能只知道乘法.
给一个大变量
a,b,c,d:int64;
a := ord(rData[0]);
a := shl(a,32);
b := ord(rData[1]);
b := shl(b,16);
c := ord(rData[2]);
c := shl(c,8);
d := ord(rData[3]);
cardno := a + b + c + d;
反过来就知道了???
 
怎么反过来?
 
****
****
已知cardno:int64;
a := shr(cardno,32);//取高32位 33-64bit
b := shr(cardno,16) mod 65536;//取16-32bit
c := shr(cardno,8) mod 256;//取 8-15bit
d := cardno mod 256;//最后8位
 
该问题 实际上是字节顺序的问题。
i386芯片中整数的表示是低字在前,高字节在后,而alpha芯片却相反。
你现在取到的整数的定义是高字节在前,低字节在后,因此i386的中需要把字节的顺序改过来才能正确使用。
你上面的那段代码确实不是太好,主要是乘法让人有点糊涂,实际上应该是这样更清楚一些吧
CardNo:=ord(Rdata[0]) shl 24 + ord(Rdata[1]) shl 16 + ord(Rdata[2]) shl 8 + ord(Rdata[3]);
不过效果一样 * 16777216 就是 shl 24
要注意 CardNo 的 定义是 integer 还是 cardinal

其实关于这个转化,还有更简单的办法

如果Rdata是一个整数定义的话可以

CardNo := ntohl(Rdata);

反过来

Rdata := htonl(CardNo)

这两个函数在WinSock单元
 
如果 Rdata定义为 PChar 可以这样

CardNo := ntohl(PInteger(Rdata)^);

PInteger(Rdata)^ := htonl(CardNo);
 
下面是考勤机读取数据的代码,我想调用考勤机的这个函数,
//注册卡
function SetOpenCard(port:integer;n:integer;bh: PChar;s:PChar;uname:PChar;bm:char):Boolean;stdcall;far;external 'hxrfkq.dll' name '_SetOpenCard@24';
//参数说明:port:串口号;n:机号 bh:人员编号;s:卡号;uname:姓名;bm:部门编号

但总不能调用成功:
var cardno:Int64;
begin
cardno:=StrToInt64(FID);
SetOpenCard(FCOM_NUM,FMac_Num,PChar(FSN),PChar(htonl(CardNo)),PChar(FName),FDeptID)

以下为程序中参考代码
private
FCOM_NUM:Integer;
FMac_Num:Integer ;
FID:string;
FSN:string;
FName:string;
FDeptID:Char;
FDept:string;
FHandle:THandle;
FFlag:Boolean;
FTimeRlt:string;

procedure TForm1.Button1Click(Sender: TObject);
var
fn,fnbackup,rfkh,s1:string;
state:boolean;
jls,isClear:integer;
CardNo:Cardinal;
str1:array[0..11] of byte;
TempStream: Tfilestream;
i,j,lscount:integer;
temp:array[0..5] of variant;
RData:array[0..100] of char;
RecordCount,CardFlag,Balance,Consume, counts,
year,month,day,hour,minute,MachineNo:integer;
begin
fn:= ExtractFilePath(ParamStr(0)) + 'ls.dat';
jls:=0;
fnbackup:= ExtractFilePath(ParamStr(0)) + 'lssj/'+DateToStr(Date)+'.dat';
state:=false;
if FileExists(fn) then DeleteFile(fn);
if FileExists('HXkq.txt') then DeleteFile('HXkq.txt');
isClear := 0;
if GetLS(FCOM_NUM,PChar(fn),jls,self.Handle,isClear,FMac_Num) then
begin
if jls=0 then
begin
MessageBox(self.Handle,'服务器内无可读流水','提示',48);
exit;
end;
//如果有流水则一条一条读
tempstream:=TFileStream.create(fn,fmopenread);
//将临时消费流水删除
MessageBox(self.Handle,pchar(format('成功读取流水数据,共有%d笔!',[jls])),'信息',64);
pb.Max:=jls;
pb.Position:=0;
for j:=1 to jls do
begin
Application.ProcessMessages;
tempstream.ReadBuffer(Rdata,8); //读取
CardNo:=ord(Rdata[0])*16777216+ord(Rdata[1])*65536+ord(Rdata[2])*256+ord(Rdata[3]);
month:=(ord(Rdata[4]) div 16)*10+ord(Rdata[4]) mod 16;
day:=(ord(Rdata[5]) div 16)*10+ord(Rdata[5]) mod 16;
hour:=(ord(Rdata[6]) div 16)*10+ord(Rdata[6]) mod 16;
minute:=(ord(Rdata[7]) div 16)*10+ord(Rdata[7]) mod 16;
s1:='卡号'+IntToStr(cardno);
s1:=s1+'时间:'+inttostr(month)+inttostr(day)+inttostr(hour)+inttostr(minute);
if CardNo>1000000000 then
begin
rfkh:=IntToStr(CardNo);
writetxt('O'+#9+rfkh+#9+Format('%.2d',[hour])+':'+Format('%.2d',[minute])+#9+Format('%.2d',[month])+'-'+Format('%.2d',[day])+'-'+RightStr(IntToStr(Yearof(now)),2)+#9+Format('%.2d',[FMac_Num]));
end
else
writetxt('O'+#9+Format('%.10d',[CardNo])+#9+Format('%.2d',[hour])+':'+Format('%.2d',[minute])+#9+Format('%.2d',[month])+'-'+Format('%.2d',[day])+'-'+RightStr(IntToStr(Yearof(now)),2)+#9+Format('%.2d',[FMac_Num]));
// AddListAndSaveData(s1);
pb.Position:=pb.Position+1;
end;
MessageBox(self.Handle,pchar(format('成功下载并保存数据共有%d笔!',[j-1])),'信息',64);
pb.Position:=0;
TempStream.Free;
end
else begin
MessageBox(self.Handle,'下载服务器数据失败,请重新下载!','警告',16);
exit;
end;
//将已读取的DAT文件放至lssj做为备份
copyfile(pchar(fn),pchar(fnbackup),state);
end;

procedure TForm1.writetxt(s: string);
var
vfilename:string;
fh:Textfile;
begin
vfilename:='HXkq.txt';
AssignFile(fh,vfilename);
if FileExists(vfilename) then append(fh)
else rewrite(fh);
writeln(fh,s);
closefile(fh);

end;
 
你的第一个问题怎么样了?
 
接受答案了.
 
后退
顶部