你好,我的情况现在是这样的,通过厂家提供的dll文件跟gprs模块进行通讯,通讯已经成功连接了,但是返回来的数据不知为什么会少了一部分,具体情况如下:type //用户数据结构
ModemDataStruct=record
m_modemId:Cardinal; // Modem模块的ID号
m_recv_time:cardinal; //接收到数据包的时间
m_data_buf:array[0..1450] of Char; //存储接收到的数据
m_data_len:word; //接收到的数据包长度
m_data_type:Byte; //接收到的数据包类型,
end;红色处代表了返回数据,这个好像看起来是一个字节数组啊,接着是显示在一个memo里面的,代码如下:procedure TForm1.ProcessData(dr:ModemDataStruct);//调用这个过程,显示在memo中,此时dr已经赋值了,格式是上面的格式
var i,j:Integer;
str:String;
strId:String;
strDate,strData:String;
time:TDateTime;
rut:integer;
begin
strId:=format('%8.8x',[dr.m_modemId]);
time:=UnixToDateTime(dr.m_recv_time+28800);
strDate:=DateToStr(Date)+' '+TimeToStr(time);
str:='ID:'+strId+'---'+'Time:'+strDate+'---'+'Len:'+IntToStr(dr.m_data_len);//dr.m_data_len为长度
for i:=1 to Length(str) do
if str[i]=#0 then //???此处不知道作用是什么
str[i]:=' ';
mmdatawnd.Lines.Add(str);
dr.m_data_buf[dr.m_data_len]:=#0; //???此处不知道作用是什么
if Form1.CheckBox1.Checked =true then//是否16进制显示的复选框
begin
//16进制显示,问题就好像在这里,请高手看看下面这个函数StrToHex,因为在memo上,显示上面返回来长度
// 已经是正确的了,但是返回来的数据少了一段,比如:正确返回的数据应该是01 04 1C 09 3C 09 44 00 7F
// 00 7B 00 81 00 00 01 26 01 19 01 2B 00 00 FF F0 FF F6 03 6A FF E6 7E 77 总长度是33,
//但是现在返回来的是:01 04 1C 09 3C 09 44 ,后面的一串没有了啊,但是长度也是显示是33,又刚好在00隔断
//了,不知是不是这里有问题,还想请教
mmDataWnd.Lines.Add('Data:'+StrToHex(dr.m_data_buf));
end
else
begin
mmDataWnd.Lines.Add('Data:'+dr.m_data_buf);
end;
end;
而StrToHex的代码如下,感觉上是不是这个函数处理有错误了,谢谢:
function StrToHex(const s : string) : string;
var
iCount : integer;
Value, CH, CL : Byte;
begin
SetLength(Result, 2 * Length(s));
for iCount:= 1 to Length(s) do
begin
Value:= Byte(S[iCount]);
CH:= (Value shr 4) and $0F;
CL:= Value and $0F;
if CL < $0A then
CL:= CL + $30
else
CL:= CL + $37;
if CH < $0A then
CH:= CH + $30
else
CH:= CH + $37;
Result[iCount * 2 - 1]:= Char(CH);
Result[iCount * 2]:= Char(CL);
end;
end;
不知说得明白不明白,谢谢大家的回答,谢谢
ModemDataStruct=record
m_modemId:Cardinal; // Modem模块的ID号
m_recv_time:cardinal; //接收到数据包的时间
m_data_buf:array[0..1450] of Char; //存储接收到的数据
m_data_len:word; //接收到的数据包长度
m_data_type:Byte; //接收到的数据包类型,
end;红色处代表了返回数据,这个好像看起来是一个字节数组啊,接着是显示在一个memo里面的,代码如下:procedure TForm1.ProcessData(dr:ModemDataStruct);//调用这个过程,显示在memo中,此时dr已经赋值了,格式是上面的格式
var i,j:Integer;
str:String;
strId:String;
strDate,strData:String;
time:TDateTime;
rut:integer;
begin
strId:=format('%8.8x',[dr.m_modemId]);
time:=UnixToDateTime(dr.m_recv_time+28800);
strDate:=DateToStr(Date)+' '+TimeToStr(time);
str:='ID:'+strId+'---'+'Time:'+strDate+'---'+'Len:'+IntToStr(dr.m_data_len);//dr.m_data_len为长度
for i:=1 to Length(str) do
if str[i]=#0 then //???此处不知道作用是什么
str[i]:=' ';
mmdatawnd.Lines.Add(str);
dr.m_data_buf[dr.m_data_len]:=#0; //???此处不知道作用是什么
if Form1.CheckBox1.Checked =true then//是否16进制显示的复选框
begin
//16进制显示,问题就好像在这里,请高手看看下面这个函数StrToHex,因为在memo上,显示上面返回来长度
// 已经是正确的了,但是返回来的数据少了一段,比如:正确返回的数据应该是01 04 1C 09 3C 09 44 00 7F
// 00 7B 00 81 00 00 01 26 01 19 01 2B 00 00 FF F0 FF F6 03 6A FF E6 7E 77 总长度是33,
//但是现在返回来的是:01 04 1C 09 3C 09 44 ,后面的一串没有了啊,但是长度也是显示是33,又刚好在00隔断
//了,不知是不是这里有问题,还想请教
mmDataWnd.Lines.Add('Data:'+StrToHex(dr.m_data_buf));
end
else
begin
mmDataWnd.Lines.Add('Data:'+dr.m_data_buf);
end;
end;
而StrToHex的代码如下,感觉上是不是这个函数处理有错误了,谢谢:
function StrToHex(const s : string) : string;
var
iCount : integer;
Value, CH, CL : Byte;
begin
SetLength(Result, 2 * Length(s));
for iCount:= 1 to Length(s) do
begin
Value:= Byte(S[iCount]);
CH:= (Value shr 4) and $0F;
CL:= Value and $0F;
if CL < $0A then
CL:= CL + $30
else
CL:= CL + $37;
if CH < $0A then
CH:= CH + $30
else
CH:= CH + $37;
Result[iCount * 2 - 1]:= Char(CH);
Result[iCount * 2]:= Char(CL);
end;
end;
不知说得明白不明白,谢谢大家的回答,谢谢
http://img.blog.163.com/photo/aNqh94DdVIrsJgWKX7F3Dw==/2012264608505645853.jpg
http://img.blog.163.com/photo/GGqHcfEak_cgBzJTOyPfzA==/2012264608505645856.jpg
从上面两个图可以看到,都是调用了那个dll文件,而且返回的长度都是一样的啊,就是不知道为什么delphi的哪里数据是不完整的啊,请教请教
调用:
StrToHex(dr.m_Data_Buf)
m_data_Buf是array of char,也就是PChar,调用时,转化为string,也就是说会遇#0为结尾。01 04 1C 09 3C 09 44 00 .....
遇到44后面的0,则认为结尾了,所以,出现你那情况。最简单的法子,就是改一下StrToHex函数,改成:function StrToHex(P: PChar; Size: Integer): string;
var
I: Integer;
Value, CH, CL: Byte;
begin
SetLength(Result, 2 * Size);
for I := 0 to Size - 1 do
begin
Value := Byte(P[I]);
CH := (Value shr 4) and $0F;
CL := Value and $0F;
if CL < $0A then
CL := CL + $30
else
CL := CL + $37;
if CH < $0A then
CH := CH + $30
else
CH := CH + $37;
Result[I * 2 - 1] := Char(CH);
Result[I * 2] := Char(CL);
end;
end;调用:
StrToHex(dr.m_databuf, dr.m_data_len);
工程 delphi_Demo.exe 监测到错误类 EOutOfMemory,错误信息:'Out of memory' 进程中止 请使用单步或运行继续运行为什么会这样啊,还请指教指教
在网上的很多方法,都是遇到了$00,字符就截断啦,$00 后面的字符就不能处理啊,
求array of char 转换成 16进制字符串 的转换函数啊,谢谢谢谢
没看清,原来的代码有些问题。
再改下。function StrToHex(Text: PChar; Size: Integer): string;
const
SHexs: array[0..15] of Char = '0123456789ABCDEF';
var
V: Byte;
I: Integer;
begin
Result := StringOfChar(#0, Size * 2);
for I := 0 to Size - 1 do
begin
V := Byte(Text[I]);
// 原来函数中,下面两行有问题。更正如下
Result[i * 2 + 1] := SHexs[V shr 4];
Result[i * 2 + 2] := SHexs[V and $F];
end;
end;D里面自带有这些函数。BinToHex, HexToBin你看看。
小弟不才,还想请教下这段代码的一些解释啊,毕竟如果碰到同类的问题可以解决啊,如不嫌弃还想请ERRORCODE兄指教指教
function StrToHex(Text: PChar; Size: Integer): string;
const
SHexs: array[0..15] of Char = '0123456789ABCDEF';//这个字符数组这样定义的作用是什么啊?
var
V: Byte;
I: Integer;
begin
Result := StringOfChar(#0, Size * 2);//用于获得一个串,此串中含有n个重复的字符(#0空字符)
//这个result不太明白啊,是不是现在就返回结果啦,为什么要
//先返回一个size*2的空字符串啊?
for I := 0 to Size - 1 do
begin
V := Byte(Text[I]);
// 原来函数中,下面两行有问题。更正如下
Result[i * 2 + 1] := SHexs[V shr 4];//右移4位??
Result[i * 2 + 2] := SHexs[V and $F];//逻辑与 ??
//这两个result太神奇了,看得不是很懂啊,为什么要用
//SHexs[V shr 4]和SHexs[V and $F];,谢谢
end;
end; 还有关于这个BinToHex我也查过啦,说明哪里是这样说啊
function HexToBin(Text, Buffer: PChar; BufSize: Integer): Integer
ERRORCODE兄的意思是不是用这个函数也可以达到上面的效果啊,
不好意思,可能自己看书还是太少,所以你的一段代码都要查上好几回,而且还是不动,还想指教指教对于这些字符(Char),字符串(Sting),十六进制字符串(???),还有PChar他们之间的关系怎么好像复杂的,为什么转换的时候会出现遇到$00就会截断的问题啊,现在一头雾水,希望ERRORCODE能指点指点,无限感激,谢谢
如BLACK的第三个字符是'A'.即i=3时text[i]='A',我们来看怎样求得它的16进制数。先说明,ASCII字符'A'是一字节,需用8个bits表示的,
而16进制数是4bits,所以一个字符要2个16进表示,
一个n位的字符就要2n位的16进数来表示,故先用
Result := StringOfChar(#0, n * 2)
语句来定好16进制数的String长度(16进制数作为
一个字符串,每一位仍得用一个字符);1.先弄清text[i]='A'的16进制数是多少?
因'A'的ascii字符=65,即
64+1=01000000+00000001=01000001
故其16进数的高位是0100=4,
低位是0001=1,
写在一起,可知'A'的16进就是$41,2. 再看怎样得到'A'的16进制数41?
(1) V:=Byte(Text[I]);
=Byte('A')
=01000001
(2) Result[i*2+1]:
=SHexs[V shr 4];
=SHexs[01000001 shr 4]
=SHexs[0100]
=4;
(3) Result[i*2+2]:
=SHexs[V shr 4];
=SHexs[01000001 and $F]
=SHexs[01000001 and 1111]
=SHexs[0001]
=1;
故其16进数的高位是0100=4,即01000001右移4位,将后4位去掉,
低位是0001=1,即01000001与1111逻辑乘(与)所得,
写在一起的16进就是$41,
而SHexs的作用是:取得数字对应的字符,给于Result返回. V shr 4, V and $F得到的是一个byte值,再通过SHexs[]取得对应显示的字符,形成result至于#00截短的问题,是因为在PChar/array of char类型,在Delphi环境中,如果是自动转换为String时,则遇#00为结束,除了手工转换string
本来应该代码是那样写的:
var
S: string;//手工设置转换string
SetString(S, dr.m_data_buf, dr.m_data_len);
//默认设置转换
S := dr.m_data_buf在你原来的代码中,直接将m_data_buf作为string参数传入到StrToHex,则系统认为是遇#00的PChar,帮你自动转,所以截短。而关于char, string, pchar,还有他们的联系,使用技巧,这个不好说了,据说很多,我也没掌握完,而且也不会表达,留待以后,呵呵
调用类似:
function StrToHex(Data: PChar; Size: Integer): string;
begin
Result := StringOfChar(#0, Size * 2);
BinToHex(Data, PChar(Result), Size);
end;HexToBin是逆函数也叫16进制编码/解码函数,Base16Encode, Base16Decode
一般为了显示方便,每两位是加个空格,这样好查看,所以,我一般是这样写的:
function Base16Encode(Text: PChar; Size: Integer): string;
const
SHexs: PChar = '0123456789ABCDEF';
var
V: Byte;
I: Integer;
R: PChar;
begin
Result := StringOfChar(#0, Size * 3); // ==> SetLength(Result, Size * 3)
R := PChar(Result);
for I := 0 to Size - 1 do
begin
V := Byte(Text[I]);
R[0] := SHexs[V shr 4]; // high
R[1] := SHexs[V and $F]; // low
R[2] := #32; // space
Inc(R, 3);
end;
end;
字符串text的第0个字符为'B',第1个字符为'L',
第2个字符为'A',...,即i=2时text[i]='A',我们来看怎样求得text[2]='A的16进制数。1. 先说明,ASCII字符'A'需用8个bits的字节表示,
而16进制数是4 bits的,所以一个字符要2个16进表示,
一个n位的字符串就要2n位的16进数来表示,故先用
Result := StringOfChar(#0, n * 2)
语句来定好16进制数的String长度(16进制数作为
一个字符串,每一位仍是一个字符,要8位);2. 再弄清text[2]='A'的16进制数是多少?
因'A'的ascii字符=65,即
64+1=01000000+00000001=01000001
故其16进数的高位是0100=4,低位是0001=1,
写在一起,知'A'的16进就是41(写成$41),
而与2个数对应的2个字符是'4','1',连在一起是'41'.3. 最后再看程序如何得到'A'的16进制数41和字符串'41'?
(1) V:=Byte(Text[i])
=Byte('BLACK'[i])
=Byte('A') //当i=2, 为第3个字符'A'
=01000001 //65的二进制
(2) Result[i*2+1] //i=2,i*2+1=5,第5个16进制数字
=SHexs[V shr 4]
=SHexs[01000001 shr 4] //右移4位,后4位被删去
=SHexs[0100] //剩下高4位
='4'; //SHexs的第4个字符
(3) Result[i*2+2] //当i=2, i*2+2=6, 第6个16进制数字
=SHexs[V and $F] //逻辑乘
=SHexs[01000001 and 1111] //数据代入
=SHexs[0001] //逻辑乘结果
=SHexs[1] //逻辑乘结果
='1'; //SHexs的第1个字符
故text(即'BLACK')的16进制数(字符串)的第5第6两位是'41'。
text('BLACK'其余各位也可类似求出来。