char 数组转化成string时候得奇怪问题(刚才那一到里面有乱码,不能显示了,sorry)(200分)

  • 主题发起人 主题发起人 qdlover
  • 开始时间 开始时间
Q

qdlover

Unregistered / Unconfirmed
GUEST, unregistred user!
字符数组
ModalNumber : array[0..39] of char;
SerialNumber : array [0..19] of char;
ControlNum : array[0..7]of char;
转化成字符串变量
pSerialNumber:widestring;
pModalNumber:widestring;
pControlNum:widestring;

在程序里面用
pserialnumber=SerialNumber 没问题

可是写成asp组件就有问题了

总是显示乱码,因为他用的是olevariant类型的变量,这种变量难道需要特别的转化吗?

定义
type DRIVER_INFO_OK = record
ModalNumber : array[0..39] of char;
SerialNumber : array [0..19] of char;
ControlNum : array[0..7]of char;
DriveType : dword;
Cylinders : dword;
Heads : dword;
Sectors : dword;
end;
var
pSerialNumber:string;
pModalNumber:string;
pControlNum:string;
pHardDriveComputerID:int64;

程序赋值
pSerialNumber:=x.SerialNumber;
pModalNumber:=x.ModalNumber;
pControlNum:=x.ControlNum;
pHardDriveComputerID:=getHardDriveComputerID;

组件属性

function Tserver.Get_ControlNum: WideString;
begin
Get_ControlNum:=StringToOleStr(pControlNum);
end;

function Tserver.Get_HardDriveComputerID: WideString;
begin
Get_HardDriveComputerID:=inttostr(pHardDriveComputerID);
end;

function Tserver.Get_ModalNumber: WideString;
begin
Get_ModalNumber:=StringToOleStr(pModalNumber);
end;

function Tserver.Get_SerialNumber: WideString;
begin
Get_SerialNumber:=StringToOleStr(pSerialNumber);
end;

乱码亚

而且每次的乱码都不一样亚
本来应该是这个样子
3CW03R10
ST315320A
3.12
可是现在全是乱码,我不敢copy到这里面来,否则页面就乱套了
好像是字符串没有用0正常结束吧?
 
用 PCHAR()函数对字符串过滤一道试一试
 
function Tserver.Get_ControlNum: WideString;
var
S: string;
begin
S := pControlNum;
Get_ControlNum:=StringToOleStr(S);
end
 
都试过了,没用

:((((((((((((
 
改用:
ModalNumber : array[0..39] of widechar;

还有,你的返回值应该是wideString, 看起来好象转倒了。
 
还是不行
源代码如下
unit server;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, AspTlb, diskid_TLB, StdVcl,types,SysUtils;

type
Tserver = class(TASPObject, Iserver)
protected
procedure OnEndPage; safecall;
procedure OnStartPage(const AScriptingContext: IUnknown); safecall;
procedure get_diskinfo; safecall;
function Get_ControlNum: WideString; safecall;
function Get_HardDriveComputerID: WideString; safecall;
function Get_ModalNumber: WideString; safecall;
function Get_SerialNumber: WideString; safecall;
end;
function IsWinNT:boolean;
stdcall; external 'DiskID.dll'
name 'IsWinNT';
function ReadPhysicalDrive(driveID:integer;buffer:Pointer;bufLen:integer):integer;
stdcall; external 'DiskID.dll'
name 'ReadPhysicalDriveInNT';
function ReadPhysicalDrive9X(driveID:integer;buffer:Pointer;bufLen:integer):integer;
stdcall; external 'DiskID.dll'
name 'ReadDrivePortsInWin9X';
function getHardDriveComputerID:int64;
stdcall; external 'DiskID.dll'
name 'getHardDriveComputerID';

type DRIVER_INFO_OK = record
ModalNumber : array[0..39] of widechar;
SerialNumber : array [0..19] of widechar;
ControlNum : array[0..7]of widechar;
DriveType : dword;
Cylinders : dword;
Heads : dword;
Sectors : dword;
end;
var
pSerialNumber:string;
pModalNumber:string;
pControlNum:string;
pHardDriveComputerID:int64;
implementation

uses ComServ;

procedure Tserver.OnEndPage;
begin
inherited OnEndPage;
end;

procedure Tserver.OnStartPage(const AScriptingContext: IUnknown);
begin
inherited OnStartPage(AScriptingContext);
end;

procedure Tserver.get_diskinfo;
var
x:DRIVER_INFO_OK;
intRet:integer;
i:integer;
begin
if IsWinNT then
ReadPhysicalDrive(0,@x,256)
else
ReadPhysicalDrive9X(0,@x,256);
pserialnumber:='';
pSerialNumber:=x.SerialNumber;
pModalNumber:=x.ModalNumber;
pControlNum:=x.ControlNum;
pHardDriveComputerID:=getHardDriveComputerID;
end;

function Tserver.Get_ControlNum: WideString;
begin
Get_ControlNum:=StringToOleStr(pControlNum);
end;

function Tserver.Get_HardDriveComputerID: WideString;
begin
Get_HardDriveComputerID:=inttostr(pHardDriveComputerID);
end;

function Tserver.Get_ModalNumber: WideString;
begin
Get_ModalNumber:=StringToOleStr(pModalNumber);
end;

function Tserver.Get_SerialNumber: WideString;
begin
Get_SerialNumber:=StringToOleStr(pSerialNumber);
end;

initialization
TAutoObjectFactory.Create(ComServer, Tserver, Class_server,
ciMultiInstance, tmApartment);
end.
 
在你的uses中加入sharemem单元的声明
 
加了sharemem声明以后
然后一编译,delphi32异常错误了
 
200大分啊……只恨自己越来越不会Delphi了,如果是CB的话,应该能很快帮你搞
定的。
我感觉主要是处理宽字符串方面的问题,Delhpi对宽字符串的支持很差。
我看到你的下面一段程序中,DRIVER_INFO_OK结构成员使用了WideChar数组,这
是你调用的那个动态链接库所必需的吗?如果不是的话,请不要使用WideChar数
组。在Delphi中,Char数组可以方便地作为字符串来使用,但使用WideChar数组
就不同了。如果你知道被调用的那个动态库是怎么实现的就好办了……
 
在你的uses中加入sharemem单元的声明时,它必须是位于第一位置!!
另外在你的声明中:
SerialNumber : array [0..19] of widechar;这是一个以windechar为基类的零基字符数组。这
种类型和pchar类型是赋值兼容的而与pSerialNumber:string;这种delphi的数组之间赋值是不能直
接进行的(其它类同)。可以这样写:
pSerialNumber:=strpas(pchar(x.serialNumber));

对于字符型的变量赋值相容如下这:
[red]T1 is PChar or any string type and the expression is a string constant.
T1 and T2 are both string types.
T1 is a string type and T2 is a Char or packed-string type.
T1 is a long string and T2 is PChar.
T1 and T2 are compatible packed-string types.
T1 and T2 are compatible set types.
T1 and T2 are compatible pointer types.
T1 and T2 are both class, class-reference, or interface types and T2 is a derived from T1.
T1 is an interface type and T2 is a class type that implements T1.
T1 is PChar or PWideChar and T2 is a zero-based character array of the form array[0..n] of Char.[/red]
 
用widechar是别人说的,本来是char和string互相赋值的
sharemem位于第一,我这里也会出错,所以放弃了
pSerialNumber:=strpas(x.serialNumber);这个样子可以,但是结果一样

我用
temp:='12345678901234567890123456789012345678901234567890';
for i:=0 to length(x.SerialNumber )-1 do
begin
temp:=x.SerialNumber;
end;
temp[i+1]:=#0;
pSerialNumber:=temp;
不行
temp:='12345678901234567890123456789012345678901234567890';
for i:=0 to length(x.SerialNumber )-1 do
begin
temp[i+1]:=x.SerialNumber;
end;
temp[i+1]:=#0;
pSerialNumber:=temp;
不行
temp:='12345678901234567890123456789012345678901234567890';
for i:=0 to length(x.SerialNumber )-1 do
begin
temp:=x.SerialNumber;
end;
pSerialNumber:=strpas(temp);
不行
temp:='12345678901234567890123456789012345678901234567890';
for i:=0 to length(x.SerialNumber )-1 do
begin
temp[i+1]:=x.SerialNumber;
end;
pSerialNumber:=strpas(temp);
不行

可是明明在应用程序里面没有错误,写成asp组件就会出错,而且
我在里面用
response.write(temp);就是乱码了
不明白呀,不明白
 
charset="gb2312"
 
不是你的系统字体有问题了吧
 
程序没问题说明很有可能是ASP写制的问题,不过我也不懂,UP!
 
ASP 的字符串全是双字节进行处理的.

把你的 string 声明为 wideString
char 为 wideChar

另外,你的 HTML 输出有没有指定 charset:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>

还有直接写行不行:
response.write("我要输出中文");
 
调用没有问题
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<%
set getdiskid=server.CreateObject ("diskid.server")
getdiskid.get_diskinfo
Response.Write "中文SerialNumber:"&getdiskid.SerialNumber &"<BR>"
Response.Write "ModalNumber:"&getdiskid.ModalNumber &"<BR>"
Response.Write "ControlNum:"&getdiskid.ControlNum &"<BR>"
Response.Write "HardDriveComputerID:"&getdiskid.HardDriveComputerID &"<BR>"
%>

我现在脑子有点乱
一会儿说用char,string,一会儿说用widechar,widestring

我程序都改乱套了
 
function Get_ControlNum: OleVariant; safecall;
function Get_HardDriveComputerID: OleVariant; safecall;
function Get_ModalNumber: OleVariant; safecall;
function Get_SerialNumber: OleVariant; safecall;
 
还没有结束?我相信这不是一个复杂的问题,只是被人为地搞昏了头,让我们从以下方面来
分析,相信问题会很快解决:
1、DRIVER_INFO_OK结构的几个成员是否一定要定义为WideChar数组?
这取决于ReadPhysicalDrive函数采用的参数里采用的是哪种数据类型,如果没有特别的
情况,没人会在普通的动态库里使用宽字符串类型。所以,请先不要考虑将你的结构成员
使用为WideChar数组,而应该是Char数组。

2、几个组件方法(如Get_ControlNum等)的返回值类型是什么?
即:在TypeLibrary中编辑.TLB时,其返回值是什么?是BSTR吧(对应到Delphi中就是
WideString),那就对了。请不要随意使用Variant/OleVariant,天哪,我不知道为什么
那么多人喜欢使用Variant,它不但处理速度慢,而且把本来一些很清晰的数据类型概念
搞混淆。除了在常用数据类型中不能处理或不便处理的情况外,请不要滥用Variant!建议
好好看看Marco Cantu的《Delphi X 从入门到精通》(X代表从3到6)。

方法1:
OK,现在请尝试将DRIVER_INFO_OK结构的几个成员定义为Char数组(像你的问题开头给出的
那样),并且几个对象方法的返回值类型为BSTR,你会发现结果一切正常。

方法2:
将那个几对象方法定义为无返回值(Procedure),这样实现:
MIDL定义: HRESULT _stdcall GetControlNum( void );
Delphi实现:
procedure Tserver.Get_ControlNum;
begin
Response.Write(pControlNum);
end;
ASP调用:
Response.Write(Obj.GetControlNum & "<br>")

实际上你可以先试第二种方法,如果输出的是仍是乱码,想都不用想都知道错并不是出在输
出部分,而是出在输入部分,即:采用在IVER_INFO_OK结构中的那些成员根本就不应该使用
WideChar数组,而应该使用Char数组。此外,在Tserver.get_diskinfo过程中,在调用动态
库中的函数给IVER_INFO_OK结构类型的变量赋值时,应该将该结构所占的内存区进行填充:
ZeroMemory(@x, SizeOf(x)),这样数据会更规则、干净,程序不容易出错。
其它:几个全局变量字符串使用WideString或AnsiString是没有关系的,使用WideString应
该会更快一点,因为在这个场合下它少了两次数据复制的过程(但速度的差别你是不容易感
觉出来的)
 
谢谢这么详细地回答
可是
这个样子改了之后就又跟我原来的程序一样了,还是不对呀
如果加了ZeroMemory(@x,SizeOf(x));,那么字符串都不返回了,是空的

但是其中一个整数类型参数却仍然可以返回,而且结果正确

无论什么情况下,这个整数类型的参数都可以正确地返回,那几个widestring类型却怎么也不行

搞不清楚了


unit server;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, AspTlb, diskid_TLB, StdVcl,types,SysUtils,windows;

type
Tserver = class(TASPObject, Iserver)
protected
procedure OnEndPage; safecall;
procedure OnStartPage(const AScriptingContext: IUnknown); safecall;
procedure get_diskinfo; safecall;
function Get_ControlNum: WideString; safecall;
function Get_HardDriveComputerID: WideString; safecall;
function Get_ModalNumber: WideString; safecall;
function Get_SerialNumber: WideString; safecall;
end;
function IsWinNT:boolean;
stdcall; external 'DiskID.dll'
name 'IsWinNT';
function ReadPhysicalDrive(driveID:integer;buffer:Pointer;bufLen:integer):integer;
stdcall; external 'DiskID.dll'
name 'ReadPhysicalDriveInNT';
function ReadPhysicalDrive9X(driveID:integer;buffer:Pointer;bufLen:integer):integer;
stdcall; external 'DiskID.dll'
name 'ReadDrivePortsInWin9X';
function getHardDriveComputerID:int64;
stdcall; external 'DiskID.dll'
name 'getHardDriveComputerID';

type DRIVER_INFO_OK = record
ModalNumber : array[0..39] of char;
SerialNumber : array [0..19] of char;
ControlNum : array[0..7]of char;
DriveType : dword;
Cylinders : dword;
Heads : dword;
Sectors : dword;
end;
var
pSerialNumber:widestring;
pModalNumber:widestring;
pControlNum:widestring;
pHardDriveComputerID:int64;
implementation

uses ComServ;

procedure Tserver.OnEndPage;
begin
inherited OnEndPage;
end;

procedure Tserver.OnStartPage(const AScriptingContext: IUnknown);
begin
inherited OnStartPage(AScriptingContext);
end;

procedure Tserver.get_diskinfo;
var
x:DRIVER_INFO_OK;
intRet:integer;
i:integer;
temp:widestring;
begin

ZeroMemory(@x,SizeOf(x));

if IsWinNT then
ReadPhysicalDrive(0,@x,256)
else
ReadPhysicalDrive9X(0,@x,256);

pSerialNumber:=x.SerialNumber;
pModalNumber:=x.ModalNumber;
pControlNum:=x.ControlNum;
pHardDriveComputerID:=getHardDriveComputerID;
end;

function Tserver.Get_ControlNum: WideString;
begin
Get_ControlNum:=pControlNum;
end;

function Tserver.Get_HardDriveComputerID: WideString;
begin
Get_HardDriveComputerID:=inttostr(pHardDriveComputerID);
end;

function Tserver.Get_ModalNumber: WideString;
begin
Get_ModalNumber:=pModalNumber;
end;

function Tserver.Get_SerialNumber: WideString;
begin
Get_SerialNumber:=pSerialNumber;
end;

initialization
TAutoObjectFactory.Create(ComServer, Tserver, Class_server,
ciMultiInstance, tmApartment);
end.
 
将代码上传到www.playicq.com上让大家帮忙看看![8D]
 
后退
顶部