Delphi: Help needed with errors with strings and integers - delphi

I need to make a 'Calculator' that works out and average for 3 different marks.
procedure TForm1.btnAddClick(Sender: TObject);
var
sName : string;
iprac, itheory, iproject : integer;
begin
sName := edtStudentName.text;
iprac := sedPrac.value;
iTheory := sedTheory.Value;
iProject := sedProject.Value;
lblOutput.caption := sName + ' You got ' + IntToStr (iPrac + iTheory + iProject) / 3;
end;
end.
Thats the code so far, but I get an error:
[Error] ComputerStudyMarks_u.pas(46): Incompatible types: 'String' and 'Integer'
Please be patient with me! I am a hardcore noob but this is for school.
Maybe someone can help me with this program.
I am busy using the book "Enjoy Delphi" and the code I am copying from the book itself is giving me an error.
Any help would be much appreciated!
P.S I cant add a picture of the form because I dont have enough reputation :(

iprac := sedPrac.value;
It's not clear what sedPrac is. And therefore what the Value property it. If Value is a string then you cannot assign a string to an integer. Your would need to convert to integer first, like this:
iprac := StrToInt(sedPrac.value);
Likewise for iTheory and iProject.
Of course, it may be that Value is already an integer, in which case your code is fine. My best guess is that these variables refer to TSpinEdit controls, and that Value is an integer, and so all is well. But that is just a guess.
IntToStr (iPrac + iTheory + iProject) / 3
Now, IntToStr is a function that returns a string. And there is no / operator defined for strings. Presumably you meant to write:
IntToStr((iPrac + iTheory + iProject) div 3)
Note that you have to use div since the value is an integer and / is floating point division.
Some final pieces of advice.
When presenting code, present all the information. You omitted to present some types here and so we don't know what sedPrac is.
When you present an error message, make sure that we can marry up the line number in the message with the code that you present. In your question, we don't know which line is line 46.

Related

Converting Integer number into hexadecimal number in delphi 7

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.
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:
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.
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.
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;

Delphi TValueListEditor Strings prop-ed quirk?

Investigating odd behaviour of a TValueListEditor being used to generate a filter
expression for a ClientDataSet, I've traced it to a situation where if the first entry
in it apparently had nothing in the Value column, it returned #13#10 as the Value, rather than
''.
In the following, the TStringlist TL is initialized with the same contents as the ValueListEditor
Strings property has in my app. The Assert does not fail for the TStringlist, but it does for the
ValueListEditor. These results occurred with D7 and XE4.
procedure TDefaultForm.ApplyFilter;
var
i,
Max : Integer;
Key,
Value : String;
TL : TStringlist;
begin
TL := TStringlist.Create;
try
TL.Add('Country=');
TL.Add('Class=CON');
for i:= 0 to TL.Count - 1 do begin
Key := TL.Names[i];
Value := TL.Values[Key];
Assert(Value <> #13#10); // succeeds for all i
end;
Max := ValueListEditor1.RowCount;
for i:= 1 to Max do begin
Key := ValueListEditor1.Keys[i];
Value := ValueListEditor1.Values[Key];
// Value := ValueListEditor1.Strings.ValueFromIndex[i-1];
Assert(Value <> #13#10); //Fails for i = 1!
end;
finally
TL.Free;
end;
end;
Btw, the TVLE was set up entirely in the Object Inspector: I simply dragged a TVLE off the palette, clicked Strings in the OI, clicked in the LH cell and typed 'Country' (sans quotes), pressed the Down key and typed 'Class' then right-arrow and typed 'CON'.
Obviously, I could avoid this by Value := Trim(Value), but was curious where the #13#10 was coming from.
Update: Prompted by #Deltic's answer and helpful comments, I decided to re-trace my steps and added another TVLE to my form. The following extracts from the DFM are revealing:
object ValueListEditor1: TValueListEditor
Left = 16
Top = 224
Width = 306
Height = 135
KeyOptions = [keyEdit, keyAdd]
Strings.Strings = (
'Country='#13#10
'Class=CON')
TabOrder = 2
end
[...]
object ValueListEditor2: TValueListEditor
Left = 440
Top = 192
Width = 306
Height = 246
KeyOptions = [keyEdit, keyAdd]
Strings.Strings = (
'A='
'B=ValueOfB')
TabOrder = 5
end
So, with hindsight, my question really boils down to how did the #13#10 get into the DFM? And then it came back to me ...
With no previous experience of the TVLE, when I set up the form, I got stuck at the point where I needed to add a second row. I tried pressing [Enter], but that did nothing, so then I tried Ctrl-Enter and that did nothing either. But repeating the exercise now has confirmed that that's how the CR/LF got into the TVLE's Strings.
So, it seems that the answer to my q is "No, the TVLE isn't broken, but its Strings property editor
has a quirk regarding Ctrl-Enter". In other circs, I would consider deleting my q, seeing as it's at least partly caused by operator aberration, but perhaps it's better left to assist any others who trip over the same point.
Update #2 I see that my curiousity has earned me a -1. Fair enough, but I'm still inclined to leave this q & a in place, if only as an illustration of the fact that problems have deterministic causes, which can often be identified by simple things such as re-tracing one's steps, particularly with someone obviously knowledgeable looking over one's shoulder, as it were. Perhaps the down-voter would care to enlighten readers what help to future readers such a silent -1 is.
You have not shown how your value list editor is initialised, and I suspect that this is where your problem is. Behind a TValueListEditor is nothing more than a TStringList (strictly speaking a subclass of one, but the subclass doesn't change the fundamental behaviour w.r.t named values).
If your apparently empty value in the value list is yielding a value of #13#10 then it must be because that is the actual value that it has.
This simple test snippet verifies this:
var
i:Integer;
k, v:String;
begin
ed.InsertRow('Country', '', TRUE);
ed.InsertRow('Class', 'CON', TRUE);
for i:= 1 to ed.RowCount - 1 do
begin
k := ed.Keys[i];
v := ed.Values[k];
ASSERT(v <> #13#10); // Never fails
end;
end;
Where ed is a TValueListEditor on the form.
Replace the first line of code in the above snippet with this however:
ed.InsertRow('Country', #13#10, TRUE);
And the ASSERT() fails.
I suggest you investigate the initialisation of your value list editor. My guess is that it is being populated by reading from a file using a mechanism which is reading the entire line into a string, including the line end sequences, and the code that is adding the values for each read line is not stripping the #13#10 line terminators, resulting in the values being added as <name>=<value>#13#10 in each case.

How to include a variable between strings in Delphi?

procedure TForm1.Button1Click(Sender: TObject);
var
xlap,xlbook,xlsheet:variant;
y:integer;
begin
xlap:=createoleobject('excel.application');
xlbook:=xlap.workbooks.add;
xlap.visible:=true;
xlsheet:=xlbook.worksheets.add;
for y:=1 to 50 do
begin
xlsheet.cells[y,2].value:= concat('=IF(A',y,'>6,"Good","Bad")')
inc(y);
end;
end;
That's my code to make an Excel through Delphi. I want to input the IF formula into column B of the Excel, but there is error when I use the concat('=IF(A',y,'>6,"Good","Bad")').
May be I need another way to include y between those strings.
Any suggestion? Thanks before
Delphi has a format statement bit like sprintf printf in c, well nearly
xlsheet.cells[y,2].value:= format('=IF(A%d>6,"Good", "Bad")',[y])
%d is a place holder for an int. Look it up for loads of other stuff.
NB the variables you want to interpolate are assed in an array.
In addition to Tony's answer about Format, here are a couple of other approaches. (Format is great if you have mixed types or many values, but it carries some overhead that might not be needed.)
You can concatenate strings with a simple + - in fact, the Concat documentation says it does the same thing but is faster:
Temp := 'ing';
Str := 'Test' + Temp; // Str = 'Testing'
As your y variable is an integer, you'll need to convert it to a string first (note you don't need to Inc(y);, as the loop will do that already - it's automatically incremented from the starting value to the ending value on each pass through the loop):
for y:=1 to 50 do
begin
xlsheet.cells[y,2].value:= '=IF(A' + IntToStr(y) + '>6,"Good","Bad")';
end;

Algol60 passing integer element of array as parameter - error bad type

I have following problem.
When I try to run the code with arun file.obj (I have compiled with algol.exe file)
BEGIN
INTEGER PROCEDURE fun(tab,index,lower,upper);
INTEGER tab,index,lower,upper;
BEGIN
INTEGER t;
text (1, "Start");
t := 0;
FOR index := lower STEP 1 UNTIL upper DO
t := t + tab;
fun := t;
END;
INTEGER ARRAY t[1:10];
INTEGER i,result,lower,upper;
lower := 1;
upper := 10;
FOR i := 1 STEP 1 UNTIL 10 DO
t[i] := i;
i := 1;
result := fun(t[i],i,lower,upper);
END FINISH;
I am still getting error:
ERROR 3
ADD PBASE PROC LOC
07D4 0886 1 13
083A 0842 0 115
The compiler I use is "The Rogalgol Algol60" product of RHA (Minisystems) Ltd.
Error 3 means "3 Procedure called where the actual and the formal parameter types do not match."
But I do not understand why. The reason of error is t[i] (If I change to i - it is ok).
Someone knows what I am doing wrongly?
I compile the code on the dosbox (linux)
Problem is that the index of the integer array that you're passing to your procedure isn't the same as the integer that he's expecting. I can't remember what an integer array is full of, but I guess it isn't integers... Have to admit I never use them, but can't remember why. Possibly because of limitations like this. I stick to Real arrays and EBCDIC ones.
You can almost certainly fix it by defining a new integer, j; inserting "j := t[i];" before your invocation of 'fun'; then invoking 'fun' with 'j' rather than t[i].
BTW you may want to make the array (and the 'for' loop) zero-relative. ALGOL is mostly zero-relative and I think it may save memory if you go with the flow.
Let me know if this helps....

Delphi Edit Text Integer: Minus Sign Error

Hi I am very beginner for Delphi.
But what confuses me is that I have Edit1.Text
and variable "i" which uses StrToInt(Edit1.Text);
Everything is Ok until I type minus sign
If I copy/paste minus with number (eg -2) it works
Can Anyone help me!
Regards, Umar
The StrToInt conversion function is unsafe to use when you're not 100% sure the input string can be converted to an integer value. And the edit box is such an unsafe case. Your conversion failed because you've entered as a first char the - sign that cannot be converted to integer. The same would happen to you also when you clear the edit box. To make this conversion safe, you can use the TryStrToInt function, which handles the conversion exceptions for you. You can use it this way:
procedure TForm1.Edit1Change(Sender: TObject);
var
I: Integer;
begin
// if this function call returns True, the conversion succeeded;
// when False, the input string couldn't be converted to integer
if TryStrToInt(Edit1.Text, I) then
begin
// the conversion succeeded, so you can work
// with the I variable here as you need
I := I + 1;
ShowMessage('Entered value incremented by 1 equals to: ' + IntToStr(I));
end;
end;
You get an error, obviously, because - is not an integer. You can use TryStrToInt instead.

Resources