Trouble tracing through pass-by-reference and pass-by-value-result - language-agnostic

I have the following program:
begin
integer i;
procedure pass(x, y);
integer x, y;
begin
x := x+1;
y := x+1;
x := y;
i := i+ 1
end
i := 1;
pass(i,i);
print i
end
I can work through the pass-by-value answer, but what would the pass-by-reference and pass-by-value-result traces look like?

Related

get the whole word string after finding the word in a text

i have a problem developing this function, i have this text..
Testing Function
ok
US.Cool
rwgehtrhjyw54 US_Cool
fhknehq is ryhetjuy6u24
gflekhtrhissfhejyw54i
my function :
function TForm5.FindWordInString(sWordToFind, sTheString : String): Integer;
var
i : Integer; x:String;
begin
Result := 0;
for i:= 1 to Length(sTheString) do
begin
x := Copy(sTheString,i,Length(sWordToFind));
if X = sWordToFind then
begin
if X.Length > sWordToFind.Length then
begin
Result := 100;
break;
end else
begin
Result := i;
break;
end;
end;
end;
end;
now, i want X to be US.Cool, but here its always = US, because i want to check the length of sWordToFind and X.
After clarification, this question is about getting length of a word searched by its starting substring within a string. For example when having string like this:
fhknehq is ryhetjuy6u24
When you execute a desired function for the above string with the following substrings, you should get results like:
hknehq → 0 → substring is not at the beginning of a word
fhknehq → 7 → length of the word because substring is at the beginning of a word
yhetjuy6u24 → 0 → substring is not at the beginning of a word
ryhetjuy6u24 → 12 → length of the word because substring is at the beginning of a word
If that is so, I would do this:
function GetFoundWordLength(const Text, Word: string): Integer;
const
Separators: TSysCharSet = [' '];
var
RetPos: PChar;
begin
Result := 0;
{ get the pointer to the char where the Word was found in Text }
RetPos := StrPos(PChar(Text), PChar(Word));
{ if the Word was found in Text, and it was at the beginning of Text, or the preceding
char is a defined word separator, we're at the beginning of the word; so let's count
this word's length by iterating chars till the end of Text or until we reach defined
separator }
if Assigned(RetPos) and ((RetPos = PChar(Text)) or CharInSet((RetPos - 1)^, Separators)) then
while not CharInSet(RetPos^, [#0] + Separators) do
begin
Inc(Result);
Inc(RetPos);
end;
end;
I spend a few times on your idea, so i wrote below codes, but it is not a good way for develop a Start With search. with some research you can find builtin functions, that provide better performance. you can try StrUtils.SearchBuf Function it will provide a full function string search.
anyway this code are working with SPACE separator, I hope it will be useful for you:
function TForm5.FindWordInString(sWordToFind, sTheString : String): Integer;
var
i : Integer; x:String;
flag : Boolean;
begin
Result := 0;
i := 1;
flag := False;
while True do
begin
if i > Length(sTheString) then Break;
if not flag then
x := Copy(sTheString,i,Length(sWordToFind))
else
begin
if sTheString[i] = ' ' then Break;
x := x + sTheString[i];
end;
if (X = sWordToFind) then
begin
flag := True;
if (X.Length >= sWordToFind.Length) and
(sTheString[i + Length(sWordToFind)] = ' ') then
break
else
i := i + Length(sWordToFind) -1;
end;
i := i + 1;
end;
Result := Length(x);
end;

GM Direction Component is Null with specifics coordinates

I'm working with gmlib in Delphi Seattle 10.
My client application sends the location(Latitude and Longitude) through an fireMonkey application to my database InterBase XE7.
My admin console consists in display a google map with markers that come from a query,for later calculate the distance between all markers in the map.
The procedure that creates markers is working perfectly and at the same time i'm filling the GMDirection component with the coordinates of markers. Here is the code of "CreatePoint" procedure:
amplitud := 1;
posicion := 0;
Distancia := 0;
markerGM.Tag := 1;
qryDatos.Close;
qryDatos.Open;
while not qryDatos.Eof do
begin
SetLength(marcadores,amplitud);
marcadores[posicion] := qryDatos.FieldByName('PLULOG').AsInteger;
Latitud := qryDatos.FieldByName('LATITUD').AsFloat;
Longitud := qryDatos.FieldByName('LONGITUD').AsFloat;
autorizado := qryDatos.FieldByName('AUTORIZADO').AsString;
with markerGM.Add(Latitud,Longitud) do
begin
if autorizado = 'T' then
begin
if markerGM.Tag = 1 then
begin
directionGM.DirectionsRequest.Origin.LatLng.Lat := Latitud;
directionGM.DirectionsRequest.Origin.LatLng.Lng := Longitud;
end
else if markerGM.Tag = 2 then
begin
directionGM.DirectionsRequest.Destination.LatLng.Lat := Latitud;
directionGM.DirectionsRequest.Destination.LatLng.Lng := Longitud;
directionGM2.DirectionsRequest.Origin.LatLng.Lat := Latitud;
directionGM2.DirectionsRequest.Origin.LatLng.Lng := Longitud;
Distancia := DistanceBetween(directionGM.DirectionsRequest.Origin.LatLng.Lat,directionGM.DirectionsRequest.Origin.LatLng.Lng,
directionGM.DirectionsRequest.Destination.LatLng.Lat,directionGM.DirectionsRequest.Destination.LatLng.Lng);
end
else if markerGM.Tag = 3 then
begin
directionGM2.DirectionsRequest.Destination.LatLng.Lat := Latitud;
directionGM2.DirectionsRequest.Destination.LatLng.Lng := Longitud;
directionGM3.DirectionsRequest.Origin.LatLng.Lat := Latitud;
directionGM3.DirectionsRequest.Origin.LatLng.Lng := Longitud;
Distancia := Distancia + DistanceBetween(directionGM2.DirectionsRequest.Origin.LatLng.Lat,directionGM2.DirectionsRequest.Origin.LatLng.Lng,
directionGM2.DirectionsRequest.Destination.LatLng.Lat,directionGM2.DirectionsRequest.Destination.LatLng.Lng);
end
else if markerGM.Tag = 4 then
begin
directionGM3.DirectionsRequest.Destination.LatLng.Lat := Latitud;
directionGM3.DirectionsRequest.Destination.LatLng.Lng := Longitud;
directionGM4.DirectionsRequest.Origin.LatLng.Lat := Latitud;
directionGM4.DirectionsRequest.Origin.LatLng.Lng := Longitud;
Distancia := Distancia + DistanceBetween(directionGM3.DirectionsRequest.Origin.LatLng.Lat,directionGM3.DirectionsRequest.Origin.LatLng.Lng,
directionGM3.DirectionsRequest.Destination.LatLng.Lat,directionGM3.DirectionsRequest.Destination.LatLng.Lng);
end;
MarkerType := mtColored;
ColoredMarker.Width := 48 + (Index * 20);
ColoredMarker.Height := 48;
markerGM.Tag := markerGM.Tag + 1;
end;
end;
mapGM.RequiredProp.Center.Lat := Latitud;
mapGM.RequiredProp.Center.Lng := Longitud;
mapGM.RequiredProp.Zoom := 13;
amplitud := amplitud + 1;
posicion := posicion + 1;
qryDatos.Next;
end;
mapGM.Active := True;
And here is the code of the procedure of "DistanceBetween" from Internet:
function TfrmLocationMain.DistanceBetween(const Lat1: Extended; const Lon1: Extended; const Lat2: Extended; const Lon2: Extended): Extended;
begin
Result := RadToDeg(ArcCos(Sin(DegToRad(Lat1)) * Sin(DegToRad(Lat2)) + Cos(DegToRad(Lat1)) * Cos(DegToRad(Lat2)) * Cos(DegToRad(Lon1 - Lon2)))) * 69.09;
end;
And finally. When the google map with the markers are created and the components are full of data. I'm execute all the GMDirection components to calculate the distance and displays in a EditText.
procedure TfrmLocationMain.btnRutaClick(Sender: TObject);
begin
directionGM.Execute;
directionGM2.Execute;
directionGM3.Execute;
directionGM4.Execute;
Distancia := (Distancia/0.62137);
edtDistancia.Text := FloatToStr(Distancia);
mapGM.RequiredProp.Zoom := 14;
end;
All this code is working with all registers in a test database. With coordinates from my country El Salvador. But when I implemented in a database from Guatemala. Some coordinates are causing that GMDirection component give me the following error:
Could not convert variant of type(Null) into type(OleStr)
This happens whit some coordinates from a Guatemala's database.
For example. If the Query gives me the following data:
14.513,-90.558
14.559,-90.545
14.572,-90.542
All the code works perfectly. But if the Query gives me the following data:
14.505,-90.568
14.667,-90.494
14.666,-90.494
Give me the error above.
I don't know what is the problem. And I don't understand why the code works with some registers and with others not.
If someone has a similar problem or idea of what may be failing.
I would greatly appreciate your help with this.
Regards.
I have found the problem. To solve it, open unit GMDirection, add Variants unit to the uses clause
implementation
uses
{$IFDEF DELPHIXE2}
System.SysUtils, System.DateUtils, Xml.XMLIntf, Xml.XMLDoc, System.Variants,
{$ELSE}
SysUtils, DateUtils, XMLIntf, XMLDoc, Variants,
{$ENDIF}
Lang, GMFunctions;
Search line (3575 aprox)
if SameText(Node.NodeName, LBL_D_SUMMARY) then Result.FSumary := Node.NodeValue;
and replace by
if SameText(Node.NodeName, LBL_D_SUMMARY) and (Node.NodeValue <> null) then Result.FSumary := Node.NodeValue;
Recompile the components
That's all

Call by result Example

Is there any proper example for explaining call-by-result ? (not pseudocode)
I have learned that ALGOL 68, Ada could use this way,
but I cannot find any clear example of Call-by-Result.
I just made by myself.
pseudocode
begin
integer n;
procedure p(k: integer);
begin
n := n+1;
k := k+4;
print(n);
end;
n := 0;
p(n);
print(n);
end;
Implement using Ada Language
call.adb
with Gnat.Io; use Gnat.Io;
procedure call is
x : Integer;
Procedure NonSense (A: in out integer) is
begin
x := x + 1;
A := A + 4;
Put(x);
end NonSense;
begin
x := 0;
NonSense (x);
Put(" ");
Put(x);
New_Line;
end call;
Since Ada uses call-by-result way, result should be 1 4. (It could be checked by entering this code into online-Ada-compiler "http://www.tutorialspoint.com/compile_ada_online.php")
And, other result applied different passing parameter types should be...
call by value: 1 1
call by reference: 5 5
(compare > call by value-result: 1 4)

Writing a program to calculate Happy Numbers in Pascal. Stuck with an infinite loop

I'm writing a procedure to do the calculating. The program asks the user for any number between 1 and 9999 and then calculates whether or not that number is a happy number.
program EindEvaluatieProceduresFuncties2;
uses wincrt, math;
var lucky: boolean;
num: longint;
i, j: integer;
arr: array [1..4] of integer;
sum: integer;
procedure HappyNumber;
begin
repeat
begin
repeat
begin
i:=i+1;
//writeln('i = ',i);
arr[i]:=num mod 10;
//writeln( 'a[i] = ', arr[i] );
num:=num div 10;
//writeln ( 'n = ', num );
end;
until num=0;
//writeln('Digits are : ');
//for j:=i downto 1 do
//writeln('a[j] = ', arr[j],' ', j);
//writeln('Calculating Happy Number');
for j := i downto 1 do
sum := sum + (Sqr(arr[j]));
for j := i downto 1 do
writeln('sum = ',sum);
num := sum;
end;
until sum < 10 ;
end;
begin
lucky := false;
writeln('Please give a positive number below 10000.');
readln(num);
while ( num < 1 ) or ( num > 9999 ) do
begin
writeln('Number must be positive and less than 10000. Try again.');
readln(num);
end;
HappyNumber;
if (lucky = True) then
begin
writeln(num, ' is a happy number.');
end
else
begin
writeln(num, ' is not a happy number.');
end;
writeln('');
writeln('Press < ENTER > to end the program.');
readln;
end.
Within the procedure I have the command i := 0; as seen below:
procedure HappyNumber;
begin
repeat
begin
repeat
begin
i:=0;
i:=i+1;
This is where the problem occurs. If I do this it becomes an infinite loop, however if I place the command outside of the repeat loop then i does not reset to 0 at the beginning of every iteration of the loop, which I need it to.
I should point out that much of the code is there at the moment simply to let me see what is happening and wont be a part of the final code. Wherever I have inserted "//" are those lines.
I am aware that there is perhaps a better way I could be doing this whole program. If anyone has any suggestions for how I can make it easier, I'd also appreciate that very much.
Thank you.
Never heard of happy / unhappy numbers and found it quite interesting to solve this task :-)
There is still a lot to optimize but I think you can use it for studying.
program EindEvaluatieProceduresFuncties2;
uses SysUtils, crt ;
var input: string;
number: integer;
code: integer;
function HapyNumber(num: integer):boolean;
var
erg: integer;
digit: integer;
begin
Result := true;
erg := 0;
if num = 4 then Result := false;
if num = 4 then exit;
if num = 1 then exit;
if num = 0 then exit;
// serialize the number into digits and calculate the next number
while num > 0 do begin
digit := num mod 10;
num := num div 10;
erg := erg + digit * digit;
write(IntToStr(digit) + ' ');
end;
write(IntToStr(num) + ' ');
writeln('=' + IntToStr(erg));
Result := HapyNumber(erg);
end;
begin
repeat
writeln('Please give a positive number below 10000.' + sLineBreak + 'Number must be positive and less than 10000.' + sLineBreak + 'Type x for exit!');
readln(input);
if lowerCase(input) = 'x' then exit;
val(input, number, code);
if code <> 0 then begin
ClrScr;
writeln('Invalid number "' + input + '" !');
end
else if (number > 0) and (number <= 9999) then begin
ClrScr;
writeln('Cheking ' + IntToStr(number) + '..');
if HapyNumber(number) then writeln(number, ' is a happy number.')
else writeln(number, ' is not a happy number.');
writeln('Press enter to continue');
readln;
ClrScr;
end;
until lowerCase(input) = 'x';
end.
The important codepart is
while num > 0 do begin
digit := num mod 10;
num := num div 10;
erg := erg + digit * digit;
write(IntToStr(digit) + ' '); // just output the tmp result
end;
It serialize a number into digits (1973 will be 3 7 9 1)
I used recursion just for fun and it is not really necessary :-)

Understanding call by value-result and call by reference differnce

So I have this piece of Pascal code:
program P;
var a: array [1..2] of Integer;
var i :Integer;
var k :Integer;
procedure update(x,y,z: Integer);
begin
x := x+1;
y := x*2;
x := y;
k := x;
end
begin
a[1] := 5; a[2] := 10;
k := 3;
for i:=1 to 2 do
begin
update(a[i],a[2],k);
print(a);
print(k)
end
end.
(assume that 'print' prints elements of array separated by spaces, and then prints a new line and also for an integer it just prints it)
And i'm trying to understand how different the output would be if the function call was by value-result or by reference.
obviously, if it was just by-value, it's easy to tell that the procedure wouldn't make any difference to the actual parameter, i.e the output (in by value) should be: 5 10 3 5 10 3.
I think that if it was be value-result it would have been, at least the first iteration: 12 12 12.
at the case of by reference I got confused.
What would it be?
You haven't declared any variable parameters. The variable K will be changed, but that doesn't count in this context and is generally considered bad practice.
PROGRAM ParamTest;
VAR
A, B : Integer;
PROCEDURE TestProc(X : Integer; VAR Y : Integer; CONST Z : Integer);
BEGIN
X := X + Z;
Y := Y + Z;
END;
BEGIN
A := 10;
B := 10;
TestProc(A, B, 5);
WriteLn(A, ' ', B);
END.
X : Call by value
Y : Call by reference
Z : Call by constant
The output of this program should be 10 15.
With declaring Zas constant parameter you promise to the compiler that you don't change that value. The following procedure variant should give an error while compiling.
PROCEDURE TestProc(X : Integer; VAR Y : Integer; CONST Z : Integer);
BEGIN
X := X + Z;
Y := Y + Z;
Z := Z + 1;
END;