Eiffel - How do I make my classes readable? - linked-list

I'm new to Eiffel and I'm trying to use the LINKED_LIST class for organizing instances of other class "MONOMIO" I've made. I added a function for ordering this elements and I use the remove and the cursor movement features and when I try to execute the code it raises an exception saying that the objects contained should be readable and writable. I would like to know how to do it, this is my class:
class
MONOMIO
feature --Initialization
make (coef:INTEGER; expX:INTEGER; expY:INTEGER)
do
coeficiente := coef
exponenteX := expX
exponenteY := expY
end
feature
evaluar(valX: INTEGER; valY: INTEGER): REAL_64
do
Result := coeficiente*(valX^exponenteX)*(valY^exponenteY)
end;
coeficiente: INTEGER;
exponenteX: INTEGER;
exponenteY: INTEGER;
feature --setter
set_coeficiente(val: INTEGER)
do
coeficiente := val
end;
end
I think the exception raises because of this feature I've made for a class that has as a feature the LINKED_LIST[MONOMIO] and it's called "contenido":
simplificar
local
tamanio_polinomio: INTEGER -- NĂºmero de monomios que tiene el polinomio
contador: INTEGER
monomio_a_comparar: MONOMIO -- Auxiliar
coeficiente_total:INTEGER -- Auxiliar
indice_monomio_en_revision:INTEGER
do
from
contenido.start
indice_monomio_en_revision := 0
tamanio_polinomio := contenido.count
until
indice_monomio_en_revision = tamanio_polinomio
loop
contenido.start
contenido.move (indice_monomio_en_revision)
monomio_a_comparar := contenido.item
from
contador := indice_monomio_en_revision
coeficiente_total := monomio_a_comparar.coeficiente
contenido.forth
until
contador = tamanio_polinomio
loop
if
(monomio_a_comparar.exponentex = contenido.item.exponentex) and
(monomio_a_comparar.exponentey = contenido.item.exponentey)
then
coeficiente_total := coeficiente_total + contenido.item.coeficiente
contenido.remove -- Mueve el cursor a la derecha
tamanio_polinomio := tamanio_polinomio - 1
contador := contador - 1
else
if
not contenido.islast
then
contenido.forth
end
end
contador := contador + 1
end
contenido.start
contenido.move (indice_monomio_en_revision)
contenido.item.set_coeficiente (coeficiente_total)
indice_monomio_en_revision := indice_monomio_en_revision + 1
end
end;
I hope anyone can help me with this problem. Thanks.

Suppose you have a list with 1 element. Then we enter the outer loop and move to the first element. Then we execute contador := indice_monomio_en_revision that is still 0 at this point and do contenido.forth. Now we are beyond the list because there is only one element. However contador = tamanio_polinomio is false (0 = 1), so we enter the inner loop and try to retrieve the second (non-existing) item. BOOM!
Other issues include:
There are multiple calls like contenido.start followed by contenido.move. You could use a single call to go_i_th instead.
Instead of counting number of items in the list I would look at the feature after. It tells when you reach an end of the list. It would simplify the logic of your loop (e.g. the call to islast would be removed) and let you to remove some local variables.
Taking the last point into account I would write the inner loop condition as
contenido.after
At least this would avoid the crash you experience. As to the logic, you may need to check features start, after, forth and remove to see what effect they have. The usual way to write loops in such cases is like
from
l.start
until
l.after
loop
... -- Use l.item
l.forth
end
In case of remove probably you do not need to call forth.

Related

how to extract data from a database using the primary key

I am trying to extract the Name of a person out of my database, containing two tables, with only having the ID (primary key).
I am struggling to come up with a solution, although I do have notes that I've written and the logic seems to check out (to me at least).
if P1Score > P2Score
then winner := P1ID
else winner := P2ID
winner in tblGames = the ID of winner in tblPlayers
WinnerName := first name of Winner + surname of Winner in tblPlayers
So this is my logic, obviously it's missing a lot, but I can't seem to expand on it much more
I have the ID of the person from tblGames, but now I'm struggling to understand how to use that ID to extract the Name and Surname from my tblPlayers and assign it to a variable, so I can put it into the Winner Column of tblGames.
I have tried a few things using my own thought process, but I do not know enough about Delphi and databases to actually implement it correctly.
BEGIN
if (StrToInt(P1_score) - StrToInt(P2_score) = 0) then
Draw := True
else
Draw:= False;
if StrtoInt(P1_Score) > StrToInt(P2_Score) then
winnerID := P1_ID
else
winnerID := P2_ID;
with dmTournament do
begin
tblGames.Insert;
tblGames['Player1_Id'] := StrToInt(P1_ID);
tblGames['Player2_ID'] := StrToInt(P2_ID);
tblGames['Player1_score'] := StrToInt(P1_Score);
tblGames['Player2_Score'] := StrToInt(P2_Score);
tblGames['Draw'] := Draw;
tblGames['Winner'] := WinnerName; //How do I get WinnerName(?)
tblGames.Post;
end;
END;
You don't need to do a lot of code. You can let MySQL engine do job for you. Execute the following quires in same order they appeared. This will update the table data as you want.
/* 1: Set all games to draw */
UPDATE Games SET draw = true;
/* 2: Update when Player1 is winner :*/
UPDATE Games, Players SET
Games.draw = false,
Games.winner = CONCAT(Players.first_name, ' ', Players.last_name)
WHERE
(Games.player1_score > Games.player2_score) AND (Games.player1_id=Players.ID);
/* 3: Update when Player2 is winner */
UPDATE Games, Players SET
Games.draw = false,
Games.winner = CONCAT(Players.first_name, ' ', Players.last_name)
WHERE
(Games.player2_score > Games.player1_score) AND (Games.player2_id=Players.ID);

Out parameter undefined

I'm currently stuck in creating two tasks inside of a procedure adding numbers of an array passed to the respective procedure.
My generic package looks like this:
generic
type Item_Type is private;
with function "+"(Left: Item_Type; Right: Item_Type) return Item_Type;
package Parallel_Algorithms is
type Array_Type is array(Natural range <>) of Item_Type;
type Array_Access_Type is access all Array_Type;
procedure Parallel_Sum(Input: Array_Access_Type; Result: out Item_Type);
end Parallel_Algorithms;
I implemented the Parallel_Sum Method the following way, being aware that the implementation is not perfect, nor thread safe.
procedure Parallel_Sum(Input: Array_Access_Type; Result: out Item_Type) is
Loop_Var: Integer:= 0;
task type T;
Task1, Task2 : T;
task body T is
begin
while Loop_Var < Input'Length loop
Result := Result + Input(Loop_Var);
Loop_Var := Loop_Var + 1;
end loop;
end T;
begin
-- Result := Temp;
end Parallel_Sum;
If I now run my main program the output of Result always ends up being something like 1918988326. Considering the elements inside of my array (1,2,3,4) that result is obviously wrong.
I read in another post that non altering an out type may result in undefined behaviour of the respective variable.
What would be the proper way to get the 'real' Result?
Upon looking at the problem more closely I see there are several issues to overcome. The tasks must accumulate their own totals, then those totals must be combined. Adding totals to an unprotected Result variable will produce a race condition which will result in undefined results.
Following is my approach to the problem.
------------------------------------------------------------------
-- Parallel Addition of Array Elements --
------------------------------------------------------------------
generic
type Element_Type is range <>;
package Parallel_Addition is
type Array_Type is array(Natural range <>) of Element_Type;
type Array_Access is access all Array_Type;
task type Adder is
Entry Set_Slice(Low, High : in Natural;
Item : in not null Array_Access);
end Adder;
protected Result is
procedure Accumulate(Item : in Element_Type);
function Report return Element_Type;
private
Sum : Integer := 0;
end Result;
end Parallel_Addition;
package body Parallel_Addition is
-----------
-- Adder --
-----------
task body Adder is
My_Array : Array_Access;
Id_Low, Id_High : Natural;
Sum : Integer := 0;
begin
accept Set_Slice(Low, High : in Natural;
Item : in not null Array_Access) do
Id_Low := Low;
Id_High := High;
My_Array := Item;
end Set_Slice;
for I in Id_Low..Id_High loop
Sum := Sum + Integer(My_Array(I));
end loop;
Result.Accumulate(Element_Type(Sum));
end Adder;
------------
-- Result --
------------
protected body Result is
----------------
-- Accumulate --
----------------
procedure Accumulate (Item : in Element_Type) is
begin
Sum := Sum + Integer(Item);
end Accumulate;
------------
-- Report --
------------
function Report return Element_Type is
begin
return Element_Type(Sum);
end Report;
end Result;
end Parallel_Addition;
------------------------------------------------------------------
-- Parallel_Addition Test --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Parallel_Addition;
procedure PA_Test is
package adders is new Parallel_Addition(Natural);
use adders;
Data : aliased Array_Type := (1,2,3,4,5,6,7,8,9,10);
T1, T2 : Adder;
begin
T1.Set_Slice(Low => 0, High => 4, Item => Data'Access);
T2.Set_Slice(Low => 5, High => 9, Item => Data'Access);
loop
if T1'Terminated and then T2'Terminated then
exit;
end if;
end loop;
put_Line("The sum is " & Integer'Image(Result.Report));
end PA_Test;

Scan entire process memory with ReadProcessMemory

I'm tryin to scan an entire process memory but no success... What I'm doing is: for tests I'm using notepad, so I write there %B and this values in HEX are: 25(%) and 42(B). So the code is:
while (VirtualQueryEx(PIDHandle, Pointer(MemStart), MemInfo, SizeOf(MemInfo)) <> 0) do
begin
if ((MemInfo.State = MEM_COMMIT) and (not (MemInfo.Protect = PAGE_GUARD)
or (MemInfo.Protect = PAGE_NOACCESS)) and (MemInfo.Protect = PAGE_READWRITE)) then
begin
SetLength(Buff, MemInfo.RegionSize);
if (ReadProcessMemory(PIDHandle, MemInfo.BaseAddress, Buff,
MemInfo.RegionSize, ReceivedBytes)) then
begin
for I := 0 to SizeOf(Buff) do
begin
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Form1.Memo1.Lines.Append(IntToHex(Buff[i], 1));
end;
end;
end;
MemStart:= MemStart + MemInfo.RegionSize;
end;
CloseHandle(PIDHandle);
end;
The var 'Buff' is TBytes (I read about TBytes and think it's same as array of byte). So I'm converting the bytes to Hex, and searching for values: 25 and 42 respectively. The code is like:
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Because have 00 between the hex values. So I need to add '+2'. How can I scan the entire memory for this values??
Notepad uses Unicode so you'll need to look for UTF-16 encoded data, $0025 and $0042.
I don't understand why you feel the need to convert into hex strings before comparing. There's nothing special about hex that requires the use of strings. Hexadecimal is just a number system with base-16. So, decimal 32 is the same as hexadecimal 20, i.e. 32=$20. Do your comparison directly with integral values:
if (Buff[i]=$25) and (Buff[i+2]=$42) then
That said, taking into account the $00 bytes your test should really be something like this:
var
Target: string;
....
Target := '%B';
if CompareMem(#Buff[i], #Target[1], Length(Target)*SizeOf(Char)) then
....
I don't want to get too deep into the rest of your code, but this line
for I := 0 to SizeOf(Buff) do
is wrong on many different levels.
SizeOf(Buff) returns the size of a pointer since a dynamic array variable is essentially just a pointer. A useful thing to remember is that SizeOf is evaluated at compile time.
If you used Length instead of SizeOf then you would be iterating over the end of the list. To loop over a dynamic array, loop from 0 to Length(...)-1.
But in this case you are accessing index i+2 inside the loop, so you should loop from 0 to Length(...)-3.
But in fact you need to compare against 4 consecutive bytes to find a match. Perhaps like this:
TargetByteLength = Length(Target)*SizeOf(Char);
for i := 0 to Length(Buff)-TargetByteLength do
if CompareMem(#Buff[i], #Target[1], TargetByteLength) then
....

Cant find simple error in Delphi Insertion Sort algorithm

I am using insertion sort to sort a stringlist (EmailingListArray below).
EmailingListArray[1] is an array that contains names.
EmailingListArray[2] contains corresponding emails.
I am sorting EmailingListArray[1] and when something changes within it, it also changes the second array, so they are sorted together.
An awkward way of doing things, I know, but it's for coursework and I wanted to put an insertion sort in somewhere to try get an extra mark :L
Here's my code
//quick check to make sure array contains correct values
for first := 0 to EmailingListArray[1].Count do
ShowMessage(EmailingListArray[1][first]);
//then sort
First := 0;
Last := EmailingListArray[1].Count;
for CurrentPointer := First +1 to Last-1 do
begin
CurrentValue := EmailingListArray[1][CurrentPointer];
CurrentValue2 := EmailingListArray[2][CurrentPointer];
Pointer := CurrentPointer + 1;
while ((EmailingListArray[1][Pointer] > CurrentValue) AND (Pointer > 0)) do
begin
EmailingListArray[1][Pointer+1] := EmailingListArray[1][Pointer];
EmailingListArray[2][Pointer+1] := EmailingListArray[2][Pointer];
pointer := Pointer -1;
end;
EmailingListArray[1][Pointer + 1] := CurrentValue;
EmailingListArray[2][Pointer + 1] := CurrentValue;
end;
//show message at the end for a check
ShowMessage('hello?');
The message "hello?" isn't being displayed for some reason :S.
The program isn't crashing or anything so it really should atleast display "hello?" at the end.
It isn't sorting my arrays either.
Neither am I sure if the algorithm is written correctly, I got it out of our textbook.
Any help would be much appreciated!
If you want to get a good mark:
Avoid giving misleading names for your variables:
CurrentPointer should be called CurrentIndex or CurrentPosition as it is an index and not a Pointer
Pointer is to be avoided (reserved for Pointer type) and more so because it is not a Pointer; should be WorkIndex or WorkPosition
Read the Insertion sort algorithm (wikipedia has a simple pseudocode for array indexed from 0) and implement it properly:
WorkIndex := CurrentIndex - 1; // - not + in your "Pointer := CurrentPointer + 1;"
Get your Index range from 0 to Count-1 for a TStrings.
Don't mix up the 2 arrays:
EmailingListArray[2][WorkIndex + 1] := CurrentValue2; // not CurrentValue
Update: Missed the bad while condition for zero based array.
2bis. While condition should be with >=0, not >0
while ((EmailingListArray[1][WorkIndex] > CurrentValue) AND (WorkIndex >= 0)) do

An array of pointers that point to the same array

I've read a piece of Delphi code like this :
sample1 = ARRAY[1..80] OF INTEGER;
psample =^sample1;
VAR
function :ARRAY[1..70] OF psample;
From my understanding, the programmer is trying to declare an array that contains 70 pointers and each pointer points to a sample1 array.
So when I write :
function[1]^[1] := 5;
function[1]^[2] := 10;
then :
function[n]^[1] := 5
function[n]^[2] := 10; ( n = 2 to 70)
Is that correct ?
Your code sample is lacking some information since you do not say how function is defined. This means that you cannot draw the conclusions that you attempt to draw.
Of course, since function is a reserved word in Pascal, that code could never even compile. I will assume now that the variable is called f.
Consider the following definitions:
type
sample1 = array [1..80] of integer;
psample = ^sample1;
var
f : array [1..70] of psample;
Here, sample1 and psample are types. sample1 is type describing an array of 80 integers. psample is a pointer to a sample1.
Next a variable named f is defined. It is an array of 70 psamples.
Now, before you can even consider what happens when you write f[1]^[1], we need to assign some values to the elements of f.
Suppose we did it like this:
var
sample: sample1;
...
for i := 1 to 70 do
f[i] := #sample;
Now it would be true that f[i]^[k] refers to the same integer as f[j]^[k] for all valid i and j. So when you write f[1]^[1] := 42 you are also assigning that value to f[2]^[1], f[3]^[1] and so on.
On the other hand you could do it like this:
var
samples: array [1..70] of sample1;
...
for i := 1 to 70 do
f[i] := #samples[i];
Now each f[i] pointer points to a distinct array in memory. In this case assigning f[1]^[1] := 42 does not modify the value of f[2]^[1] or any of the other values.
That is correct. You have 70 pointers, each pointing to an array of 80 integers.

Resources