DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: sosolee369369
今日帖子: 2
在线用户: 15
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 zhaolin918 (45) ▲▲▲▲▲ -
注册会员
2010/11/13 16:14:40
标题:
string 和 array of char 之间的转换问题 浏览:3186
加入我的收藏
楼主: 我的程序如下:
var
  S: string;
  Darr: array of char;
  p:pchar;
begin
  s:= '中文';
  SetLength(Darr,Length(s));
  Move(s,Darr[0],Length(S));
  try
    GetMem(p,Length(Darr));
    Move(Darr[0],p,Length(Darr));
    showMessage(p);
  finally
    FreeMem(p);
  end;
end;
showMessage的结果是“中文”。但是最后报错:“Invalid pointer operation”,用的D6。不知道什么原因。
----------------------------------------------
-
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2010/11/13 16:48:24
1楼: 不懂指针,但是看try结构似乎不对

  GetMem(p,Length(Darr));
  try
    。。。。
  finally
    FreeMem(p);
  end;
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 pgldjlzs (sense) ▲▲▲▲▲ -
注册会员
2010/11/13 17:46:50
2楼: 在dlphi2010下测试,出现“Invalid pointer operation”的原因主要是FreeMem(P),原因应该是Pchar类型是自管理的,不用FreeMem,事实上也不必用GetMem。而且上述用Length的话不能显示正确内容,改为SizeOf就OK。测试代码如下:
procedure TForm1.btn1Click(Sender: TObject);
var
  Str:string;
  P:PChar;
  Arr:array of Char;
begin
  str:='中文';
  SetLength(Arr,sizeof(str));
  Move(str,Arr[0],sizeof(Str));

  try
//    GetMem(P,sizeof(Str));
    Move(Arr[0],P,sizeof(Arr));
    ShowMessage(P);
  finally
//    FreeMem(P);
  end;
----------------------------------------------
-
作者:
男 learu (learu) ★☆☆☆☆ -
盒子活跃会员
2010/11/13 18:20:15
3楼: 真对现在的程序员悲哀啊...(不是对楼主)
如果自己都没明确搞明白 请不在乱回答别人好不好!!

TO 2楼:  
  是谁告诉你PChar类型是自管理的了?
  不知道写的什么乱七八糟的... 自己错就算了 不要误导别人 OK
----------------------------------------------
-
作者:
男 learu (learu) ★☆☆☆☆ -
盒子活跃会员
2010/11/13 18:30:30
4楼: var
  S: Ansistring;
  Darr: array of Ansichar;
  p:pAnsichar;
begin
  s:= '中文';
  SetLength(Darr,Length(s));
  Move(s[1], Darr[0], Length(S));
  p := AllocMem(Length(Darr)+1);
  try
    Move(Darr[0], p^, Length(Darr));
    showMessage(p);
  finally
    FreeMem(p);
  end;
end; 

虽然这段代码 很多都是重复多余的(是指好像没什么实际意义)
顺便解释一下跟楼主写的不同点的原因:
为什么用了AnsiString  因为D6的String = D2009,2010,XE 下的AnsiString
同理 我把 PChar都换成了 PAnsiChar,  Char换成了 AnsiChar
为是只是开发环境对代码兼容
至于为什么我用 Allocmem 不是用GetMem  因为AllocMem比GetMem 多了申请完内存后会将内存全部置为0
因为指针字符器是以\0结束的 (这些好像在计算机原理或者别的基础书里都有讲 如果不懂 请看书) 
所以申请空间时 你需要申请比字符串多一个字节 并且是0(如果是Unicode下就是2个字节)

----------
var
  S: Ansistring;
  Darr: array of Ansichar;
  p:pAnsichar;
begin
  s:= '中文';
  SetLength(Darr,Length(s));
  Move(s[1], Darr[0], Length(S)+1);
  p := @Darr[0];
  showMessage(p);
end;

其实这样子就可以了 不需要又申请什么内存
----------------------------------------------
-
作者:
男 learu (learu) ★☆☆☆☆ -
盒子活跃会员
2010/11/13 18:35:01
5楼: 至于为什么会报 Invalid pointer operation错

原因是因为  字符串指针 必须是以\0为结束

因为你申请的内存只放的下"中文"4个字节   会发生2种情况
运气好:
  "中文" 后面跟的是\0 且这个内存地址是有效的 那就不会报错
运气不好:
  也就是你这样读字符串的时候越界了 非法指针操作


都是很基础的东西  去翻翻基础书吧
----------------------------------------------
-
作者:
女 melice (melice) ★☆☆☆☆ -
盒子活跃会员
2010/11/14 23:24:58
6楼: 做了简单的修改,move换成copymemory,getmem换成getmemory。测试正常。
var
  S: string;
  Darr: array of char;
  p:pchar;
  l:integer;
begin
  s:= '中文';
  L := Length(s);
  SetLength(Darr,L);
  CopyMemory(@Darr[0], @s[1], L);
  try
    p := GetMemory(L+1);
    CopyMemory(p, @Darr[0],  L);
    showMessage(p);
  finally
    FreeMem(p);
  end;
----------------------------------------------
-
作者:
女 melice (melice) ★☆☆☆☆ -
盒子活跃会员
2010/11/14 23:27:17
7楼: var
  S: string;
  Darr: array of char;
  p:pchar;
begin
  s:= '中文';
  SetLength(Darr,Length(s));
  Move(s,Darr[0],Length(S));  //自己调试跟踪下这句的效果是什么。
  try
    GetMem(p,Length(Darr));
    Move(Darr[0],p,Length(Darr));
    showMessage(p);
  finally
    FreeMem(p);
  end;
----------------------------------------------
-
作者:
男 yzhtwo (深秋) ▲▲▲▲▲ -
普通会员
2010/11/15 8:57:59
8楼: 讨论一下语法也好
var
  S: string;//最好是s: AnsiString
  Darr: array of char;
  p:pchar;
begin
  s:= '中文';
  Setlength(Darr, Length(s)+1);//保留最后一位给#0;
  //SetLength(Darr,Length(s));
  Move(Pointer(s)^, Pointer(Darr)^, Length(s));//注意变量参数的传递,或引用类型参数
 //或 Move(s[1], Darr[0], Length(s));
 //Move(s,Darr[0],Length(S));
  try
    GetMem(p,Length(Darr));
    Move(Pointer(Darr)^, p^, Length(Darr));//注意变量参数的传递,或引用类型参数
    //或Move(Darr[0], P^, Length(Darr));
    //Move(Darr[0],p,Length(Darr));
    showMessage(p);
  finally
    FreeMem(p);
  end;
end;
----------------------------------------------
-
作者:
男 please_air (please_air) ★☆☆☆☆ -
普通会员
2010/11/15 9:35:58
9楼: yzhtwo (深秋)

可以详细说说, 

 Move(Pointer(Darr)^, p^, Length(Darr));//注意变量参数的传递,或引用类型参数
    //或Move(Darr[0], P^, Length(Darr));
    //Move(Darr[0],p,Length(Darr)


----------------------------------------------
----------
短信群发 http://www.188sms.cn
家校通 http://www.studjxt.cn
网站建设 http://www.51zwz.net
----------
作者:
男 yzhtwo (深秋) ▲▲▲▲▲ -
普通会员
2010/11/15 14:45:05
10楼: 继续讨论一下
var
  s: Ansistring;
  FArr: array[1..10] of char;
  FDArr: array of char;
  P: PChar;
  c: Char;
  //对于变量名s,FArr,FDArr,P都是相对应的内存首地址(s,FDArr,P需初始化)
begin
  try
  GetMem(P, 10*SizeOf(Char));
  //----------

   s :='0123456789';
   
  //下面也是取得s[1];
  c := PChar(s)^;  //取字符串地址指向的第一个字符,也就是s[1];
  ShowMessage(c);

  // procedure Move( const Source; var Dest; count : Integer );
  //Source, Dest参数实际上传入的是变量的地址,也就是说取变量的地址传入;
  //所以我们不能直接传入变量s(地址), 只能传入s[1]或PChar(s)^,让过程取s[1]取地址(字符串首地址)
  Move(PChar(s)^, P^, Length(s));
  c := P^;
  ShowMessage(c);
  //----------

  FArr := 'abcdefghij';
  //下面也是取得FArr[1];
  c :=  PChar(@FArr)^;  //取数组地址指向的第一个字符,也就是FArr[1];
  ShowMessage(c);

   Move(FArr, P^, Length(s));
   c := P^;
   ShowMessage(c);
  //----------

  SetLength(FDArr, 10); //设置动态数驵长度,FDArr指向动态数组的首地址

 // FDArr := 'ABCDEFGHIJ';//跟静态数组不一样,这样不可以
  FDArr[0] := 'A';
  FDArr[1] := 'B';
  FDArr[2] := 'C';
  FDArr[3] := 'D';
  FDArr[4] := 'E';
  FDArr[5] := 'F';
  FDArr[6] := 'G';
  FDArr[7] := 'H';
  FDArr[8] := 'I';
  FDArr[9] := 'J';
  //下面也是取得fDArr[0];
  c := PChar(FDArr)^;  //跟静态数组有区别,不要取@操作
  ShowMessage(c);

  Move(PChar(FDArr)^, P^, Length(FDArr)); // 取动态数组地址指向的第一个字符传入
  c := P^;
  ShowMessage(c);
  //----------

  finally
  FreeMem(P);
  end;
end;
----------------------------------------------
-
作者:
女 melice (melice) ★☆☆☆☆ -
盒子活跃会员
2010/11/15 21:20:59
11楼: 又仔细看了下,lz的代码暴露了很多问题,move的含义没弄清楚,指针概念不清晰等等。showmessage可以显示完全是一种巧合。如果字符串再长一点,搞不好连整个堆栈都破坏掉了。

2次move传递的实际上是地址,而不是字符串的内容。这个才是为什么异常的核心所在啦。
至于pchar后面要多个#0,这个也是要小心的问题。

总之,对于指针的操作,要小心小心再小心。再怎么小心也是不过分的。
----------------------------------------------
-
作者:
男 rururu (rr) ★☆☆☆☆ -
盒子活跃会员
2010/11/17 2:35:32
12楼: string 和 array of char 之间好象很容易转换哦, 很多年前就做过了, 现在有点忘了, array of char 和 pchar可以直接转换, pchar(array of char)就行, string就复杂了点, 具体有点忘了, 但是可以转换的.
----------------------------------------------
-
作者:
男 rururu (rr) ★☆☆☆☆ -
盒子活跃会员
2010/11/17 2:43:04
13楼: string可以和pchar相互直接转换啊!

var
a: string;
b: pchar;
.....
a:=string(b);
b:=pchar(a);

在delphi7上完全可以互换;
----------------------------------------------
-
作者:
男 homejun (homejun) ★☆☆☆☆ -
盒子活跃会员
2011/2/17 22:14:30
14楼: StrPCopy
----------------------------------------------
-delphi新资讯站 http://www.delphigear.cn
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行54.6875毫秒 RSS