Illegal expression in a pascal program - pascal

My code below throws an exception. Why?
program Masquerade(input, output);
Begin
var amount, count, money : integer;
writeln ('Welcome to the Wonder True Masquerade Band');
writeln ('Would you like to proceed? Yes/No');
var choice : String;
readln (choice);
End.
Throws the error: fatal: syntax error ";" expected but "identifier AMOUNT" found
Where should the semi-colon go?

Put begin after var.
I haven't used Pascal for years and don't have any compiler to test it, but it should be like this:
program Masquerade(input, output);
var
amount, count, money : integer;
begin
writeln ('Welcome to the Wonder True Masquerade Band');
...

Related

how to validate input with "real" as the variable to numbers only?

im a coding newbie, currently using freepascal to learn. i want to make a simple temperature converter. im struggling at how to validate the input. because im using "real" as var, and i cant validate the input to numbers and negative sign only. i want to write "false input" and repeat to temperature input, if the input contains alphabet/alphanumeric. but when i input the temperature in alphabet/alphanumeric it will just exiting from program. how to do this correctly? is there any solution?
input validation with "real" as the variable
here's my current code
program Fahrenheit_to_Celsius;
uses crt;
function strtofloat (floatstring : string) : extended;
var F: string;
floatvalue: extended;
C: real;
exit: boolean;
decision: shortstring;
begin
clrscr;
textattr :=$3;
gotoxy (52,1);
writeln ('Fahrenheit to Celsius Converter');
repeat
write ('Input Fahrenheit: ');
readln (F);
begin
try
F := strtofloat ('10 E 2');
except
on exception : econverterror do
showmessage (exception.message);
end;
try
F := strtofloat ('$FF');
except
on exception : econverterror do
showmessage (exception.message);
end;
C := ((F-32)*(5/9));
writeln ('Temperature in Celsius: ', C:0:5);
begin
writeln;
gotoxy ((wherex () + 56), (wherey() - 0));
writeln ('Convert again or exit?');
gotoxy ((wherex () + 31), (wherey() - 0));
writeln ('Input e then press enter to exit or input anything else to convert again');
write ('Decision:');
readln (decision);
if (decision = 'e') then
exit := true
else
exit := false;
gotoxy ((wherex () + 0), (wherey() - 3));
delline;
gotoxy ((wherex () + 0), (wherey() - 0));
delline;
end;
until exit;
end.
It's been a long time since I practiced pascal but I will give you an idea, I think you cannot validate it this way because if you declare the input as real once the program recive an non valid input it exits, so what I suggest, is to declare the variable as string instead, then you create a function to validate it, finally if the function returns true you convert the string to float.
The function should loop through every character in the recieved string and returns false if
one character is not a number or not a .
the string contains more then one . ( create a variable and increment it every time you catch a character equal to . )
the first character is .
the last character is .

E2153 ';' not allowed before 'ELSE' [duplicate]

This question already has answers here:
Can I use an If statement inside a While statement?
(3 answers)
Closed last year.
When I compile my schedule:
procedure TForm1.FormCreate(Sender: TObject);
var
Speed: Double;
myStringList: TStringList;
b: array[0..512] of Char;
Memory: tMemoryStatus;
i : Integer;
begin
Speed := GetCPUSpeed;
myStringList := TStringList.Create;
TIdStack.IncUsage;
GetTempPath(511,b);
memory.dwLength := sizeof(memory);
GlobalMemoryStatus(memory);
i := Languages.IndexOf(SysLocale.DefaultLCID);
try
myStringList.Add('IP: ' + GStack.LocalAddress);
finally
TIdStack.DecUsage;
end;
If waveOutGetNumDevs > 0 then myStringList.Add('Scheda Audio: Presente');
else myStringList.Add('Scheda Audio: Assente');
myStringList.Add('');
Memo1.Lines.Assign(myStringList);
myStringList.Free;
end;
It gives me this error:
[DCC Error] Unit1.pas(198): E2153 ';' not allowed before 'ELSE'
on this line:
else myStringList.Add('Scheda Audio: Assente');
This is covered in Delphi's documentation:
Declarations and Statements (Delphi): If Statements
Notice that a semicolon between the then clause and the word else is never used. You can place a semicolon after an entire if statement to separate it from the next statement in its block, but the then and else clauses require nothing more than a space or carriage return between them. Placing a semicolon immediately before else (in an if statement) is a common programming error.
Also related:
Declarations and Statements (Delphi): Compound_Statements
A compound statement is a sequence of other (simple or structured) statements to be executed in the order in which they are written. The compound statement is bracketed by the reserved words begin and end, and its constituent statements are separated by semicolons. For example:
begin
Z := X;
X := Y;
X := Y;
end;
The last semicolon before end is optional. So this could have been written as:
begin
Z := X;
X := Y;
Y := Z
end;
A common misconception for Delphi is that semicolon is a statement terminator. In some languages, like C/C++, that is true. But in Delphi, that is not true. Semicolon is a statement separator instead. There is a subtle difference. You have to place a semicolon between consecutive statements, but you DO NOT need to place a semicolon at the end of a statement when it is the last statement in an enclosing block.
This is even mentioned in the documentation for the error message in question:
E2153 ';' not allowed before 'ELSE' (Delphi)
You have placed a ';' directly before an ELSE in an IF-ELSE statement. The reason for this is that the ';' is treated as a statement separator, not a statement terminator - IF-ELSE is one statement, a ';' cannot appear in the middle (unless you use compound statements).
...
The Delphi language does not allow a ';' to be placed directly before an ELSE statement. In the code above, an error will be flagged because of this fact.
...
There are two easy solutions to this problem. The first is to remove the offending ';'. The second is to create compound statements for each part of the IF-ELSE...
On a side note: you need to protect your TStringList with a try..finally block. And the call to TIdStack.IncUsage() should be moved directly above the try of the finally that calls TIdStack.DecUsage().
Try something more like this:
procedure TForm1.FormCreate(Sender: TObject);
var
Speed: Double;
myStringList: TStringList;
b: array[0..MAX_PATH] of Char;
Memory: tMemoryStatus;
i : Integer;
begin
myStringList := TStringList.Create;
try
Speed := GetCPUSpeed;
// add Speed to myStringList as needed...
GetTempPath(MAX_PATH, b);
// add b to myStringList as needed...
memory.dwLength := sizeof(memory);
GlobalMemoryStatus(memory);
// add memory info to myStringList as needed...
i := Languages.IndexOf(SysLocale.DefaultLCID);
// add language info to myStringList as needed...
TIdStack.IncUsage;
try
myStringList.Add('IP: ' + GStack.LocalAddress);
finally
TIdStack.DecUsage;
end;
if waveOutGetNumDevs > 0 then
myStringList.Add('Scheda Audio: Presente')
else
myStringList.Add('Scheda Audio: Assente');
myStringList.Add('');
Memo1.Lines.Assign(myStringList);
finally
myStringList.Free;
end;
end;

Reading A Variable As Both A Number And String of Words

I am trying to get Dep_Code to read as a string after choosing the options given (1, 2 or 3). I first had it set to integer in my first program (I think) and was able to get it to read out the options given as words (Accounts ACC or the others). However, it was accidentally deleted. I've tried various ways to get it even setting Dep_Code as a string but its not working and I keep getting a variety of errors. Btw, I'm not familiar with programming so I'm aware that the following code is quite incorrect... but I hope you all can help. Thank you!
REPEAT
writeln ('Please enter the Department Code:- ');
writeln;
writeln ('1. Accounts (ACC)');
writeln ('2. Human Resources (HR)');
writeln ('3. Operations (OP)');
writeln;
readln (Dep_Code);
IF Dep_Code = 1 THEN
Dep_Code := ('Accounts (ACC)')
ELSE IF Dep_Code = 2 THEN
Dep_Code := ('Human Resources(HR)')
ELSE IF Dep_Code = 3 THEN
Dep_Code := ('Operations (OP)');
UNTIL ((Dep_Code >= 1) AND (Dep_Code <= 3));
This is impossible. Pascal is a strictly typed language, and something cannot be an Integer and a string at the same time, and variables cannot change type either:
IF Dep_Code = 1 THEN
Dep_Code := ('Accounts (ACC)')
But you don't need a string at all. Keep it an integer. The functions that handle the various depts can write or define such strings, if necessary. Your logic for the menu does not need a string variable.
Do something like:
procedure HandleAccounts(var Error: Boolean);
begin
...
end;
// Skipped the other functions to keep this answer short ...
var
Dep_Code: Integer;
AllFine: Boolean;
// Skip the rest of the necessary code ...
repeat
// Skipped the Writelns to keep this answer short ...
Readln(Dep_Code);
Error := False;
case Dep_Code of
1: HandleAccounts(Error);
2: HandleHumanResources(Error);
3: HandleOperations(Error);
else
Error := True;
end;
until not Error;
Above, I skipped some of the code. You can fill in the blanks, I guess.

Command Line Args in pascal

I am new in pascal I have a program which gives result ....
I need to pass command line input in in given variable ip1 and ip2.
Its can be achieved by ParamStr[1] but it doesn't work.
program main;
var
output : integer;
var
ip1 : integer;
var
ip2 : integer;
function add(input1,input2:integer) : integer;
var
result: integer;
begin
if (input1 > input2) then
result := input1
else
result := input2;
add := result;
end;
begin
ip1 := 2533;**{ command line input}**
ip2 := 555;**{ command line input}**
output := add(ip1,ip2);
writeln( ' output : ', output );
end.K
As the other answer says, you use ParamCount and ParamStr to access command line parameters.
ParamCount returns the number of parameters passed on the command line, so you should check it first to see if you've received enough information.
ParamStr allows you to access each of the parameters passed. ParamStr(0) always gives you the full name of the executing program (including the path). Additional parameters are retrieved using the ordinal order in which they were passed, with ParamStr(1) being the first, and ParamStr(ParamCount) being the last. Each value received using ParamStr is a string value, and therefore has to be converted into the appropriate type before you can use it.
Here's a working example (pretty trivial, and all error checking omitted - you should, for instance, protect the code using StrToInt to handle errors if something is provided that won't convert to an integer).
program TestParams;
uses
SysUtils;
var
Input1, Input2, Output: Integer;
begin
if ParamCount > 1 then
begin
Input1 := StrToInt(ParamStr(1));
Input2 := StrToInt(ParamStr(2));
Output := Input1 + Input2;
WriteLn(Format('%d + %d = %d', [Input1, Input2, Output]));
end
else
begin
WriteLn('Syntax: ', ParamStr(0)); { Just to demonstrate ParamStr(0) }
WriteLn('There are two parameters required. You provided ', ParamCount);
end;
WriteLn('Press ENTER to exit...');
ReadLn;
end.
Calling it without parameters (or only one) displays the following:
C:\Temp>TestParams
Syntax: C:\Temp\TestParams.exe
There are two parameters required. You provided 0
Press ENTER to exit...
C:\Temp>TestParams 2
Syntax: C:\Temp>TestParams.exe 2
There are two parameters required. You provided 1
Press ENTER to exit...
Calling it with two parameters displays
C:\Temp\TestParams 2 2
2 + 2 = 4
Press ENTER to exit...
You need to understand the difference between a string and an integer.
To convert betwwen an integer such as 123 and the string of characters 1 2 3 you need to use a function. strtoint is one such function, converting a string to an integer. inttostr is another, converting from an integer to a string.
The command-line data is supplied via paramstr(n) as a string.
intvar := strtoint(paramstr(n));
assigns the value of the string to the integer variable intvar.
Whereas writeln has facilities to convert an integer argument to a formatted string, the way you have used it is attempting to output a string, so you need to convert the integer output to a string.
writeln(' output : ', inttostr(output) );
should do that very nicely.
var
x : string;
pcnt : integer;
begin
writeln('Parameter count=',inttostr(paramcount));
for pcnt := 1 to paramcount do
writeln('Parameter ',pcnt, ' of ',paramcount,' = ',paramstr(pcnt));
readln(x);
end.
should display the parameter list.
Indeed it is the case that the writeln procedure will recognise the variable type and take steps to format the value appropriately as a string, as has arrogantly been pointed out.
The issue to me is the difference between a string and an integer. paramstr returns a string which must be converted to an integer. After more than forty years' experience in Pascal, it's my opinion that it's better for a beginner to go through the exercise of converting each way and then use the conversion facility inbuilt in writeln.
First walk, then run. You first need to understand the steps in the procedure. Then you can start using the shortcuts - once you've mastered the basics.

how to get a variable out of a procedure in the right way in PASCAL?

I'm following an internet course on the basics of programming. After making a diagram I convert it to code, right now this is PASCAL language.
I'm having a problem with procedures and can't find an answer, nor in the course, nor with some google-ing.
I want to get a variavble back form a procedure. Right now iIhave a working piece of code but I think this is not the good way of working. Here's an extract of the code:
program WELKEWAGEN;
// declare your variables here
var T, N, KM, vari, prijsDW, prijsBW, jrenGEBR, taksDW, taksBW, prijsB, verbrBW, prijsD, verbrDW : real;
procedure OPHALEN(para : string);
begin
repeat
writeln('geef de ', para , ' op');
readln(vari);
until (vari > 0);
end;
begin
//this is the main program but there is more code ofcourse
OPHALEN('prijs benzinewagen');
prijsBW := vari;
//...
end.
Now the internet course says I should program it like this:
begin
//...
prijsBW := OPHALEN('prijs benzinewagen');
//...
end.
But this is not working.
I get following errors:
WELKEWAGEN.pas(24,14) Error: Incompatible types: got "untyped" expected "Real"
WELKEWAGEN.pas(50) Fatal: There were 1 errors compiling module, stopping
pas(24,14) is this line: prijsBW := OPHALEN('prijs benzinewagen');
Procedures don't return values, so the syntax
prijsBW := OPHALEN('prijs benzinewagen');
is invalid.
If you want to return a value, you need to define a function instead:
function OPHALEN(para : string): Real;
var
Res: Real;
begin
Res := 0;
repeat
writeln('geef de ', para , ' op');
readln(Res);
until (Res > 0);
OPHALEN := Res;
end;
Note that the (bad) global variables you're using mean you don't have to return anything at all, because a procedure can access and change that global variable directly (but you have no way of knowing when the procedure is finished):
procedure OPHALEN(para : string);
begin
vari := 0;
repeat
writeln('geef de ', para , ' op');
readln(vari);
until (vari > 0);
end;
Modern Pascal dialects (such as Delphi and FreePascal) allow a cleaner syntax for the return value of functions by using an automatically declared function result variable of the proper type for you, named Result (because that's what it is - the result of the function):
function OPHALEN(para : string): Real;
begin
Result := 0;
repeat
writeln('geef de ', para , ' op');
readln(Result);
until (Result > 0);
end;
If you need to return multiple values, you can use var parameters, which allow them to be changed inside the function.
procedure OPHALEN(para: string; var RetVal: Real);
begin
RetVal := 0;
repeat
writeln('geef de ', para , ' op');
readln(RetVal);
until (RetVal > 0);
end;
Your original code (and the examples I've provided above) all fail to allow the user to cancel, BTW. There should be some way to exit the loop for the user; otherwise, your code just endlessly loops, writing para to the screen and then waiting for input. This has a tendency to annoy users.

Resources