只要看5行代码,搞定者300大洋拿去!有关WideString 与 String的问题。 ( 积分: 300 )

  • 主题发起人 主题发起人 geng7758
  • 开始时间 开始时间
procedure TForm1.Button1Click(Sender: TObject);
var
Str: string;
WStr: WideString;
begin
Str :=Chr($81)+Chr(0);
ShowMessage(IntToStr(Length(Str)));
showmessage(str);
WStr :=Str;
Str :=WStr;
ShowMessage(IntToStr(Length(Str)));
showmessage(wstr);
end;
 
就是delphi已经提供的功能,但在英文的NT环境下可能会发生???的错误,具体为什么请自己检查delphi为什会这样了。
 
$80可能超过标准ASCII的范围
这个转换上可能是不一样的
 
function WideStringToString(const WS: WideString
CodePage: Word): String;
var
L: Integer;
begin
L := WideCharToMultiByte(CodePage, 0, PWideChar(WS), -1, nil, 0, nil, nil);
SetLength(Result, L);
if WideCharToMultiByte(CodePage, 0, PWideChar(WS), -1, PChar(Result), L, nil, nil) = 0 then
begin
case GetLastError of
ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER:
Result := '';
end;
end;
end;

procedure TForm1.btn1Click(Sender: TObject);
var
Str: string;
WStr: WideString;
begin
Str := Chr($81) + Chr(1);//注意81前面有个$,其实就是要试大于128的字符
ShowMessage(IntToStr(Length(Str)));
WStr := Str;
ShowMessage(IntToStr(Length(WStr)));
//Str := WStr;//这一步就拜托各位加些冬冬了
Str := WideStringToString(WStr, CP_ACP);
ShowMessage(IntToStr(Length(Str)));//如果这里显示2,那就可能对了
end;
 
function WideStringToString(const WS: WideString
CodePage: Word): String;
var
L: Integer;
begin
L := WideCharToMultiByte(CodePage, 0, PWideChar(WS), -1, nil, 0, nil, nil);
SetLength(Result, L);
if WideCharToMultiByte(CodePage, 0, PWideChar(WS), -1, PChar(Result), L, nil, nil) = 0 then
begin
case GetLastError of
ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER:
Result := '';
end;
end;

Result := Copy(Result, 0, L - 1)
//除去#0(字符串结束符)
end;

procedure TForm1.btn1Click(Sender: TObject);
var
Str: string;
WStr: WideString;
begin
Str := Chr($C4) + Chr($E3)
//你
Str := Chr(81) + Chr(1);//注意81前面有个$,其实就是要试大于128的字符
ShowMessage(IntToStr(Length(Str)));
WStr := Str;
ShowMessage(IntToStr(Length(WStr)));
//Str := WStr;//这一步就拜托各位加些冬冬了
Str := WideStringToString(WStr, CP_ACP);
ShowMessage(IntToStr(Length(Str)));//如果这里显示2,那就可能对了
ShowMessage(Str);
end;
 
WStr := Str;
编译器生成的汇编代码:
8D45F8 lea eax,[ebp-$08]
8B55FC mov edx,[ebp-$04]
E80A4AF7FF call @WStrFromLStr
WStrFromLStr调用了WStrFromPCharLen,WStrFromPCharLen调用了WCharFromChar,而WCharFromChar又最终调用了MultiByteToWideChar来实现Ansi字符串->Unidoce字符串的转换。
$81$1,String->WideString,认为是一个MBCS字符,可是在Unicode码表中又找不到对应的字符,于是乎,就只好用一个UnknownChar “?”来代替啦。
 
楼主拿分来[:)]

请看下面的讨论:

http://www.01cn.net/cgi-bin/topic_show.cgi?id=1224&h=1&bpg=3&age=0
 
To 寻路:
没用
To lichengbin:
关键可能就是你所说的“在Unicode码表中又找不到对应的字符,于是乎,就只好用一个UnknownChar”,也就是说String和WideString有时候并不能互换的!
To 千中元:
里面没说到关键
To All:
各位还有别的招么?没有的话300大元属于lichengbin兄了~
 
可以这样。
procedure TForm1.Button1Click(Sender: TObject);
var
Str: string;
WStr: WideString;
begin
Str := Chr($81) + Chr($1);//注意81前面有个$,其实就是要试大于128的字符
WStr := PWideChar(Pointer(Str));
Str := PChar(Pointer(WStr));
Memo1.Lines.Add(IntToStr(Length(Str)));
end;
 
To lichengbin:
OK!不过这种方式还有个问题,当中间有个#0时就会被截断,例如:
Str := Chr($81) + Chr($0) + Chr($1);//Length(Str) = 3

//转换后Length(Str) = 1;
还有办法么?
 
那就这样,呵呵
var
Str: string;
WStr: WideString;
begin
Str := #$81#0#1;

SetLength(string(Pointer(WStr)), Length(Str));
// 调试:
// Evaluate/Modify(Ctrl+F7): PInteger(Integer(Pointer(WStr))-4)^,这里存放的
// 是字符串的长度,可以看到现在以AnsiString类型方式分配内存的WStr的长度是3

Move(Pointer(Str)^, Pointer(WStr)^, Length(Str));

Str := '';
SetLength(Str, Length(string(Pointer(WStr))));
Move(Pointer(WStr)^, Pointer(Str)^, Length(Str));

Memo1.Lines.Add(IntToStr(Length(Str)));

// 切记:
// 要手工释放宽字符串WStr的内存,因为我们把它当作AnsiString来分配内存和使用的,
// 这里它的长度是3,如果让Delphi自动释放的话,它将调用SysFreeString来试图释放
// WStr的不是用SysAllocString分配的内容,这是不正确的。
string(Pointer(WStr)) := '';
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
Str: string;
WStr: WideString;
begin
Str := Chr($81) + Chr(1);//注意81前面有个$,其实就是要试大于128的字符
ShowMessage(IntToStr(Length(Str)));
WStr := Str;
ShowMessage(IntToStr(Length(Str)));
Str[1] := PChar(WStr)^
//这一步就拜托各位加些冬冬了
//Str[2] := WStr[2];
ShowMessage(IntToStr(Length(Str)));//如果这里显示2,那就可能对了
end;
 
string的使用分两种,一种是确实的字符串,另一种是存储二进制数据.
因此我想这个问题,没有意义.如果你发现存储了某个确实的字符串,然后转换出了问题,这才有用.
 

Similar threads

后退
顶部