So I just worked on a generic program for school which uses the sort algorithms. The teacher always loves putting everything into different units so I decided to create an "output" procedure which gives an output of the sorted array.
unit selectionsort;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, typen, ausgabe;
procedure SSort (FeldS: t_Feld);
implementation
procedure SSort (FeldS: t_Feld);
var h,j,min,hilf: integer;
begin
for h:= 1 to c-1 do
begin
## all the sorting stuff
end;
**ausgabe(FeldS);**
end;
end.
(ausgabe is german for output)
unit ausgabe;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, typen;
procedure ausgabe(FeldA: t_feld);
implementation
procedure ausgabe(FeldA: t_feld);
begin
for i:= 1 to c do
begin
write(FeldA[i], ' ');
end;
readln();
end;
end.
The bold part (when calling the procedure ausgabe) is where I get the error: fatal: Syntax error, "." expected but "(" found. I know I could just delete the procedure "Ausgabe" and do the output in the sort procedures but I would like to do it this way.
As the procedure ausgabe and the unit have the same name (this is possible as they are in different scopes), the compiler assume a so-called "qualified identifier": unitname.procedurename. This is needed if multiple units have identifiers with the same name. To overcome the error: Either you rename the unit or the procedure or you call the procedure using its qualified name (the first ausgabe is the name of the unit where the compiler should search for the symbol, the second ausgabe is the actual procedure name):
ausgabe.ausgabe(FeldS);
Related
It has been around 20 years since I last had to write in Pascal. I can't seem to use the structure elements of the language correctly where I am nesting if then blocks using begin and end. For example this gets me an Compiler Error "Identifier Expected".
procedure InitializeWizard;
begin
Log('Initialize Wizard');
if IsAdminLoggedOn then begin
SetupUserGroup();
SomeOtherProcedure();
else begin (*Identifier Expected*)
Log('User is not an administrator.');
msgbox('The current user is not administrator.', mbInformation, MB_OK);
end
end;
end;
Of course if I remove the if then block and the begin end blocks associated with them then everything is OK.
Sometimes I get it this kind of syntax right and it works out OK, but the problems become exasperated when nesting the if then else blocks.
Solving the problem is not enough here. I want to have a better understanding how to use these blocks. I am clearly missing a concept. Something from C++ or C# is probably creeping in from another part of my mind and messing up my understanding. I have read a few articles about it, and well I think I understand it and then I don't.
You have to match every begin with an end at the same level, like
if Condition then
begin
DoSomething;
end
else
begin
DoADifferentThing;
end;
You can shorten the number of lines used without affecting the placement, if you prefer. (The above might be easier when you're first getting used to the syntax, though.)
if Condition then begin
DoSomething
end else begin
DoADifferentThing;
end;
If you're executing a single statement, the begin..end are optional. Note that the first condition does not contain a terminating ;, as you're not yet ending the statement:
if Condition then
DoSomething
else
DoADifferentThing;
The semicolon is optional at the last statement in a block (although I typically include it even when it's optional, to avoid future issues when you add a line and forget to update the preceding line at the same time).
if Condition then
begin
DoSomething; // Semicolon required here
DoSomethingElse; // Semicolon optional here
end; // Semicolon required here unless the
// next line is another 'end'.
You can combine single and multiple statement blocks as well:
if Condition then
begin
DoSomething;
DoSomethingElse;
end
else
DoADifferentThing;
if Condition then
DoSomething
else
begin
DoADifferentThing;
DoAnotherDifferentThing;
end;
The correct use for your code would be:
procedure InitializeWizard;
begin
Log('Initialize Wizard');
if IsAdminLoggedOn then
begin
SetupUserGroup();
SomeOtherProcedure();
end
else
begin
Log('User is not an administrator.');
msgbox('The current user is not administrator.', mbInformation, MB_OK);
end;
end;
I am mainly interested in stable sorting large arrays of strings. With real-world data I succeed in beating Tarray.sort by a factor 10-100 (even though the latter is not stable). As an exercise I tried to repeat this for simple types. Works fine. And then to bundle it into a generic class as in Tarray. Consider my starting point:
procedure sortArray(var values : array of byte); overload;
var temp : array of byte;
function getSequence(from: integer) : integer;
procedure doThis(...);
procedure doThat(...);
begin
setLength(temp,high(values)+1);
// actual code calling one of the procedures
end;
procedure sortArray(var values : array of double); overload;
var temp : array of double;
... etc ...
All the local subroutines have access to values and temp.
It seemed to me like an ideal situation to try out how generics work. In a generic class you can't have local subroutines, so these are all changed into methods. I then have:
type
TsimpleArray<T> = class
private
class function getSequence(var values,temp : array of T; from: integer) : integer;
class procedure doThis(var values,temp : array of T; ...);
...
public
class procedure sort(var values : array of T);
end;
Class functions can not have access to global temp storage, so that has to be passed as a parameter to all these methods, as well as the source array. All comaprisons if v>values[k] and the like to be changed into if Tcomparer<T>.default.compare(v,values[k])>0.
Well, it works. But it is now around 10 times slower then my simple procedure approach. (Still a lot faster than Tarray.sort.) I guess this is the prize we pay for better maintainable generic code. Or are there things I could do better?
I am making simple encrypt/decrypt program in Lazarus with 2 buttons, one for encrypt and one for decrypt. I also have two memo boxes (or just two memos ).
I tested my algorithm and it works but when i tried implementing it in user friendly app i got this problem.
I have this function:
function enc(x:string):string;
var
y:string;
p,q:integer;
m:char;
begin
y:=x[1];
for p:=2 to Length(x)do
begin
q:=p-1;
if chr(ord(x[p]))=' ' then
m:='!'
else if ord(x[p])>ord(x[q]) then
m:=Succ(chr(ord(x[p])))
else
m:=Pred(chr(ord(x[p])));
Y:=y+m ;
end;
enc:=y;
end;
and one procedure to call this function
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Text:=enc(Memo2.Text);
end;
I compiled program and it worked but when i tried to enter some text and encrypt that text i got this error
exception class 'External: SIGSEGV'
In file 'unit1.pas' at line 46: y:=x[1];
I recently started to learn pascal and to use lazarus soo sry if this Q is stupid but i really want to know what I'm doing wrong.
That error, for that code, implies that x is an empty string. If the first character is not valid, then what else could x be, other than empty?
Guys I am trying to overload a function within a package in Oracle 11gR2.
Functions go like this.
Function is_h2h(p_param in number) return boolean
is
begin
--some code here
return true;
end;
Function is_h2h(p_param in number) return number
is
begin
--some code here
return 1;
end;
So the problem is when I write an if statement within another procedure for example
if is_h2h(some_param) then --code goes
end if;
the compiler returns PLS-00307: Too many declarations of 'IS_H2H' match this call.
So how can I implement this kind of overloading?
You need to make the signatures different (ignoring the return type) otherwise the compiler won't choose for you.
My first preference would be to give the functions different names, e.g.:
function is_h2h_b(p_param in number) return boolean...
function is_h2h_n(p_param in number) return number...
If you really really really want to use the same name, you can use a different parameter name - but then you're limited to only using named parameters (which, mind you, is good practice anyway):
function is_h2h(p_param_b in number) return boolean...
function is_h2h(p_param_n in number) return number...
if is_h2h(p_param_b => some_param) then...
This snippet not only causes a runtime error, it makes FPC close if I run it using the debugger.
procedure sortplayersbyscore(var vAux:tplayers);
procedure swap(var a:trplayers;var b:trplayers);
var
rAux:trplayers;
begin
rAux:=a;
a:=b;
b:=rAux;
end;
var
i,j:integer;
sorted:boolean;
begin
vAux:=playersarray;
i:=1;
sorted:=false;
while (i <= MAXPLAYERS -1) and not sorted do
begin
j:=1;
sorted:=true;
while (j <= MAXPLAYERS -i) do
begin
if (vAux[j].score < vAux[j+1].score) then
begin
swap(vAux[j],vAux[j+1]);
sorted:=false;
end;
inc(j);
end;
inc(i);
end;
end;
The code itself is part of a really big source file, I can post the whole thing but the responsible for the error is just that bunch of lines. The debugger terminates at line:
swap(vAux[j],vAux[j+1]);
tplayers is just a type defined as an array of records that contain score (an integer) among a bunch of other variables. trplayers is the type of the aforementioned records. I'm at a total loss; FPC (while not under debugging mode) spits an out-of-range error but under my watches I see that the variables I'm trying to read exist. Any help is really appreciated!
rAux:trplayers; have you typed a wrong symbol or the type here really contains "r" in its name?
It looks valid (other than typos) ... so let's try something simple.
What's the value of "j" when you abort?
If the debugger won't tell you, try adding:
writeln ('j = ', j);
just before the "swap" call.
As Yochai's question implied, your array needs to be dimensioned at least from
1 (or lower) to MAXPLAYERS (or larger). (I.e.: 0..MAXPLAYERS-1 would not work,
but 1..MAXPLAYERS should.)