Pascal error: until expected else found - syntax-error

Fatal error while trying to compile "until" expected found "else", cant seem to get how to fix it
......
begin
divisor:= 2;
cont:= 0;
write(i,':');
repeat
if (i mod divisor = 0) then
begin
write(' divisor ');
divisor:=succ(divisor);
cont:=succ(cont);
end;
else
divisor:=succ(divisor);
until (cont = 6) or (divisor>i div 2)
writeln();
end;
end;
end.

The issue is that you have a semicolon after end; before else. That basically terminates the if statement so the else becomes an else to repeat (which obviously isn't valid). The fix is to remove the semicolon after end;
See this for reference: http://wiki.freepascal.org/Else
Fix:
if (i mod divisor = 0) then
begin
write(' divisor ');
cont:=succ(cont);
end
else
divisor:=succ(divisor);

Related

Oracle/sql compare two numbers

I need a SQL/Oracle function that compares two numbers
if number are even like( 22,10,4,12,6..) true
if are odd number like(3,7,13,5...) false.
CREATE OR REPLACE FUNCTION is_even(num_in NUMBER) RETURN BOOLEAN IS
BEGIN
IF MOD(num_in, 2) = 0 THEN
RETURN TRUE;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_even;
/
CREATE OR REPLACE FUNCTION is_odd(num_in NUMBER) RETURN BOOLEAN IS
BEGIN
RETURN MOD(num_in, 2) = 1;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_odd;
One point not addressed in the other answer, which I have already mentioned in the comments and you don't seem to have paid attention to is that Boolean values can only be used in PL/SQL code, not in Oracle SQL.
This restricts you from calling your function through the most common method - to use it in a sql statement. If you try running this query with your function, it would fail.
select is_even(10) FROM DUAL;
ORA-06552: PL/SQL: Statement ignored
ORA-06553: PLS-382: expression is
of wrong type
You may call this function to set a Boolean PL/SQL variable, but it isn't very useful in a general scenario.
DECLARE
v_even_odd BOOLEAN := is_even(3);
Alternatively, you could return a number or a string ( "TRUE" / "FALSE" ).
CREATE OR REPLACE FUNCTION is_even (num_in NUMBER)
RETURN VARCHAR2
IS
BEGIN
IF MOD (num_in, 2) = 0
THEN
RETURN 'TRUE';
ELSE
RETURN 'FALSE';
END IF;
END is_even;
/
Which works fine while calling from sql.
select is_even(10) FROM DUAL;
IS_EVEN(10)
----------------
TRUE
I ready don't understand what is the difficulty here, as you yourself have provided the code for two functions above...
Anyway here you go:
CREATE OR REPLACE FUNCTION is_even(num_in NUMBER) RETURN BOOLEAN IS
BEGIN
IF MOD(num_in, 2) = 0 THEN
RETURN TRUE;
else
RETURN FALSE;
END IF;
END is_even;
/

Parsing a multi line flat file in Oracle

How do i parse a multi line file using UTL_FILE? In the below example snippet -
The line starting with '1' is the File header - one per file.
The line starting with '5' is the transaction header - one per transaction
The line starting with '8' is the transaction trailer - one per transaction
The line starting with '9' is the file footer - one per file.
I need logic to 1) read the file lines and 2) to be able to distinguish where a transaction starts and ends. Per line, I know Oracle has the instr and substr to distinguish different values in it.
Any suggestions would be welcome! Thanks for your time.
1TreasuryPart 201610031830MEMO
53336 Bank1Base0000001
650 3100000126 1-30-00010-00 000002126100000000000000021261USD20161003RAYMOND SOLIS jane.doe#gmail.com 205-888-9900 20161003020030000001 WEBENRAPC34560000000000 WEB
800000000010000000212610000000000000000001
53336 Bank1Base0000002
800000000000000000000000000000000000000002
53343 ToddMUD 0000001
800000000000000000000000000000000000000001
53343 ToddMUD 0000002
800000000000000000000000000000000000000002
53351 DenisTM 0000001
650 3100000128 7779026 000004000000000000000000080000USD20161003Denis Pellerin jack.doe#gmail.com 405-922-2116 20161003100421000001 WEBUNEAPC34560000000000 WEB
650 3100000128 7779026 000004000000000000000000080000USD20161003Denis Pellerin jack.doe#gmail.com 405-922-2116 20161003100421000002 WEBUNEAPC34560000000000 WEB
800000000020000000800000000000000000000001
53351 DenisTM 0000002
800000000000000000000000000000000000000002
9000006000000000003000000101261000000000000
I'm not quite sure what you're looking for. Posting code is always helpful so that we're not guessing. I'd think that you'd want something like this where there are separate procedures defined to parse each individual type of line.
declare
l_file utl_file.file_type;
l_line varchar2(4000);
l_in_transaction boolean := false;
begin
l_file := utl_file.fopen( <<parameters>> );
loop
utl_file.get_line(l_file, l_line);
if( substr(l_line,1,1) = '1' and l_in_transaction = false)
then
parse_file_header( l_line );
end if;
if( substr(l_line,1,1) = '5' and l_in_transaction = false )
then
parse_transaction_header( l_line );
l_in_transaction := true;
end if;
if( l_in_transaction = true)
then
parse_transaction_row( l_line );
end if;
if( substr(l_line,1,1) = '8' and l_in_transaction = true)
then
parse_transaction_trailer( l_line );
l_in_transaction := false;
end if;
if( substr(l_line,1,1) = '9' and l_in_transaction = false)
then
parse_file_trailer( l_line );
end if;
end loop;
exception
when no_data_found
then
utl_file.fclose( l_file );
end;

How to avoid violating the DRY principle when the boolean expression of a while loop is reassigned every loop pass?

Both
while MyFunction(1, 2, 3) > 0 do
begin
Temp := MyFunction(1, 2, 3);
ShowMessage(IntToStr(Temp));
end;
and
Temp := MyFunction(1, 2, 3);
while Temp > 0 do
begin
ShowMessage(IntToStr(Temp));
Temp := MyFunction(1, 2, 3);
end;
violate the DRY principle because there are two calls to MyFunction when only one is necessary.
Easy,
function dotemp(a,b,c:integer;var value : integer):boolean;
begin
value:a*b+c;
result:=value>0;
end;
begin
while dotemp(a,b,c,temp) do
begin
Operateontemp(temp);
end;
end;
Pascal has no lvalue assignments, but it DOES have var parameters.
I don't quite see the problem. Why don't you invert the logic and forget about Break:
repeat
Temp := MyFunction(1, 2, 3);
if Temp <= 0 then
begin
//code which uses Temp, for example:
ShowMessage(IntToStr(Temp));
end;
until Temp > 0;
That does exactly the same as you first sample, i.e. the while True do code snippet, but neither calls the function twice, nor does it need to use an assignment as an expression (not possible in Delphi), nor does it need to exit early with Break.
In C, you would do this with
do
{
...
} while (temp <= 0);
Note that every
if (condition) then
Break;
can be replaced by
if not (condition) then
// rest of original loop.
end;
for the rest of the loop.
There is the possibility to use an infinite loop and Break:
while True do
begin
Temp := MyFunction(1, 2, 3);
if Temp <= 0 then Break;
ShowMessage(IntToStr(Temp));
end;
Temp := 1;
while Temp > 0 do
begin
//...
end;
Or repeat-until

PLS 00103 error: Encountered the Symbol: IS, end-of -file

The below query when executed is giving errors: PLS 00103. Can you please help me find out the erros here. I have tried other combinations like ELSIF, but all give errors.
CREATE OR REPLACE
FUNCTION fnExpirationDateCondition
(
ExpirDateStr IN VARCHAR2,
OptionDateStr IN VARCHAR2 ) // Error 1 here
RETURN INTEGER ExpirDate DATE; // Error 2 here
OptionDate TIMESTAMP;
IS
BEGIN
ExpirDate :=TO_DATE(ExpirDateStr,'YYYY-MM-DD');
OptionDate :=TO_TIMESTAMP(OptionDateStr, 'YYYY-MM-DD HH24:MI:SS.FF');
IF(ExpirDate > OptionDate) THEN
RETURN 1;
ELSE
IF(ExpirDate < OptionDate) THEN // Error 3 here
RETURN -1;
ELSE
RETURN 0;
END IF;
END IF;
END;
Errors:
1.) Encountered the symbol "ExpirDate" when expecting one of the following:
2.) Encountered the Symbol "IS" when expecting one of the following:
3.) Encountered the symbol "end-of-file" when expecting one of the following:
I have also tried replacing ExpirDate :=TO_DATE(ExpirDateStr,'YYYY-MM-DD') with TO_DATE(ExpirDateStr,'YYYY-MM-DD') INTO ExpirDate. it doesn't seemed to work.
Any suggestions will be really helpful.
The issue is that you've got your variable declarations happening before the IS that marks the start of the function's declaration section.
Try this, instead:
create or replace function fnexpirationdatecondition
(expirdatestr in varchar2,
optiondatestr in varchar2)
return integer
is
expirdate date;
optiondate timestamp;
begin
expirdate := to_date(expirdatestr,'YYYY-MM-DD');
optiondate := to_timestamp(optiondatestr, 'YYYY-MM-DD HH24:MI:SS.FF');
if(expirdate > optiondate) then
return 1;
elsif(expirdate < optiondate) then
return -1;
else
return 0;
end if;
end fnexpirationdatecondition;
/
Or, alternatively, you could just have a single return statement (recommended), and just use a case statement to handle the if-elsif-else logic:
create or replace function fnexpirationdatecondition
(expirdatestr in varchar2,
optiondatestr in varchar2)
return integer
is
expirdate date;
optiondate timestamp;
begin
expirdate := to_date(expirdatestr,'YYYY-MM-DD');
optiondate := to_timestamp(optiondatestr, 'YYYY-MM-DD HH24:MI:SS.FF');
return case when (expirdate > optiondate) then 1
when (expirdate < optiondate) then -1
else 0
end;
end fnexpirationdatecondition;
/

Error: illegal Expression

I have this code:
tInteger :
begin
if(jinfo<maxinfo) then
begin
jinfo:=jinfo+1;
lokasi[jinfo]:=ScanStr;
WRITE(ResFile,jinfo:4);
end;
WRITE(ResFile,' ');
WRITE(ResFile,inum);
end;`
BEGIN
ScanStr:='';
REPEAT
ScanStr:=ScanStr+cc;
ReadChar;
UNTIL NOT (cc in ['a'..'z','A'..'Z','0'..'9','_']);
{Test KeyWord}
TampStr:=UpperCase(ScanStr);
i:=1; j:=JmlKeyWord; {index pencarian keyword dalam tabel}
REPEAT
k:=(i+j) DIV 2;
IF TampStr<=KeyWord[k] THEN j:=k-1;
IF TampStr>=KeyWord[k] THEN i:=k+1;
UNTIL i>j;
IF i-j>1 THEN
BEGIN k:=k+ORD(tKurungTutup); Token := KeyToken; END
ELSE
BEGIN Token := tIdentifier;
ScanStr:=COPY(ScanStr,1,10); END;
end;
But the script gives me this error:
error:illegal expression
error:ordinal expression expected
fatal: Syntax Error,: Expected but identifier SCANSTR found
I don't understand this error message. I'm sure this script was right.
The "script" (which isn't a script - it's code) is wrong.
You're inside a case statement:
tInteger :
begin
if(jinfo<maxinfo) then
begin
jinfo:=jinfo+1;
lokasi[jinfo]:=ScanStr;
WRITE(ResFile,jinfo:4);
end;
WRITE(ResFile,' ');
WRITE(ResFile,inum);
end;
The only thing valid after that is either another case branch, an optional else clause, or a final end.
case TheThing of
ThingA:
begin
// Code here
end;
ThingB:
begin
// Code here
end;
else
// Else code here
end;
You have another full begin..end block, which is invalid syntax.
BEGIN
ScanStr:='';
REPEAT
ScanStr:=ScanStr+cc;
ReadChar;
UNTIL NOT (cc in ['a'..'z','A'..'Z','0'..'9','_']);
{Test KeyWord}
TampStr:=UpperCase(ScanStr);
i:=1; j:=JmlKeyWord; {index pencarian keyword dalam tabel}
REPEAT
k:=(i+j) DIV 2;
IF TampStr<=KeyWord[k] THEN j:=k-1;
IF TampStr>=KeyWord[k] THEN i:=k+1;
UNTIL i>j;
IF i-j>1 THEN
BEGIN k:=k+ORD(tKurungTutup); Token := KeyToken; END
ELSE
BEGIN Token := tIdentifier;
ScanStr:=COPY(ScanStr,1,10); END;
end;