Converting Integer number into hexadecimal number in delphi 7

2.1k views Asked by At

Write a program to convert an integer number to its hexadecimal representation without using inbuilt functions.

Here is my code, but it is not working. Can anyone tell where is the mistake?

It is giving an error:

"Project raised exception class EAccessViolation with message 'Access violation at address 00453B7B in module 'Project.exe'.Write of address FFFFFFFF'.Process stopped.Use Step or Run to continue."

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.
2

There are 2 answers

0
Ken Bourassa On

First mistake : String are 1 indexed. Meaning that the index of their first character is 1 and not 0. You initialize "i" to 0 and then try to set hexnumber[i].

Second mistake : Strings might be dynamic, but they don't grow automatically. If you try to access the first character of an empty string, it won't work. You need to call SetLength(HeXNumber, NumberOfDigits). You can calculate the number of digits this way :

NumberOfDigits := Trunc(Log16(integernum)) + 1;

Since Log16 isn't really something that exists, you can either use LogN(16,integernum) or (Log(IntegerNum) / Log(16)) depending on what is available in your version of Delphi.

Note that this might return an invalid value for very, very large value (high INT64 range) due to rounding errors.

If you don't want to go that road, you could replace the instruction by

hexnumber := hexvalue(integernum mod 16) + hexnumber;

which would also remove the need to invert the string at the end.

Third Mistake : Using unsigned integer for loop variable. While this is debatable, the instruction

for I := 0 to Count - 1 do

is common practice in Delphi without checking Count > 0. When count = 0 and using an unsigned loop counter, you'll either get an integer overflow (if you have them activated in your project options) or you'll loop High(I) times, which isn't what you want to be doing.

Fourth mistake : already mentionned : Result:=Chr(num) should be replaced by something like Result := InttoStr(Num)[1]. Personally, I'd implement the function using an array.

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;
0
Tom Brunberg On

Since this obviously is a homework assignment, I don't want to spoil it for you and write the solution, but rather attempt to guide you to the solution.

User input
In real code you would need to be prepared for any mistake from the user and check that the input really is integer numbers only and politely ask the user to correct the input if erroneous.

Conversion loop
You have got that OK, using mod 16 for each nibble of integernum and div 16 to move to the next nibble, going from units towards higher order values.

Conversion of nibble to hex character
Here you go wrong. If you would have written out also the cases for 0..9, you could have got the case statement right. As others have commented, Chr() takes an ASCII code. However, using a case statement for such a simple conversion is tedious to write and not very efficient.
What if you would have a lookup table (array) where the index (0..15) directly would give you the corresponding hex character. That would be much simpler. Something like

const
  HexChars: array[_.._] of Char = ('0',_____'F')

I leave it to you to fill in the missing parts.

Forming the result (hex string)
Your second major mistake and the reason for the AV is that you did not set the length of the string hexnumber before attempting to acess the character positions. Another design flaw is that you fill in hexnumber backwards. As a result you then need an extra loop where you reverse the order to the correct one.
There are at least two solutions to solve both problems:

  1. Since you take 32 bit integer type input, the hex representation is not more than 8 characters. Thus you can preset the length of the string to 8 and fill it in from the lower order position using 8 - i as index. As a final step you can trim the string if you like.
  2. Don't preset the length and just concatenate as you go in the loop hexnumber := HexChars[integernum mod 16] + hexnumber;.

Negative values
You did not in any way consider the possibility of negative values in your code, so I assume it wasn't part of the task.