Creating plsql function for Factorial program - plsql

When I call the function using select statement
[select fact(5) from dual;]
I get output as 1.Can you guys please help me from the below code
create or replace function fact(num in number)
return number
Is
res_fact number:=1;
begin
for i in 1..5 loop
res_fact:=res_fact*i;
dbms_output.put_line(res_fact);
-- dbms_output.put_line('Factorial of '||num||' = '||res_fact);
return res_fact;
end loop;
dbms_output.put_line(res_fact);
end;
res_fact=res_fact*i;
as i call function i used to get the factorial of that input number
res_fact=5*4*3*2*1;
res_fact=120

Make this code "return res_fact;" out of loop you code will run, But above code work for only 5.

Two issues....
Firstly you need to move your return statement outside of your loop. As you now have it it will return on the first pass through the loop.
Secondly you are ignoring your input parameter and always going to get factorial of 5 rather than what is passed in (once you move your return statement.
See code below
create or replace function fact(num in number)
return number
Is
res_fact number:=1;
begin
for i in 1..num loop
res_fact:=res_fact*i;
end loop;
dbms_output.put_line('Factorial of '||num||' = '||res_fact);
return res_fact;
end;

Related

PLS-00103: Encountered the symbol “CREATE”

its showing error in 27 line create or replace function Buffalo
Declare
random_number number(4);
user_number number(4);
cow number(1);
buffaloes number(1):=0;
begin
random_number:=uniquetest(random_number);
/*random_number:=dbms_random.value(1000,9999);*/
dbms_output.put_line(random_number);
user_number:=&user_number;
while(user_number!=random_number)
loop
buffaloes:=Buffalo(user_number,random_number);
dbms_output.put_line('0'||'c'||buffaloes||'B');
buffaloes:=0;
user_number:=0;
user_number:=&user_number;
end loop;
end;
/*error in this line */
create or replace function Buffalo
(user_number in number,random_number in number)
return number
is
user_comparision number(1);
random_comparision number(1);
buffaloes number(1);
user_number1 number(4):=user_number;
random_number1 number(4):=random_number;
begin
while(user_number!=random_number)
loop
user_comparision:=user_number1 mod 10;
random_comparision:=random_number1 mod 10;
user_number1:=user_number1/10;
random_number1:=random_number1/10;
if(user_comparision = random_comparision)
then
buffaloes:=buffaloes+1;
end if;
end loop;
return buffaloes;
end;/
it is showing error in create statement. can anybody help me in solving this error.
Tell how to solve this create statement error.
it is showing error in create statement. can anybody help me in solving this error.
Tell how to solve this create statement error.
You should make 2 scripts of it. Currently you're starting off with a anonymous block, that is actually calling the function buffalo, while it hasn't been created yet.
Both the anonymous block and the function seem to be creating some infinite loop by the way,
So I'm not sure what you're trying to achieve here..
Without knowing the background of this problem it's impossible to give a solution.

On keydown in Ada

I would need to execute some function when the user presses the "escape" key in my Ada program. I know we can retrieve what he enters thanks to get_line but it's not exactly what I need to do.
Indeed, I don't want to stop the program until he enters "escape".
First, is it possible ?
It is possible to get the characters without the need to press enter using :
Ada.Text_IO.Get_Immediate (Answer)
with Answer, a Character.
And the escape key is ASCII 27, so you can check whether Character'Pos(Answer) equals 27 or not. Also, as suggested in the comments, you can also compare Answer to Ada.Characters.Latin_1.ESC.
Here is an example of a program that display "Yeah!!!1!!1!" in a loop until the key ESC is pressed.
with Ada.Characters.Latin_1;
with Ada.Text_IO;
procedure Test is
Finished : Boolean := False;
task Escape_Task;
task body Escape_Task is
Answer : Character;
begin
loop
Ada.Text_IO.Get_Immediate(Answer);
if Answer = Ada.Characters.Latin_1.ESC then
Finished := True;
exit;
end if;
end loop;
end Escape_Task;
begin
while not finished loop
Ada.Text_IO.Put_Line("Yeahh!!!1!!1!");
end loop;
end Test;

Ada actual for "S" must be a variable

So here is a piece of my body file. I am getting the error "words.adb:75:42: actual for "S" must be a variable".
procedure Remove_Character(S : in out Ustring; C : in Character; Successful : out Boolean) is
begin
for I in 1..length(S) loop
if Element(S, I) = C then
Delete(S, I, I);
Successful := true;
return;
end if;
end loop;
Successful := false;
end Remove_Character;
function Is_Subset(Subset : Ustring; S : Ustring) return Boolean is
Could_Remove : Boolean;
begin
for I in 1..length(Subset) loop
Remove_Character(S , Element(Subset, I), Could_Remove);
if Could_Remove = false then
return false;
end if;
end loop;
return True;
end Is_Subset;
I understand where my error is coming from. Remove_Character uses S : in out Ustring while function Is_Subset uses S : in Ustring.
My question is how do I change the variable from Remove_Character into only an in Ustring?
Sorry if this is a tad jumbled, I'm fairly new to both programming and the site.
You can't, at least not directly.
I don't know what a UString is, but I presume the Delete procedure modifies it. If you changed the declaration of S in Remove_Character to S: in Ustring, you'd presumably get an error on the call to Delete.
The simplest approach I can think of would be to make a copy of S in Is_Subset:
Copy_Of_S: UString := S;
and then pass the (modifiable) copy to Remove_Character.
By "simplest", I mean it makes the smallest change to your existing code. But you should probably consider reorganizing it. Determining whether one UString is a subset of another by modifying one of the strings doesn't seem like the best approach; I'm sure there's a more efficient way to do it.
A minor and irrelevant point: this:
if Could_Remove = false then
is better written as:
if not Could_Remove then

Writing a function inside a PL/SQL page

I want to create a function that do a specific task inside a oracle package, I tried with the bellow code, but it gives an error that I don't understand.
CREATE OR REPLACE
PACKAGE DINIDU_EXE_PACKAGE AS
FUNCTION EXE14
(SUP_ID_ SUPPLIER_PART_PROJECT_TAB.SUPPLIER_ID%TYPE,PAR_ID_ SUPPLIER_PART_PROJECT_TAB.PART_ID%TYPE,PRO_ID_ SUPPLIER_PART_PROJECT_TAB.PROJECT_ID%TYPE) RETURN NUMBER IS
QUNTITY_FOR_A_PROJECT_ NUMBER;
BEGIN
SELECT QUENTITY AS QUNTITY_FOR_A_PROJECT_ FROM SUPPLIER_PART_PROJECT_TAB WHERE SUPPLIER_ID=SUP_ID AND PART_ID=PAR_ID AND PRO_ID=PROJECT_ID;
IF QUNTITY_FOR_A_PROJECT_ >0 THEN
RETURN QUNTITY_FOR_A_PROJECT_;
ELSE
RETURN 0;
END IF;
END EXE14;
END;
Error(6,1): PLS-00103: Encountered the symbol "QUNTITY_FOR_A_PROJECT_" when expecting one of the following: language
Egor is right in his comment. You are putting a function in to the package specification while it has to be in package body instead.
Only a reference to a function or its signature - function name and arguments list - have to be in the package specification. The actual function has to be coded in the body.
CREATE OR REPLACE PACKAGE DINIDU_EXE_PACKAGE AS
FUNCTION EXE14
( SUP_ID_ SUPPLIER_PART_PROJECT_TAB.SUPPLIER_ID%TYPE
, PAR_ID_ SUPPLIER_PART_PROJECT_TAB.PART_ID%TYPE
,PRO_ID_ SUPPLIER_PART_PROJECT_TAB.PROJECT_ID%TYPE)
END;
/
CREATE OR REPLACE PACKAGE BODY DINIDU_EXE_PACKAGE AS
FUNCTION EXE14
( SUP_ID_ SUPPLIER_PART_PROJECT_TAB.SUPPLIER_ID%TYPE
, PAR_ID_ SUPPLIER_PART_PROJECT_TAB.PART_ID%TYPE
,PRO_ID_ SUPPLIER_PART_PROJECT_TAB.PROJECT_ID%TYPE)
RETURN NUMBER IS
QUNTITY_FOR_A_PROJECT_ NUMBER;
BEGIN
SELECT QUENTITY AS QUNTITY_FOR_A_PROJECT_ FROM SUPPLIER_PART_PROJECT_TAB WHERE SUPPLIER_ID=SUP_ID AND PART_ID=PAR_ID AND PRO_ID=PROJECT_ID;
IF QUNTITY_FOR_A_PROJECT_ >0 THEN
RETURN QUNTITY_FOR_A_PROJECT_;
ELSE
RETURN 0;
END IF;
END EXE14;
END;
/
EDIT: see Egor's comment and Rachcha's answer for the actual cause of the compilation error.
Your code first declares QUNTITY_FOR_A_PROJECT_ as a local variable, but then your SELECT statement uses the same identifier as a column alias (QUENTITY AS QUNTITY_FOR_A_PROJECT_). More importantly, you have not selected the result INTO anything.
I think you meant to do something like this:
SELECT QUENTITY INTO QUNTITY_FOR_A_PROJECT_ FROM SUPPLIER_PART_PROJECT_TAB ...
Another problem: your function accepts the following parameters: SUP_ID_, PAR_ID_ and PRO_ID_, but you don't use them in your function. I suspect the identifiers are not used correctly in the query, but I cannot know for sure because I don't know what the columns of your SUPPLIER_PART_PROJECT_TAB table are.

Ada String Concatenation

I have a function that returns a string for a particular item, and I need to call that function numerous times and combine those strings into one. The combined string is bounded. I've made sure to fill it when space characters when it initializes but I keep getting "length check failed" errors. Is there something basic I'm doing wrong here?
FOR I IN 1..Collection.Size LOOP
Combined_String := combined_string & Tostring(Collection.Book(I));
END LOOP;
Unbounded_String is probably the easiest way to go:
with Ada.Strings.Unbounded;
use Ada.Strings.unbounded;
...
Temp_Unbounded_String : Unbounded_String; -- Is empty by default.
...
for I in 1 .. Collection.Size loop
Append(Temp_Unbounded_String, ToString(Collection.Book(I));
end loop;
If you then need to have the result placed in your fixed length standard string:
declare
Temp_String : constant String := To_String(Temp_Unbounded_String);
begin
-- Beware! If the length of the Temp_String is greater than that of the
-- fixed-length string, a Constraint_Error will be raised. Some verification
-- of source and target string lengths must be performed!
Combined_String(Temp_String'Range) := Temp_String;
end;
Alternatively, you can use the Ada.Strings.Fixed Move() procedure to bring the Unbounded_String into the target fixed-length string:
Ada.Strings.Fixed.Move(To_String(Temp_Unbounded_String), Combined_String);
In this case, if the source string is "too long", by default a Length_Error exception is raised. There are other parameters to Move() that can modify the behavior in that situation, see the provided link on Move for more detail.
In order to assign Combined_String, you must assign the full correct length at once. You can't "build up" a string and assign it that way in Ada.
Without seeing the rest of your code, I think Ada.Strings.Unbounded is probably what you should be using.
I know this is an ancient question, but now that Ada 2012 is out I thought I'd share an idiom I've been finding myself using...
declare
function Concatenate(i: Collection'index)
is
(tostring(Collection(i) &
if (i = Collection'last) then
("")
else
(Concatenate(i+1))
);
s: string := Concatenate(Collection'first);
begin
Put_Line(s);
end;
Typed off the top of my head, so it'll be full of typos; and if you want it to work on empty collections you'll need to tweak the logic (should be obvious).
Ada 2012's expression functions are awesome!
Ada works best when you can use perfectly-sized arrays and strings. This works wonderfully for 99% of string uses, but causes problems any time you need to progressively build a string from something else.
Given that, I'd really like to know why you need that combined string.
If you really need it like that, there are two good ways I know of to do it. The first is to use "unbounded" (dynamically-sized) strings from Ada.Strings.Unbounded, as Dave and Marc C suggested.
The other is to use a bit of functional programming (in this case, recursion) to create your fixed string. Eg:
function Combined_String (String_Collection : in String_Collection_Type) return String is
begin
if String_Collection'length = 1 then
return String_Collection(String_Collection'first);
end if;
return String_Collection(String_Collection'first) &
Combined_String (String_Collection'first + 1 .. String_Collection'last);
end Combined_String;
I don't know what type you used for Collection, so I'm making some guesses. In particular, I'm assuming its an unconstrained array of fixed strings. If it's not, you will need to replace some of the above code with whatever your container uses to return its bounds, access elements, and perform slicing.
From AdaPower.com:
function Next_Line(File : in Ada.Text_IO.File_Type :=
Ada.Text_Io.Standard_Input) return String is
Answer : String(1..256);
Last : Natural;
begin
Ada.Text_IO.Get_Line(File => File,
Item => Answer,
Last => Last);
if Last = Answer'Last then
return Answer & Next_Line(File);
else
return Answer(1..Last);
end if;
end Next_Line;
As you can see, this method builds a string (using Get_Line) of unlimited* length from the file it's reading from. So what you'll need to do, in order to keep what you have is something on the order of:
function Combined_String (String_Collection : in String_Collection_Type)
Return String is
begin
if String_Collection'length = 1 then
Return String_Collection(String_Collection'First).All;
end if;
Recursion:
Declare
Data : String:= String_Collection(String_Collection'First).All;
SubType Constraint is Positive Range
Positive'Succ(String_Collection'First)..String_Collection'Last;
Begin
Return Data & Combined_String( String_Collection(Constraint'Range) );
End Recursion;
end Combined_String;
Assuming that String_Collection is defined as:
Type String_Collection is Array (Positive Range <>) of Access String;
*Actually limited by Integer'Range, IIRC

Resources