你好,我的情况现在是这样的,通过厂家提供的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;
不知说得明白不明白,谢谢大家的回答,谢谢

解决方案 »

  1.   

    自己在说明一下,可能说的不是很清楚,厂家提供了vb的demo和delphi的demo,向厂家求助,最郁闷的是厂家说dephi的那个工程师已经离职了,无可奈何,郁闷,还想请大家帮忙帮忙
    http://img.blog.163.com/photo/aNqh94DdVIrsJgWKX7F3Dw==/2012264608505645853.jpg
    http://img.blog.163.com/photo/GGqHcfEak_cgBzJTOyPfzA==/2012264608505645856.jpg
    从上面两个图可以看到,都是调用了那个dll文件,而且返回的长度都是一样的啊,就是不知道为什么delphi的哪里数据是不完整的啊,请教请教
      

  2.   

    不好意思各位,上面写错了,m_data_buf:array[0..1450] of Char; //存储接收到的数据 应该是字符数组吧,谢谢
      

  3.   

    StrToHex(const S: string)
    调用:
    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);
      

  4.   

    好感激你的回答啊,我先去换了试试啊,谢谢,还有点不太明白,char不是也是string的一部分么,char跟Pchar又不一样是么,16进制的数值不是一个数值类型么?为什么可以用Pchar来存起来啊?谢谢
      

  5.   

    555555555555555,我按照楼上的做法把strtohex函数改了啊,但是发生了个错误,是这样啊调试器监测到错误
    工程 delphi_Demo.exe 监测到错误类 EOutOfMemory,错误信息:'Out of memory' 进程中止 请使用单步或运行继续运行为什么会这样啊,还请指教指教
      

  6.   

    char 和 pchar是不同的 好比C语言中的  int i 和 int* i
      

  7.   

    5555555555555555在网上找了很多strtohex的方法,都是不行啊,要不就是在00处就截断了,要么就是乱码啊 ,不是16进制的啊,55555555555555555555有没有好心人帮帮忙啊?谢谢
      

  8.   

    给帖子加分了,转为求助更为具体的问题,后来发现问题就是处在StrToHex这个函数上啊,
    在网上的很多方法,都是遇到了$00,字符就截断啦,$00 后面的字符就不能处理啊,
    求array of char 转换成 16进制字符串 的转换函数啊,谢谢谢谢
      

  9.   

    ...........
    没看清,原来的代码有些问题。
    再改下。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你看看。
      

  10.   

    啊,太感激ERRORCODE兄了,真的问题解决啦,现在接收已经正常了,谢谢谢谢!!!!!!!!!!
    小弟不才,还想请教下这段代码的一些解释啊,毕竟如果碰到同类的问题可以解决啊,如不嫌弃还想请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能指点指点,无限感激,谢谢
      

  11.   

    举个例子就清楚了,设text的第i个字符为'A',
    如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,
      

  12.   

    上面贴中有一行因'A'的ascii字符=65,即 说法不确切,应改为:因'A'的ascii字符的代码=65,即 
      

  13.   

    en,楼上说明很详细了。那个位操作就是为了得到16进制串而已,这个,你用二进制来比划一下就容易明白了。
    而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,还有他们的联系,使用技巧,这个不好说了,据说很多,我也没掌握完,而且也不会表达,留待以后,呵呵
      

  14.   

    BinToHex, HexToBin是VCL本身提供的函数,一般来说直接调用,不用再自己写。
    调用类似:
    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; 
      

  15.   

    啊,抱歉,看了一遍又发现不少漏洞,再次修改:举个例子就清楚了,假设text='BLACK';
    字符串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'其余各位也可类似求出来。
      

  16.   

    两位兄台的解释很详细啊,谢谢,仿佛找回了一点感觉啦,谢谢,原来delphi还可以这样用的哦,以前学数字电路的时候都没有想到现在可以这样的用法呢,总之,太感激了,谢谢