display all variables for a specific type - pascal

I want to create a menu in WriteFoodMenu that lets the user display all available options (which is currently what the WriteLn does in WriteFoodMenu or only display the options in which the selected venue is located.
So for example if the user selects 'Bakery',
WriteLn(mfood.foodtype, ' - ', mfood.chef, ' - ', mfood.venue);
will only display options in which the venue is a bakery.
Edit: let me know if i need to include anything else
type
Venues =(cafe, resteraunt, bakery, milkbar, fastfood);
Mfood = record
foodtype, chef: string
venue: Venues;
end;
function FoodType(prompt: String): Venues;
var
selection: Integer;
begin
WriteLn('Venues:');
WriteLn(' 1. Cafe');
WriteLn(' 2. Restaurant');
WriteLn(' 3. Bakery');
WriteLn(' 4. Milkbar');
WriteLn(' 5. FastFood');
selection := ReadIntegerRange('Select a venue (1 - 5): ', 1, 5);
result := Venues(selection - 1);
end;
procedure WriteFoodMenu(MFood: MFood);
begin
WriteLn(mfood.foodtype, ' - ', mfood.chef, ' - ', mfood.venue);
end;

You will have to select on Venues:
procedure WriteFoodMenu(Venue: Venues; MFood: MFood);
begin
if MFood.venue = Venue then
WriteLn(mfood.foodtype, ' - ', mfood.chef, ' - ', mfood.venue);
end;
That only works if you pass the desired venue to the procedure. Now you can have a list of MFoods:
const
Foods: array[0..numOfFoods - 1] of MFood =
(
(FoodType: 'Spaghetti'; Chef: 'Luigi'; Venue: resteraunt),
( etc...),
// etc...
( etc...)
);
...
Venue := FoodType('Select a venue');
for I := Low(Foods) to High(Foods) do
WriteFoodMenu(Venue, Foods[I]);
Note that it would make sense to display the prompt you pass to FoodType before you present the menu. You are currently not using the prompt at all.

Related

Item Query From Table and Send It To Procedure

Note
I want to query page item name and send the corresponding items value into a procedure. I can get the item name but couldn't get the value of it. At first I use the following code:
begin
for j in (select item_name from UTLITMINF where service_id ='abc' ) loop
val := val || ':' || j.item_name; --items name
END LOOP;
/* exe := ' begin
dynamic_api_call(p_service => :ser,
p_par => :v_val, --items value to need to send
o_result_json => :v_l_response_text);
end; ';
execute immediate exe
using IN ser,
in val,
out l_response_text;*/
begin
dynamic_api_call(p_service => 'abc',
p_par => val, --items name from page queried from table and send its value to procedure
o_result_json => l_response_text);
end;
raise_application_error(-20001,l_response_text);
end;
In val parameter it contains P11_CUSTOMER. But the value of it did not pass through the procedure. How can I get the value of it? Suggest me if i need to improve my code.
You can use the V (short for value) and NV (short for numeric value) function for dynamic item names. Try something like this (you'll need to adjust on your end).
declare
l_response_text varchar2(255);
l_ser varchar2(255) := 'abc';
l_item_name varchar2(255);
begin
select item_name
into l_item_name
from UTLITMINF
where service_id = l_ser;
dynamic_api_call(
p_service => l_ser,
p_par => v(l_item_name),
o_result_json => l_response_text
);
end;
Try the dynamic sql like the below
begin
for j in (select item_name from UTLITMINF where service_id ='abc' ) loop
val := val || ':' || j.item_name; --items name
END LOOP;
exe := ' begin
dynamic_api_call(p_service => :ser,
p_par => :v_val, --items value to need to send
o_result_json => :v_l_response_text);
end ;';
execute immediate exe
using ser,
val,
OUT l_response_text;
raise_application_error(-20001,l_response_text);

call a procedure with table as IN parameters

I have the following code which works very nice:
declare
v_order_id oe.orders.order_id%type := 1;
v_order_item pkg_order_management.to_order_list := pkg_order_management.to_order_list();
begin
v_order_item.extend(2);
v_order_item(1).product_id := 2289;
v_order_item(1).quantity := 2;
v_order_item(2).product_id := 2058;
v_order_item(2).quantity := 5;
pkg_order_management.prc_create_order(240, v_order_item, v_order_id);
dbms_output.put_line('it was created the order: ' || v_order_id);
end;
but I want to call the pkg_order_management.prc_create_order procedure like
declare
v_order_id oe.orders.order_id%type := 1;
begin
pkg_order_management.prc_create_order(240, ((2289, 2),(2058, 5)), v_order_id);
dbms_output.put_line('it was created the order: ' || v_order_id);
end;
Here is the types definition from the package:
type t_order_item is record
( product_id oe.order_items.product_id%type
, quantity oe.order_items.quantity%type);
type to_order_list is table of t_order_item;
When I call the procedure as in 2nd case, I receive the following error:
PLS-00306: wrong number or types of arguments in call to
'PRC_CREATE_ORDER'
Surely, my call type is wrong but I have no idea how to solve this.
Can you give me a hint, please?
PL/SQL record types are not object-oriented constructs. So we can't use them as flexibly as we can actually Objects.
If you want to pass an inline array you need to define your types using SQL:
create or replace type t_order_item is object
( product_id number
, quantity number);
/
create or replace type to_order_list is table of t_order_item;
/
Note that this means you can no longer use %TYPE referencing to define the attributes of t_order_item.
Now your call to the procedure will look like this:
begin
pkg_order_management.prc_create_order(240
, to_order_list(t_order_item(2289, 2)
, t_order_item(2058, 5)
), v_order_id);
end;
/
The proper call would be this:
pkg_order_management.prc_create_order(
240,
pkg_order_management.to_order_list(
t_order_item(2289, 2),
t_order_item(2058, 5)
),
v_order_id
);
... but do you really want such an ugly code?
pkg_order_management.prc_create_order(240, v_order_item, v_order_id); looks more beautiful to me.
You need to use OBJECT not RECORD.
Please red this:
https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/objects.htm
Then you can use this nice notation:
CREATE TYPE t_order_item AS OBJECT (
product_id NUMBER,
quantity NUMBER
);
/
CREATE TYPE to_order_list IS TABLE OF t_order_item;
/
DECLARE
v_order_id NUMBER;
PROCEDURE prc_create_order (a NUMBER, order_list to_order_list, o_order_id OUT NUMBER)
IS
BEGIN
NULL;
END;
BEGIN
prc_create_order(240, to_order_list(
t_order_item(2289, 2),
t_order_item(2058, 5)
)
, v_order_id);
END;
/

Pascal list issue

I'm facing an issue connected with lists in Pascal right now.
When I add a person it goes successfully, but when I want to add next person it throws an error:
Ide: Lazarus.
Code (at the start of the code the head is equal to nil):
TYPE
Person = RECORD
name: STRING[15];
last_name: STRING[15];
age: INTEGER;
end;
pListElement = ^ListElement;
ListElement = RECORD
person: ^Person;
next: pListElement;
end;
PROCEDURE AddPerson(var head: pListElement);
PROCEDURE ShowPersons(var head: pListElement);
implementation
PROCEDURE AddPerson(var head: pListElement);
Var NewPerson: pListElement;
Begin
new(NewPerson);
Write(' Podaj imie: ');
readln(NewPerson^.Person^.name);
Write(' Podaj nazwisko: ');
readln(NewPerson^.Person^.last_name);
Write(' Podaj wiek: ');
readln(NewPerson^.Person^.age);
if (head = NIL) THEN
begin
head:= NewPerson;
NewPerson^.next:= nil;
end else
begin
NewPerson^.next:= head;
NewPerson:= head;
end;
End;
PROCEDURE ShowPersons(var head: pListElement);
Begin
if (head <> NIL) THEN
begin
WriteLn(' | ', head^.Person^.name:15, ' | ', head^.Person^.last_name:15, ' | ', head^.Person^.age:3, ' |');
ShowPersons(head^.next);
end;
End;
The problem is that while you make a new ListElement record in Addperson, you then assume the Person is magically initialized. It isn't. It needs to be looked up or created (new()'ed), depending on what it is actually good for.

Why does my program not output all my data?

program ZZX1;
{$mode objfpc}{$H+}
uses
crt,
wincrt,
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
type
Masquerader = record
Name, CountyCode: string;
Payment: real;
end;
var
Applicant: array[1..10] of Masquerader;
DemList: array[1..10] of string;
BerList: array[1..10] of string;
EsqList: array[1..10] of string;
x:integer;
Y:integer;
DemCounter:integer;
BerCounter:integer;
EsqCounter:integer;
DemAmount:real;
BerAmount:real;
EsqAmount:real;
procedure LoadData;
begin
clrscr;
X:=0;
DemCounter:=0;
BerCounter:=0;
EsqCounter:=0;
DemAmount:=0;
BerAmount:=0;
EsqAmount:=0;
repeat
X:= x+1;
repeat
write('Enter Your County Code DemM or BerM or EsqM: ');
readln(Applicant[x].CountyCode);
until (Applicant[x].CountyCode= 'DemM') or (Applicant[x].CountyCode= 'BerM') or (Applicant[x].CountyCode= 'EsqM');
If Applicant[x].CountyCode = 'DemM' then
begin
write('Enter Your Name: ');
readln(Applicant[x].Name);
write('Enter Your Total Payment: ');
readln(Applicant[x].Payment);
clrscr;
DemCounter:= DemCounter + 1;
DemAmount:= DemAmount + Applicant[x].Payment;
DemList[DemCounter]:= Applicant[x].Name;
end;
If Applicant[x].CountyCode = 'BerM' then
begin
write('Enter Your Name: ');
readln(Applicant[x].Name);
write('Enter Your Total Payment: ');
readln(Applicant[x].Payment);
clrscr;
BerCounter:= BerCounter + 1;
BerAmount:= BerAmount + Applicant[x].Payment;
BerList[BerCounter]:= Applicant[x].Name;
end;
If Applicant[x].CountyCode = 'EsqM' then
begin
write('Enter Your Name: ');
readln(Applicant[x].Name);
write('Enter Your Total Payment: ');
readln(Applicant[x].Payment);
clrscr;
EsqCounter:= EsqCounter + 1;
EsqAmount:= EsqAmount + Applicant[x].Payment;
EsqList[EsqCounter]:= Applicant[x].Name;
end;
until x=6 ;
end;
Procedure PrintData;
begin
Y:= 0;
for y := 1 to 6 do
begin
writeln('Name: ', Applicant[y].Name);
writeln('CountyCode: ', Applicant[y].CountyCode);
writeln('Payment: ', Applicant[y].Payment:0:2);
writeln;
end;
For Y:= 1 to DemCounter do
begin
writeln(DemList[Y]);
writeln(DemCounter,'',' persons are registered in Demerara');
writeln;
writeln('DemTotal:$ ', DemAmount:0:2);
end;
For Y:= 1 to BerCounter do
begin
writeln(BerList[Y]);
writeln(BerCounter,'',' persons are registered in Berbice');
writeln;
writeln('BerTotal:$ ', BerAmount:0:2);
end;
For Y:= 1 to EsqCounter do
begin
writeln(EsqList[Y]);
writeln(EsqCounter,'',' persons are registered in Essequibo');
writeln;
writeln('EsqTotal:$ ', EsqAmount:0:2);
end;
end;
Procedure quit;
begin
writeln('Press <Enter> To Quit');
readln;
end;
begin
LoadData;
PrintData;
quit;
end.
This program currently collects 6 persons and groups them by their countycode, calculating the total amount of persons and money collected by each county.
When I run the program below my expected output is on the screen for a few seconds then it disappears leaving only a piece of the expected output( The end Part). Please assist.
If there are characters in the keyboard buffer when the program reaches the readln; statement in the procedure quit, readln will read those characters and continue onwards rather than waiting for further input before continuing.
To check this, try adding a character variable as a parameter to readln and write the ASCII value of the character out (or check its value in a debugger) to see if there is anything in that variable after the readln.
(EDIT)
After further thinking, I wonder if the code like:
For Y:= 1 to EsqCounter do
begin
writeln(EsqList[Y]);
writeln(EsqCounter,'',' persons are registered in Essequibo');
writeln;
writeln('EsqTotal:$ ', EsqAmount:0:2);
end;
... should actually read something like:
For Y:= 1 to EsqCounter do
begin
writeln(EsqList[Y]);
end;
writeln(EsqCounter,'',' persons are registered in Essequibo');
writeln;
writeln('EsqTotal:$ ', EsqAmount:0:2);
... because otherwise the same values of EsqCounter and EsqTotal will be output EsqCounter times, which seems unnecessary.

read() strings of variable length

I've got rows of two values (input from console) that look likes this:
David 89000
Peter 99500
Jim 23999
END 1
is there a way to save the string and number into a variable other than to loop-read a char when you don't know the string length?
str:=''; salary:=0; i:=1;
while str<> 'END' do
begin
str:=''; salary:=0;
read(ch);
while ch <> ' ' do
begin
str:=str+ch;
read(ch);
end;
read(salary);
array[i].name:=str;
array[i].salary:=salary;
i:=i+1;
readln;
end;
You can do it with a single call to ReadLn and then parse the input yourself:
var
TextIn: string;
Person: string;
Salary: Integer;
begin
while true do
begin
ReadLn(TextIn); // Requires user to hit Enter
if Copy(TextIn, 1, 3) <> 'END' then
begin
Person := Copy(TextIn, 1, Pos(' ', TextIn) - 1);
Salary := StrToInt(Copy(TextIn, Pos(' ', TextIn) + 1, 255);
end
else
Exit;
end;
end;
I didn't include any error checking (which should be there), because your original code doesn't have any either.
Not with standard I/O functions. Of course you can put that code in a separate procedure, or split with tstringlist.

Resources