求 String 轉換至 PChar 的函數(50分)

各位,别争了。这种问题在本论坛上提过很多次。其实每个人说的都对,但都是应用于不同
的情况。如果引用字符串为常量只是读的话可以直接用强制转换。但如果要处理的话就不可
以,可能会引起非常指针引用错误。这时候只能用StrPCopy函数。不过拷贝前需要分配窠间,
用完要释放。
P := StrAlloc(Length(Source) + 1);
StrPCopy(P, Source);
.....//现在处理
StrDispose(P);
 
to barton :
用你的方法依舊存在無法針對中間有 #0 存在的字串(string) 做轉換!



範例:
procedure TForm1.Button1Click(Sender: TObject);
var
p:pchar;
const
source : string='0123456789'+#0#0+'abc'
// 共 15 bytes
begin
P := StrAlloc(Length(Source) + 1);
StrPCopy(P, Source);
try
ShowMessage(p[12])
// 應該顯示 'a' 但沒有 --> 錯誤
ShowMessage(source[13])
// 顯示 'a' --> 正確
finally
StrDispose(P);
end;
end;
 
看看Pchar的定义:
A PChar is a pointer to a null-terminated string of 8-bit characters.
也就是说#0是字符串的结束标志,所以你如果一定要处理有 #0 存在的字串,
请不要使用Pchar,或者用其他变通方法。
 
問題是 String 可含有 #0 的字串,並且他本身有長度的結構存在,
但是一些 WinAPI 所要的是 Pchar ,那.....無法得到我想要的函數嗎?
 
想办法把#0去掉先……
你真的需要#0吗?
你不是真的需要吧?
 
PChar(str1);
 
PChar多方便
不过它与StrPCopy有什么区别?
 
我雖然不確定是否內含 #0 ,但是,我要讀取的是二進位檔案,內含
的可能性很大!

而且,主題為 String 轉至 PChar ,意思就是不管 String 內含何值,
都希望能成功地轉至 PChar. 當然,此 PChar 要能獨立運用。
 
jiichen,你需要的函数确实就是StrPCopy,此函数能够能够把#0及其以后的内容一起转换
到目标里面,功能是达到了的,能否使用#0及其以后的内容,那是你使用的问题了:)
 
to 光子:
真的可以嗎?為何測試不過?


範例:
procedure TForm1.Button1Click(Sender: TObject);
var
p:pchar;
const
source : string='0123456789'+#0#0+'abc'
// 共 15 bytes
begin
P := StrAlloc(Length(Source) + 1);
StrPCopy(P, Source);
try
ShowMessage(p[12])
// 應該顯示 'a' 但沒有 --> 錯誤
ShowMessage(source[13])
// 顯示 'a' --> 正確
finally
StrDispose(P);
end;
end;
 
是shortstringaspchar吗?
 
to reno :
不是,雖然找不到你講的函數,但看名稱是屬於 Short string 類的。
 
Move()试一试
 
你可以自己写啊,不难,真的.
 
关于Delphi的长字符串,有一个没有归档的特性:S[0]。

一般情况下,S[0] = Length(S)。但在有些情况下,
S[0] <> Length(S)。也就是你说的,在串中保留有Delphi认作终止符的
#0。此时,要想办法获取S[0]值作为串长,而不能简单地取Length(S)。

关于这方面的内容,micro cantu 在《Delphi 高级开指南》中有比较
详细的描述。

由于Borland 没有将它归档,因此很难保证以后的版本中可能会有的变动。
一般情况下没有必要使用这种方法去处理串。
 
直接转就可以吗。
var
p:pChar;
str:String;
begin
str:='liguang';
p:=PChar(str);
end;
 
string必须以#0结束,这也是标志string的方法。
 
to daxian:
你的方法可以,但不知為何,出現錯誤,可以幫我看看嗎?

procedure TForm1.Button2Click(Sender: TObject);
var
p:pchar;
const
source : string='0123456789'+#0#0+'abc'
// 共 15 bytes
begin
P := StrAlloc(Length(Source) + 1);

move(source,p,15);
try
ShowMessage(p[12])
// 應該顯示 'a' --> 正確
ShowMessage(source[13])
// 顯示 'a' --> 正確
finally
StrDispose(P)
// 但此步出現問題 EInvaildPointer , Why?
end;
end;


to liguang:
直接轉在某些場合會出問題,因為 Long String 有 reference counted ,如果
使用 p:=pchar(str) 的話,那當 reference count=0 的時候,字串會自動被消滅,
那 p 所指定的空間便成為違法存取了。


to ddev:
我的資料是說 Short String 長度是放在 s[0] ,但之後的 Long String 便不是了,
所以要盡量使用 Length() 函數來存取字串長度,因為 Borland 不保證以後
長度=s[0] 依舊存在。


to reno:
我知道不難,事實上,我目前也是使用自己寫的函數在使用,可是,如果 Deplphi 原
本就提供此轉換函數的話,那我還自己寫!?

to 郭靖:
實際上, AnsiString 最大使用範圍高達 2GB ,很多檔案處理函數也有使用 string
如果它一遇到 #0 便結束,那....那些函數不就完蛋了!
 
我不知道你的资料是什么,可能在理解上,这些大师们也有出入吧。

我还是比较信任 Macro Cantu 的。在他的《Delphi 高级开发指南》
中,的确说的是长字符串的问题,而不是 Short String。并且提供
了一个很完整的测试,即计算:Pascal Size 及 PChar Size.

有一点肯定的是:这个没有归档的属性很难保证以后还能用 ------
但到目前为止,Delphi 还一直使用着这种方法,也许是因为这样访
问不安全,会给 Delphi 对 AnsiString 的管理带来混乱,所以不
推荐 ----------- 我的想法。

其实,从 PChar 的转换就可以看出了,PChar 实际并没有拷贝串,
而是将指针定位到 S[0]。
 
顶部