编写一个程序,将整数转换为十六进制表示,而不使用内置函数。
这是我的代码,但它不起作用。谁能说出错误在哪里?
发出错误:
“项目引发异常类EAccessViolation,消息'模块'Project.exe'中的地址00453B7B处的访问冲突。地址FFFFFFFF'。写入停止。使用步骤或运行继续。”
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms,
Dialogs;
type
TForm1 = class(TForm)
end;
function hexvalue(num:Integer):Char;
var
Form1: TForm1;
implementation
{$R *.dfm}
function hexvalue(num:Integer):Char;
begin
case num of
10: Result:='A';
11: Result:='B';
12: Result:='C';
13: Result:='D';
14: Result:='E';
15: Result:='F';
else Result:=Chr(num);
end;
end;
var
intnumber,hexnumber,actualhex:String;
integernum:Integer;
i,j,k:Byte;
begin
InputQuery ('Integer Number','Enter the integer number', intnumber);
integernum:=StrToInt(intnumber);
i:=0;
while integernum >= 16 do
begin
hexnumber[i]:=hexvalue(integernum mod 16);
integernum:= integernum div 16;
Inc(i);
end;
hexnumber[i]:= hexvalue(integernum);
k:=i;
for j:=0 to k do
begin
actualhex[j]:= hexnumber[i];
Dec(i);
end;
ShowMessage(actualhex);
end.
答案 0 :(得分:3)
第一个错误:String是1索引的。意味着它们的第一个字符的索引是1而不是0.您将“i”初始化为0然后尝试设置hexnumber [i]。
第二个错误:字符串可能是动态的,但它们不会自动增长。如果您尝试访问空字符串的第一个字符,它将无法工作。您需要调用SetLength(HeXNumber, NumberOfDigits )。您可以通过这种方式计算位数:
NumberOfDigits := Trunc(Log16(integernum)) + 1;
由于Log16实际上不存在,您可以使用LogN(16,integernum)或(Log(IntegerNum)/ Log(16)),具体取决于您的Delphi版本中的可用内容。
请注意,由于舍入错误,这可能会为非常非常大的值(高INT64范围)返回无效值。
如果您不想走这条路,可以用
替换指令hexnumber := hexvalue(integernum mod 16) + hexnumber;
这也可以消除最后反转字符串的需要。
第三个错误:对循环变量使用无符号整数。虽然这是有争议的,但指令
for I := 0 to Count - 1 do
是Delphi中不常检查Count > 0
的常见做法。当count = 0并使用无符号循环计数器时,您将获得整数溢出(如果您在项目选项中激活它们)或者您将循环高(I)次,这不是您想要的做。
第四个错误:已经提到:Result:=Chr(num)
应该被Result := InttoStr(Num)[1]
之类的东西取代。
就个人而言,我将使用数组实现该功能。
HexArr : Array[0..15] of char = ('0', '1',...,'D','E','F');
begin
if InRange(Num, 0, 15) then
Result := HexArr[Num]
else
//whatever you want
end;
答案 1 :(得分:3)
由于这显然是一项家庭作业,我不想为你破坏它并编写解决方案,而是试图引导你找到解决方案。
用户输入
在实际代码中,您需要为来自用户的任何错误做好准备,并检查输入是否仅为整数,并礼貌地要求用户在错误时更正输入。
转换循环
您可以使用mod 16
为integernum
和div 16
的每个半字节移动到下一个半字节,从单位向更高阶的值。
将半字节转换为十六进制字符
你错了。如果您还要写出0..9的案例,那么您可以正确地使用case
语句。正如其他人所评论的那样,Chr()
采用ASCII码。但是,使用case
语句进行这种简单的转换是一件非常繁琐的写法,而且效率不高
如果你有一个查找表(数组),索引(0..15)直接给你相应的十六进制字符,该怎么办?这会简单得多。像
const
HexChars: array[_.._] of Char = ('0',_____'F')
我留给你填写缺失的部分。
形成结果(十六进制字符串)
您的第二个主要错误和AV的原因是您在尝试访问字符位置之前未设置字符串hexnumber
的长度。另一个设计缺陷是向后填充hexnumber
。因此,您需要一个额外的循环,您可以将订单转换为正确的顺序
至少有两种解决方案可以解决这两个问题:
integer
类型输入,因此十六进制表示不超过8个字符。因此,您可以将字符串的长度预设为8,并使用8 - i
作为索引从低位置填充。作为最后一步,您可以根据需要修剪弦乐。 hexnumber := HexChars[integernum mod 16] + hexnumber;
中进行连接。 负值
您没有以任何方式考虑代码中负值的可能性,因此我认为它不是任务的一部分。