Pascal. Case instead If - if-statement

I m just trying to write my second (yes, it s absolutely new for me) teaching programm on Pascal. I ve made once, using "if", here it is:
program DemoBool;
Var A: Boolean ; B: Boolean ;
C:Integer ; D:Integer ;
I:Integer;
begin
write('Enter A(1/0): '); readln(I);
if (I= 1)
then A:=true else A:=false;
writeln(A);
write('Enter B(1/0): '); readln(I);
if I=1
then B:=true else B:=false;
writeln(B);
write('enter C: '); readln(C);
write('enter D: '); readln(D);
IF ((A=B) AND (C>D)=TRUE OR NOT A )
THEN IF ((TRUE<>A) AND (C-D<3))
THEN writeln('a=b, c>d, or not A=true, (true<>a and c-d<3)=true')
ELSE writeln('a=b, c>d, or not A=true, (true<>a and c-d<3)=false')
ELSE writeln('a<>b, c<d, or not A=false') ;
readln;
end.
And how can I use case instead if for latest conditions?..
Can I write new Var-s , F, F2- Boolean and then somehow, making this:
F:= ((A=B) AND (C>D)=TRUE OR NOT A ) ;
F2:= ((TRUE<>A) AND (C-D<3));
use Case?
It s really not easy for me, but hope, I can manage this task) sorry for my explanation. Thank you for attention

There are several improvments possible to your use of boolean, but this is normal since you learn.
1
if (I= 1) then A:=true else A:=false;
You can directly assign to A the comparison result of I equal to 1
A := (I = 1);
Which leads to better byte code, even without optimization (a TEST than a SETZ instruction). The Paren pair is just for readability.
2
IF ((A=B) AND (C>D)=TRUE OR NOT A )
You don't need to compare the result of boolean operation to true of false.
if ((a=b) and (c>d) or not a)
The expression statements (a=b) and (c>d) already evaluates to a Boolean.
3
If you want to use the case of expression, let's say to replace the end of the program:
case (A = B) and (C > D)) and A and (C - D < 3) of
true: writeln('yep');
false: writeln('nope');
end;
note that I use the simplified statements of lurker comment.

As far as I understood you insisted on using a case statement. Though I entirely agree with #lurker and suppose that case statement is not useful here I have the following proposal.
program DemoBool;
var
BitLogic: byte;
tmpb: byte;
A: Boolean;
B: Boolean;
C: Integer;
D: Integer;
I: Integer;
function GetBoolBit(const B: Boolean; Offset: byte): byte;
begin
if B then
begin
result := 1;
result := result shl Offset;
end
else
result := 0;
end;
begin
//input the values
BitLogic := GetBoolBit(A = B, 0);
tmpb := GetBoolBit(A, 1);
BitLogic := tmpb or BitLogic;//make comparison and store the result
// in bit-by-bit mode - every new boolean with the new offset
// the code is unscrolled here. We can optimize it writing the following instead:
// BitLogic := GetBoolBit(A, 1) or BitLogic;
tmpb := GetBoolBit(C > D, 2);
BitLogic := tmpb or BitLogic;
tmpb := GetBoolBit(C - D < 3, 3);
BitLogic := tmpb or BitLogic;
// we get the following the lower bit will store the first boolean - A=B
// the second - the second - A
// the third - C>D etc.
// the fourth - C-D<3 etc.
//now we can make an adequate case statement:
case BitLogic of
0: {00000000b}writeln('all false');
1: {00000001b}writeln('A=B');
2: {00000010b}writeln('A(=true)');
3: {00000011b}writeln('A and A=B');
4: {00000100b}writeln('C>D');
5: {00000101b}writeln('C>D and A=B');
6: {00000110b}writeln('C>D and A');
7: {00000111b}writeln('C>D and A and A=B');
8: {00001000b}writeln('C - D < 3');
9: {00001001b}writeln('C - D < 3 and A=B');
10:{00001010b}writeln('C - D < 3 and A');
11:{00001011b}writeln('C - D < 3 and A and A=B');
12:{00001100b}writeln('C - D < 3 and C>D');
13:{00001101b}writeln('C - D < 3 and C>D and A=B');
14:{00001110b}writeln('C - D < 3 and C>D and A');
15:{00001111b}writeln('C - D < 3 and C>D and A and A=B');
end;
end.
P.S. Check the logics of your if then else statements. There is a false decision: you decide that if not C > D then C < D. It is C <= D. I would advise you to read this SO answer as well.

Related

How can I optimize my code so that I dont duplicate it

I'm trying to create a procedure that puts "-" between different dates and "0" if the is single digit, but i'm having a very hard time not duplicating my code.
procedure put (Date : in Date_Type) is
begin
Put(Date.Y, Width => 1);
Put("-");
if Date.M <= 9 then
Put("0");
end if;
Put(Date.M, Width => 1);
Put("-");
if Date.D <= 9 then
Put("0");
end if;
Put(Date.D, Width => 1);
end put;
This is the best solution I came up with
An example of a nested procedure is:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Main is
subtype Year_Num is Integer range 1_900 .. 2_040;
subtype Month_Num is Integer range 1 .. 12;
subtype Day_Num is Integer range 1 .. 31;
type Date_Type is record
Y : Year_Num;
M : Month_Num;
D : Day_Num;
end record;
procedure Put (Date : Date_Type) is
procedure zerofill (Val : in Integer) is
begin
Put ("-" & (if (Val < 10) then "0" else ""));
Put (Item => Val, Width => 0);
end zerofill;
begin
Put (Item => Date.Y, Width => 0);
zerofill (Date.M);
zerofill (Date.D);
end Put;
A_Date : Date_Type := (2022, 12, 8);
begin
Put (A_Date);
end Main;
The nested nature of this answer is because the zerofill procedure is defined within the put procedure.
Came to this solution, I didnt duplicate my code but I somehow feel like I made it more complicated
procedure Zero(item : in integer) is
begin
Put("-");
if item < 10 then
Put('0');
end if;
Put(Item,Width =>0);
end Zero;
procedure put (Date : in Date_Type) is
begin
Put(Date.Y, Width => 0);
Zero(Date.M);
Zero(Date.D);
end put;

VHDL 3-8 decoder using if else syntax error near 'else' and 'process'

I've been trying to compile this program and tried to make edits according to my understanding of the error message that increased the amount of errors. This is the 2nd VHDL code I've ever written and I'm not sure what more I can do
this is the code:
entity maashro3o is
port (Q: out bit_vector (0 to 7);
A: in bit_vector(2 down to 0);
en: in bit);
end maashro3o;
architecture maashro3o of maashro3o is
begin
process(A, en)
begin
if (en = "1")
then
if (A = "000")
then
Q <= "10000000";
else if (A = "001") then
Q <= "01000000";
else if (A = "010") then
Q <= "00100000";
else if (A = "011") then
Q <= "00010000";
else if (A = "100") then
Q <= "00001000";
else if (A = "101") then
Q <= "00000100";
else if (A = "110") then
Q <= "00000010";
else if (A = "111") then
Q <= "00000001";
END If;
else
Q <= "00000000";
End If;
end process;
end maashro3o
Update
I changed else if to elsif and else respectively.
I tried to remove then from else but I'm getting similar errors
entity maashro3o is
port (Q: out bit_vector (0 to 7);
A: in bit_vector(2 downto 0);
en: in bit);
end maashro3o;
architecture maashro3o of maashro3o is
begin
process(A, en)
begin
if (en = '1')
then
if (A = "000")
then
Q <= "10000000";
elsif (A = "001") then
Q <= "01000000";
else (A = "010") then
Q <= "00100000";
elsif (A = "011") then
Q <= "00010000";
else (A = "100") then
Q <= "00001000";
elsif (A = "101") then
Q <= "00000100";
else (A = "110") then
Q <= "00000010";
elsif(A = "111") then
Q <= "00000001";
END If;
else
Q <= "00000000";
End If;
end process;
end maashro3o;
You need to change all the elses inside the block begins with
if (A="000") then
.
.
.
end if;
There is no "else if" keyword in VHDL. Use "elsif". When coding an if-else statement with multiple conditions, you should not write else after elsif or vice versa. You can not use them both.
"else" keyword does not declare a specific statement. It is used for checking only one condition and doing something when condition is not satisfied.
Also when writing a VHDL code, don't forget to include the libraries you will need and may be need.
Corrected code is given below.
library ieee;
use ieee.std_logic_1164.all;
entity maashro3o is
port (Q: out bit_vector (0 to 7);
A: in bit_vector(2 downto 0);
en: in bit);
end maashro3o;
architecture maashro3o of maashro3o is
begin
process(A, en)
begin
if (en = '1') then
if (A = "000") then
Q <= "10000000";
elsif (A = "001") then
Q <= "01000000";
elsif (A = "010") then
Q <= "00100000";
elsif (A = "011") then
Q <= "00010000";
elsif (A = "100") then
Q <= "00001000";
elsif (A = "101") then
Q <= "00000100";
elsif (A = "110") then
Q <= "00000010";
elsif(A = "111") then
Q <= "00000001";
end if;
else
Q <= "00000000";
end if;
end process;
end maashro3o;
Why do you want to use if else statements only, since decoder is a combinational logic you can use case statement to design the logic, it will be more appropriate.

sas logical operators not functioning as expected

I have a condition which follows this logic Av(B^C) which is equivalent to (AvB) ^ (AvC).
Where:
A = NAF> 2
B= (COUNT_INT + COUNT_NOINT < 25)
C= (NAF> 1)
This is the condition given in the specs:
NAF> 2 OR (( COUNT_INT + COUNT_NOINT < 25) AND (NAF> 1))
This is how I coded it in sas, but its not producing the correct results. I appreciate any suggestions. Thanks.
Actually this is where it fails when I code up the array :
if (sum(count_int_arr[i],count_nonint_arr[i]) lt 25 ) and
( naf_arr[i] gt 2) or (naf_arr[i] gt 1) then check_naf_arr[i] = "bad";
The way you coded it is not what you gave in the initial specs. Your code is equivalent to (A AND B) OR C, whereas you want A OR (B AND C).
This should give you correct results:
DATA myData;
/* (...) */
DO i = 1 TO someValue;
IF (naf_arr[i] > 2) OR (SUM(count_int_arr[i], count_nonint_arr[i]) < 25 AND naf_arr[i] > 1)
THEN check_naf_arr[i] = "bad";
END;
/* (...) */
run;

If condition in for loop in Pascal

I have problem. If condition in for loop is checking only once. What's the problem? Here is my code:
program Planas;
function skaiciuoti() : integer;
var z, zz, d, dt, dp, i, sk : integer;
Fr, Fw : text;
begin
Assign(Fr, 'Duomenys.txt');
Reset(Fr);
ReadLn(Fr, d, z);
zz := 0;
dt := d;
for i := 1 to d do
begin
Read(Fr, sk);
zz := zz + sk;
if sk >= z then
dt := d - 1;
end;
z := d * z - zz;
dp := z div d;
if z mod d <> 0
then dp := dp + 1;
Close(Fr);
WriteLn(dt);
WriteLn(z);
WriteLn(dp);
end;
begin
skaiciuoti();
Readln;
end.
P.S Thank you for your answers in advance! :)
Perhaps you have a typo in your code in dt := d - 1. The value of d seems to be constant within the loop, so dt would not change after the first successful check. I guess you might have wanted to decrement dt by using dt := dt - 1.

get last number part of a String in PL/SQL

In PL/SQL, is there any way to calculate next serial number from another one like 'A1B0010C'. Next serial no will be A1B0011C (+1). My idea is retrieve number part, increase it get return string back.
I can do this in java, but passing more than 1000 elements to Oracle will cause problems in IN clause.
So please help, any suggestion is appreciated.
Try to write some recursive function like this
This Function returns next character. ex: D after C. 0 after Z.
create or replace function get_next_character(ch char)
return char
is
result_ch char(1) := ch;
begin
IF UPPER(ch) = 'Z' or ch = '9' THEN
result_ch := 'A';
ELSE
result_ch := chr(ascii(ch) + 1);
END IF;
return upper(result_ch);
end get_next_character;
and this is your actual function which returns the next serial number
So, it generates 'A1B0010D' if your input is 'A1B0010C'
create or replace function get_next_serial(p_serial IN varchar2) -- PASS THE REQUIRED ARGUMENTS
return varchar2
IS
v_ret_serial varchar2(100);
v_in_serial varchar2(100) := p_serial;
tmp varchar2(100);
last_char char(1);
begin
tmp := v_in_serial;
for i in reverse 1..length(v_in_serial) loop
last_char := substr(tmp, length(tmp));
last_char := get_next_character(last_char);
tmp := substr(v_in_serial, 1, length(tmp)-1);
v_in_serial := substr(v_in_serial, 1, i-1) || last_char || substr(v_in_serial, i+1);
IF last_char <> 'A' then
exit;
END IF;
end loop;
IF last_char = 'A' THEN
v_in_serial:= 'A'||v_in_serial;
END IF;
return UPPER(v_in_serial);
exception
when NO_DATA_FOUND then
return 'AA';
when others then
return null;
end get_next_serial;
you can call this function (get_next_serial('abc')) where ever you want;
select get_next_serial('ALK0989KJ') from dual
You can place these two functions in a package and use at your convenience.
You can achieve it by using the following mix of Regexp_* functions:
SQL> with t1 as(
2 select 'A1B0010C' col from dual
3 )
4 select regexp_replace(col, '[[:digit:]]+'
5 , to_char(to_number(regexp_substr(col, '[[:digit:]]+',1,2) + 1), 'fm0000')
6 , 1
7 , 2
8 ) as Res
9 from t1
10 ;
RES
------------
A1B0011C
UPDATE In response to the comment.
SQL> with t1 as(
2 select 'A1B0010C' col from dual union all
3 select 'A1B0010C2' col from dual union all
4 select 'A1B0012C001' col from dual union all
5 select 'S000001' col from dual
6 )
7 select col
8 , regexp_replace(col
9 , '([[:digit:]]+)([[:alpha:]]+$|$)'
10 , LPad(to_char(to_number(num) + 1), length(num), '0') || '\2'
11 ) as Res
12 from (select col
13 , regexp_substr(col, '([[:digit:]]+)([[:alpha:]]+$|$)', 1, 1, 'i', 1) as num
14 from t1
15 )
16 ;
COL RES
----------- -----------------
A1B0010C A1B0011C
A1B0010C2 A1B0010C3
A1B0012C001 A1B0012C002
S000001 S000002
create or replace function nextSerial(s in varchar2) return varchar2 as
i integer;
done boolean := false;
c char;
newserial varchar2(4000);
begin
newserial := s;
i := length(newserial);
while i>0 and not done loop
c := substr(newserial, i, 1);
if c='9' then
newserial := substr(newserial, 1, i-1) || '0' || substr(newserial, i+1);
elsif c>='0' and c<='8' then
c := chr(ascii(c)+1);
newserial := substr(newserial, 1, i-1) || c || substr(newserial, i+1);
done := true;
end if;
i := i-1;
end loop;
if not done then
newserial := '1' || newserial;
end if;
return newserial;
end;