Redefine variables which names depends of what user enters - pascal

I have some variables ordered by numebers, like ex1,ex2,ex3,etc (integers); i'd like to count how many times the user enter a letter of a number in a way such that if '1' is entered the program adds +1 to ex1, if 2 is enteres the program adds +1 to ex2- and so on (I can't use arrays because it's forbidden in the excersise). For example, if i ask the user to enter 15 numbers between 1 and 15, and i would like to count how many times each one of those is entered, the code i'm thinking of would be something like
for i:=1 to 15 do
read(number);
if number = i then
Begin
exi := exi + 1;
End
Obviously that didn't work. Is it possible to redefine a variable doing something similar?.

If you can't use arrays at all, you have just a couple of choices.
A case statement
for i := 1 to 15 do
begin
Read(number);
case number of
1: ex1 := ex1 + number;
2: ex2 := ex2 + number;
// rest of possible values and variables
else
// Handle number that doesn't have a variable
end;
end;
if..else statements
for i := 1 to 15 do
begin
Read(number);
if number = 1 then
ex1 := ex1 + number
else if number = 2 then
ex2 := ex2 + number
else if // rest of possible values and variables
else // Handle number that doesn't have a variable
end;
end;

Related

Alternate to DECODE like function to be used in elsif statement in PLSQL procedure

I am trying to use a condition elsif where something like decode needs to be used so that the condition is true and insertion is made. I am doing this in a procedure and condition is like
elsif ((v_DIVIDEND/Divisor)-1 < ABS(0.2)) then
insert into table(Divisor,b,c) values(Dividend,y,z);
It works fine when the divisor is not zero but when the divisor is zero it fails. I want to rule out zeroes in divisor using like another nested if condition within elsif or something like decode. I tried another if but syntax seemed to be wrong. Using Decode says it can only be used in SQL statement. Any suggestions, please...
you can also handle the "divisor equal to zero" exception and made the insert if the error occurs, see samples code in handling "divisor equal to zero" exception,
Sample 1: This sample defines a divisor_equal_to_zero exception
DECLARE
divisor_equal_to_zero EXCEPTION;
PRAGMA EXCEPTION_INIT(divisor_equal_to_zero, -1476);
v_divisor NUMBER := 0;
v_quotient NUMBER;
BEGIN
v_quotient := 1/v_divisor;
DBMS_OUTPUT.PUT_LINE('Print A: '||v_quotient);
EXCEPTION
WHEN divisor_equal_to_zero THEN
v_divisor := 1;
v_quotient := 1/v_divisor;
DBMS_OUTPUT.PUT_LINE('Print B: '||v_quotient);
--you can put the insert statement here
END;
/
Sample 2: This sample use the pre-defined ZERO_DIVIDE exception
DECLARE
v_divisor NUMBER := 0;
v_quotient NUMBER;
BEGIN
v_quotient := 1/v_divisor;
DBMS_OUTPUT.PUT_LINE('Print A: '||v_quotient);
EXCEPTION
WHEN ZERO_DIVIDE THEN
v_divisor := 1;
v_quotient := 1/v_divisor;
DBMS_OUTPUT.PUT_LINE('Print B: '||v_quotient);
--you can put the insert statement here
END;
/
Well, depending on what you want to get as a result when divisor = 0 (i.e. something large or something small), you can use something like this:
For small result (divide by 1E99):
case when divisor = 0 then 1E99 else divisor end
For large result (divide by 1E-99)
case when divisor = 0 then 1E-99 else divisor end
As of you being unable to use DECODE: that's correct, it can be used ONLY within the SELECT statement. It means that you should rewrite your code and put everything into SELECT (which is probably a bad idea). So - try CASE.
Maybe you could add a condition like this to check if Divisor is zero.
elsif ( Divisor !=0 ) and ((v_DIVIDEND/Divisor)-1 < ABS(0.2))
THEN
insert into table(Divisor,b,c) values(Dividend,y,z)
elsif Divisor = 0
THEN
insert into table(Divisor,b,c) values(?,?,?);
You can try nullif:
declare
divisor constant integer := 0;
result number;
begin
result := 100 / nullif(divisor,0);
end;
Here divisor is replaced with null if it has the value 0, giving the result as null.

Finding the exponent (without using POW or built in functions) of a number using a procedure and/or Function

I am trying to create a way to find the exponent of a number (in this case the base is 4 and the exponent 2 so the answer should be 16) using a procedure without using the POW Function or any built in functions to find the exponent. Eventually I would like to take input numbers from the user.
set serveroutput on;
CREATE OR REPLACE PROCEDURE Exponent(base number, exponent number) as
answer number;
BEGIN
base := 4;
exponent := 2;
LOOP
IF exponent > 1 THEN
answer := base * base;
END IF;
END LOOP;
dbms_output.put_line('Answer is: ' || answer);
END;
/
Error(7,25): PLS-00103: "expression 'BASE' cannot be used as an assignment target" and "expression 'EXPONENT' cannot be used as an assignment target"
Any ideas on how to solve the error and/or better ways of getting the exponent without using built-in functions like POW?
In your procedure base and exponent are input parameters and can't be changed. You've got a couple of options:
1) copy the parameters to variables internal to the procedure and manipulate those internal values, or
2) change the parameters to be input/output parameters so you can change them.
Examples:
1)
CREATE OR REPLACE PROCEDURE Exponent(pin_base number, pin_exponent number) as
base number := pin_base;
exponent number := pin_exponent;
answer number;
BEGIN
base := 4;
exponent := 2;
LOOP
IF exponent > 1 THEN
answer := base * base;
END IF;
END LOOP;
dbms_output.put_line('Answer is: ' || answer);
END;
2)
CREATE OR REPLACE PROCEDURE Exponent(base IN OUT number,
exponent IN OUT number) as
answer number;
BEGIN
base := 4;
exponent := 2;
LOOP
IF exponent > 1 THEN
answer := base * base;
END IF;
END LOOP;
dbms_output.put_line('Answer is: ' || answer);
END;
The best thing is that whatever Oracle provides as inbuilt functionality that serves the purpose in a best possible. (Almost all the times better then customized codes) Try to use EXP function. I have tried to make customized code per my understanding. Hope this helps.
CREATE OR REPLACE
FUNCTION EXP_DUMMY(
BASE_IN IN NUMBER,
EXPO_IN IN NUMBER)
RETURN PLS_INTEGER
AS
lv PLS_INTEGER:=1;
BEGIN
FOR I IN
(SELECT base_in COL1 FROM DUAL CONNECT BY level < expo_in+1
)
LOOP
lv:=lv*i.col1;
END LOOP;
RETURN
CASE
WHEN EXPO_IN = 0 THEN
1
ELSE
lv
END;
END;
SELECT EXP_DUMMY(2,4) FROM DUAL;

PL/SQL - how to repeat alternating text for a given number of times with a final output?

I want to make a procedure called OE that will have text output based on the number that I define.
For example, inputting the number 6 will give the following output:
odd
even
odd
even
odd
even
= even steven!
and inputting the number 5 will give the following output:
odd
even
odd
even
odd
= you oddball!
I'm completely new at this and have been struggling to get the odd number to load correctly (for some reason, it gets stuck in an infinite loop). Any help would be appreciated! Here is what I got so far:
CREATE OR REPLACE procedure oe
(p_n IN number)
AS
v_n number;
v_on number;
BEGIN
v_n := p_n;
v_on := p_n;
IF v_n>0 THEN LOOP
dbms_output.put_line('odd');
v_n := v_n-1;
dbms_output.put_line('even');
v_n := v_n-1;
If v_n=0 then
exit;
if v_on mod 2 > 0 then dbms_output.put_line('=' || ' you oddball!');
exit;
else
dbms_output.put_line('=' || ' even steven!');
exit;
end if;
end if;
end loop;
end if;
END;
/
You are not using exit conditions properly hence your code is going in infinite loop. You simplify your logic as below. Let me know it it works for you.
You may add few validations to make sure you get proper input parameters such as p_n > 0 and other.
CREATE OR REPLACE procedure oe
(p_n IN number)
AS
begin
for i in 1..p_n
loop
if mod(i,2)=1 then dbms_output.put_line('odd');
else dbms_output.put_line('even');
end if;
end loop;
if mod(p_n,2)=1 then dbms_output.put_line('= you oddball!');
else dbms_output.put_line('= even steven!');
end if;
end;
hemalp108 has already answered this, but I just wanted to add that you don't even need the if/else logic that fills the procedure (except perhaps for handling values less than 1, which I'll leave as an exercise), because we have case:
create or replace procedure oe
( p_n in number )
as
begin
for i in 1 .. p_n loop
dbms_output.put_line(case mod(i,2) when 1 then 'odd' else 'even' end);
end loop;
dbms_output.put_line(case mod(p_n,2) when 1 then '= you oddball!' else '= even steven!' end);
end;
(You may also notice how laying your code out neatly is half the way towards debugging it.)

PLS-00306: wrong number or types of arguments in function call

I cannot figure out how to call a function in SQL Developer. I'm trying to call the function GET_SUIT but it says that I am using the wrong number or type of arguments in call to 'GET_SUIT':
create or replace FUNCTION GET_SUIT
(
RND_NUM IN INTEGER,
Suit OUT VARCHAR2
) RETURN VARCHAR2 AS
BEGIN
if RND_NUM = 1 then -- Card is a Spade
Suit := 'Spades';
elsif RND_NUM = 2 then -- Card is a Heart
Suit := 'Hearts';
elsif RND_NUM = 3 then -- Card is a Diamond
Suit := 'Diamonds';
elsif RND_NUM = 4 then -- Card is an Club
Suit := 'Clubs';
end if;
RETURN Suit;
END GET_SUIT;
I am using the following statement:
SELECT dbms_random.value(1,4) into RND_NUM from dual;
dbms_output.put_line('Random number 2 is : ' || RND_NUM);
GET_SUIT(RND_NUM);
dbms_output.put_line('Suit of card is : ' || Suit);
From everything I have read I need to pass one integer in to the function, is that correct? Any help would be appreciated I know this is basic level stuff but I have other functions that I would like to use and I can't even get this simple one to work.
You get the error message for two reasons.
One, because your function takes two parameters but you have only assigned one in the call. You're missing a local variable to receive the OUT parameter.
Two, because a function returns a value. Consequently the call must assign to a local variable; alternatively we can use functions in the projection of a SELECT statement. This also means we don't use OUT parameters in the signature of a function (we could, the function still compiles, but it's bad practice).
So, write your function like this ...
create or replace FUNCTION GET_SUIT
(
RND_NUM IN INTEGER
) RETURN VARCHAR2
AS
Suit VARCHAR2(10);
BEGIN
if RND_NUM = 1 then -- Card is a Spade
Suit := 'Spades';
elsif RND_NUM = 2 then -- Card is a Heart
Suit := 'Hearts';
elsif RND_NUM = 3 then -- Card is a Diamond
Suit := 'Diamonds';
elsif RND_NUM = 4 then -- Card is an Club
Suit := 'Clubs';
end if;
RETURN Suit;
END GET_SUIT;
... and call it like this:
declare
l_suit varchar2(10);
rnd_num pls_integer;
begin
SELECT dbms_random.value(1,4) into RND_NUM from dual;
dbms_output.put_line('Random number 2 is : ' || RND_NUM);
l_suit := GET_SUIT(RND_NUM);
dbms_output.put_line('Suit of card is : ' || l_Suit);
end;
/

Concatenation with Zero is not occurring properly in code?

I was trying to reverse a number in PL/SQL. It's working fine, but when my number contains any 0, the output is unexpected. For example:
1234 output 4321
1000 output 1
1203 ouput 3021
10001 output 1
DECLARE
r number(9);
num number(9):=&p_num;
BEGIN
WHILE num>=1 LOOP
IF mod(num,10)=0 THEN -- extracting last digit of a number .
r:=r||0; --if end digit is 0 then concat r with 0
ELSE
r:=r||mod(num,10);--if mod is not 0 then it would be last digit.
END IF;
num:=trunc(num/10);--Removing last digit from number
END LOOP;
dbms_output.put_line(r);
END;
Try changing the type of the variable "r" to varchar2.
Since it's declared as number, leading zeros are discarded.
'Reversing a number' is fundamentally a string operation, not a numerical one. Numerically, the reverse of 10, 100, 1000, etc are all 1 - the leading zeroes in the result don't count. And the operation is not, therefore, invertible; all numbers with the same leading (significant) digits and with zero or more trailing zeroes produce the same output when reversed.
So, you need to revise your code to generate a character string, not a number.
You can't preserve leading zeros with numbers; you must use strings (varchar2). Try something like this to see:
DECLARE
r varchar2(9);
num varchars(9):=&p_num;
BEGIN
r := REVERSE(num);
dbms_output.put_line(r);
END;
I'm not sure what's going wrong in your code Vineet but perhaps this will work.
DECLARE
newStr varchar2(9) = "";
numStr varchar2(9) := to_char(&p_num);
i number;
BEGIN
i = length(numStr);
WHILE i>0 LOOP
newStr := newStr || substr(numStr, i, i + 1);
i = i - 1;
END LOOP;
dbms_output.put_line(r);
END;
Edit: Or as gabe correctly points out, just use the REVERSE function.
The problem is you're dealing with a NUMBER value. When you reverse 1000, you get 0001, which when output unformatted is 1.
What you really need is something akin to:
CREATE OR REPLACE FUNCTION rev(p_num NUMBER)
RETURN VARCHAR2 IS
v_chr VARCHAR2(50);
BEGIN
v_chr := p_num;
IF LENGTH(v_chr) > 1 THEN
RETURN SUBSTR(v_chr, -1, 1)||rev(SUBSTR(v_chr, 1, LENGTH(v_chr)-1));
END IF;
RETURN v_chr;
EXCEPTION
WHEN OTHERS THEN
RETURN 'Bad Input';
END;
/
Function created
SQL> SELECT rev(100000) FROM dual;
REV(100000)
--------------------------------------------------------------------------------
000001
SQL>

Resources