How to display time in Real-time in Virtual Pascal - time

I've been making a stock-keeping program for my school (In Virtual Pascal) and as part of that, I want to be able to display today's date along with the current time at the main menu of the program. Now, I've been able to display the correct date as that was pretty simple.
But when I use this code for displaying Time, it only displays the time at which the program is compiled, and does not refresh to display the current time.
Procedure getTheTime;
VAR
Hour, Minute, Second, Sec100 : WORD;
BEGIN
GetTime( Hour, Minute, Second, Sec100 );
TEXTCOLOR(lightgreen);
whereY;
whereX;
WRITE;WRITE(' ');
WRITE( Hour, ':', Minute, ':', Second, '.', Sec100);
END;
Basically, it displays this: 19:8:41.75
And I want the time to refresh as time goes by.
Any help would be appreciated.
The procedure where I call the getTheTime procedure.
Procedure mainMenu;
BEGIN
REPEAT
CLRSCR;
getTheDate;
getTheTime;
TEXTCOLOR(15);
GOTOXY(18,2);
WRITELN('Welcome To RAK Academy''s School Shop');
TEXTCOLOR(11);
GOTOXY(18,3);
WRITELN('------------------------------------');
WRITELN;
WRITE('A ':25);
TEXTCOLOR(15);
WRITELN(': Customers');
WRITELN;
TEXTCOLOR(11);
WRITE('B ':25);
TEXTCOLOR(15);
WRITELN(': Products');
WRITELN;
TEXTCOLOR(11);
WRITE('C ':25);
TEXTCOLOR(15);
WRITELN(': Orders');
WRITELN;
TEXTCOLOR(11);
WRITE('X ':25);
TEXTCOLOR(15);
WRITELN(': Exit');
WRITELN;
GOTOXY(0,3);
WRITE('Enter Choice: ':23);
MenuChoice:=UPCASE(READKEY);
sndPlaySound('F:\School\IB 1\HL subjects\Computer Science\Pascal programs\InternalAssessment\sound files\beep.wav', snd_Async or snd_NoDefault );
TEXTCOLOR(11);;
WRITELN(MenuChoice);
TEXTCOLOR(15);
DELAY(200);
CASE MenuChoice OF
'A' : CustomersMenu;
'B' : ProductsMenu;
'C' : OrdersMenu;
'X' : BEGIN
sndPlaySound('F:\School\IB 1\HL subjects\Computer Science\Pascal programs\InternalAssessment\sound files\end.wav', snd_Async or snd_NoDefault );
WRITELN;
WRITELN('Program Is Shutting Down');
GOTOXY(25,15);
DELAY(750);
WRITE('.');
DELAY(750);
WRITE('.');
DELAY(750);
WRITE('.');
DELAY(750);
END
ELSE
BEGIN
WRITELN;
TEXTCOLOR(12);
WRITELN('ERROR - Only Enter A-B Or X To Exit. Please Try Again.');
TEXTCOLOR(11);
READKEY;
END;
END;
UNTIL menuChoice='X';
END;

It is not the time at which the program is compiled, but the time at which the program is run.
The code between BEGIN-END runs once and then updates the time.
If you want the time to update you need to add a timer that updates the time when the OnTimer event triggers.

From memory, to give you an idea how to do this:
var updatecounter : integer;
mustexit : Boolean;
updatecounter:=10; mustexit:=false;
repeat //eventloop start.
if keypressed then
begin
c:=readkey;
if c=#0 then
c2:=readkey; // C=#0 is functionkey, read second value
mustexit:=processkey(c,c2); // process whatever key is pressed
end
else
begin
sleep(10); // windows/winprocs unit? Don't know VP that well.
// pauses 10ms
dec(updatecounter);
if updatecounter=0 then // every 10*10ms update time
begin
updatetime; // update the time.
updatecounter:=10;
end;
end;
until mustexit;
You can implement the various procedures and play with constants to get the responsivenes you want.

Related

Program in pascal [duplicate]

This question already has answers here:
What is that the Error of Illegal assignment and how to correct it?
(2 answers)
Closed last month.
Just started to learn the Pascal programming language, I wrote an assignment that was given at the university, here is my assignment:
Build a program that will perform the following actions:
retrieve data of N elements (brand, name, atomic weight, density)
find the average density value
finding the three elements with the lowest atomic mass
writing the inputs and outputs to the text file "elements.txt"
wrote code for it, in theory everything should work, but it gives out some strange errors, if I have standard errors, I apologize for them.
program MINERALY_;
uses Crt;
const NMAX=200;
type MINERAL=record
NAZOV:string;
HUST:real;
ATOM:real;
ZNACKA:real;
end;
MINERALY=array[1..NMAX] of MINERAL;
var N,i,C,D:integer;
V:real;
MI:MINERALY;
S:string;
SUB:text;
PTVRD,CTVRD:real;
MINATOM:real;
begin
ClrScr;
Writeln('Program pre nacitanie mineralov a vypocet hodnot ich jednotlivych
vlastnosti.');
Writeln('===============================================================================');
{Vynulovanie hodnot}
CTVRD:=0;
PTVRD:=0;
MINATOM:=0;
{Nacitanie poctu mineralov}
Writeln;
Write('Zadajte pocet nacitavanych mineralov (Maximalne 200): ');
repeat
Readln(S);
Val(S,D,C);
if (C<>0) or (D<=0) or (D>200) then
begin
Writeln;
Writeln('Zadali ste nespravny pocet, alebo ste zadali nespravne znaky !');
Writeln('Hodnota moze byt od 1-200');
Write('Zadajte pocet mineralov este raz: ');
end;
N:=D;
until(N>0) and (N<=200) and (C=0);
{nacitavanie udajov, zistovanie max. a min. hodnot atd.}
for i:=1 to N do
begin
Writeln;
Write('Zadajte Znacku: ');
Readln(MI[i].ZNACKA);
Writeln;
Write('Zadajte nazov: ');
Readln(MI[i].NAZOV);
Write('Zadajte hustotu (musi byt vacsia ako 0): ');
repeat
Readln(S);
Val(S,V,C);
if (C<>0) or (V<0) then
begin
Writeln;
Writeln('Zadali ste nespravnu hodnotu, alebo ste zadali nespravne znaky !');
Write('Zadajte hustotu este raz (musi byt vacsia ako 0): ');
end;
until (V>0) and (C=0);
MI[i].HUST:=V;
CTVRD:=CTVRD+MI[i].HUST;
Write('Zadajte atómovou hmotnosťou (musi byt vacsia ako 0): ');
repeat
Readln(S);
Val(S,V,C);
if (C<>0) or (V<0) then
begin
Writeln;
Writeln('Zadali ste nespravnu hodnotu, alebo ste zadali nespravne znaky !');
Write('Zadajte atómovou hmotnosťou este raz (musi byt vascia ako 0): ');
end;
until (V>0) and (C=0);
MI[i].ATOM:=V;
if (i=1) then MINATOM:=MI[i].ATOM;
if (MI[i].ATOM<MINATOM) then MINATOM:=MI[i].ATOM;
PTVRD:=CTVRD/N;
Writeln;
Writeln('Vypocitane hodnoty: ');
Writeln('===================================');
Writeln;
Writeln('Priemerna tvrdost mineralov: ',PTVRD:2:2);
Writeln('Najnizsia hustota: ',MINATOM:2:2);
Assign(SUB,'mineral.txt');
Rewrite(SUB);
Writeln(SUB,'Nacitane mineraly: ');
Writeln(SUB,'===================================');
Writeln(SUB,'');
for i:=1 to N do
begin
Writeln(SUB,i,'. mineral: ');
Writeln(SUB,'Nazov: ',MI[i].NAZOV);
Writeln(SUB,'Znacka: ',MI[i].ZNACKA);
Writeln(SUB,'Tvrdost: ',MI[i].HUST:2:2);
Writeln(SUB,'Hustota: ',MI[i].ATOM:2:2);
Writeln(SUB,'');
end;
Writeln(SUB,'===================================');
Writeln(SUB,'Vypocitane hodnoty: ');
Writeln(SUB,'===================================');
Writeln(SUB,'');
Writeln(SUB,'Priemerna tvrdost mineralov: ',PTVRD:2:2);
Writeln(SUB,'Najnizsia hustota: ',MINATOM:2:2);
Close(SUB);
Writeln;
Writeln;
Writeln('Pre ukoncenie programu stlacte ENTER !');
Readln;
end.
Here are the errors this code gives me:
Compiling main.pas
main.pas(109,14) Error: Illegal assignment to for-loop variable "i"
main.pas(132,4) Fatal: Syntax error, ";" expected but "." found
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Error: Illegal assignment to for-loop variable "i"
is when you are trying to change the value of i while the loop is still working.
since you didn't end; the loop you canno't change the value of i you can use another variable, j for example, unless your first for-loop is over and you forgot the end; key

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.

Pascal comparison error

I have a problem with my very simple Pascal code. (I just started to learn Pascal.)
So it's about an age comparison code then rest can be seen through the code.
program Test;
uses crt;
var
age : real;
Begin
writeln('Enter your age: ');
readln(age);
if age>18 then
if age<100 then
Begin
clrscr;
textcolor(lightgreen);
writeln('Access Granted');
end
else
if age<18 then
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to young');
end
else
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to old');
end;
readln;
end.
When I enter a value below 18 as the age, I expect the program to respond:
ACCESS DENIED
Reason:You are way to young
but I don't get any output. Why?
Sometimes text indentation helps you to see the issue. Here's your code with indentation added:
program Test;
uses crt;
var
age : real;
Begin
writeln('Enter your age: ');
readln(age);
if age>18 then
if age<100 then
Begin
clrscr;
textcolor(lightgreen);
writeln('Access Granted');
end
else
if age<18 then
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to young');
end
else
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to old');
end;
readln;
end.
And to make the implemented logic more obvious, I will now represent the nested ifs without the code that they execute:
if age>18 then
if age<100 then
... // Access Granted
else
if age<18 then
... // You are way too young
else
... // You are way too old
;
It is easy to see now that the branch marked as You are way too young is never reached. It is supposed to be executed when age is less than 18, but that if statement is nested into another if which will call it only when age is greater than 18. So, age should first qualify as greater than 18, then less than 18 in order for that branch to execute – you can see now why you do not get the expected result!
The intended logic could possibly be implemented this way:
if age>18 then
if age<100 then
... // Access Granted
else // i.e. "if age >= 100"
... // You are way too old
else // now this "else" belongs to the first "if"
... // You are way too young
;
I believe you should be able to fill in the missing code blocks correctly.
Just one last note: you might want to change age>18 to age>=18, so that 18 proper does not qualify as "too young".

Why 'form close' event is not happening when a huge for loop is runnig in Delphi?

I am trying out following code. However, if I click on form's close button while this code is running, nothing happens. How can I correct this? I need to close the form even when this loop is executing.
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 9999999 do
begin
Memo1.Lines.Add('hi');
Application.ProcessMessages;
end;
end;
Have a look at what's going on inside Application.ProcessMessages.
When you close the main form, windows sends a WM_QUIT message to the program. The relevant part of TApplication.ProcessMessages looks like this:
if Msg.Message <> WM_QUIT then
begin
//skipped
end
else
begin
{$IF DEFINED(CLR)}
if Assigned(FOnShutDown) then FOnShutDown(self);
DoneApplication;
{$IFEND}
FTerminate := True;
end;
I assume this is not a CLR program, so the only thing that happens at this point is setting FTerminate := True on Application. This is reflected in the Application.Terminated property.
When the application shuts down, one of the things it does in order to shut down safely is wait for all threads to finish. This code happens to be running in the main thread, but the principle would be the same in any thread: If you're doing a long-running task that might have to finish early, you have to explicitly check for early termination.
Knowing this, it's easy to figure out how to fix your code:
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 9999999 do
begin
Memo1.Lines.Add('hi');
Application.ProcessMessages;
if Application.Terminated then
Break;
end;
end;
Also, beware of using Application.ProcessMessages in the first place, as it will process all messages for the application. For a simple idea of what might go wrong, try adding IntToStr(i) instead of 'hi' to Memo1.Lines, knock a couple of orders of magnitude off the counter, and then click the button two or three times in rapid succession and watch the output...
Check for Apllication Terminated:
for i := 0 to 9999999 do
begin
Memo1.Lines.Add('hi');
Application.ProcessMessages;
if Application.Terminated then Exit;
end;
You need to run any tight loop in a thread. This will solve the problem.
BUT if you want to keep the code as it is, Application.ProcessMessages will make your loop terribly slow. So you need to run Application.ProcessMessages not so often:
Counter:= 0;
for i := 0 to 9999999 do
begin
DoSomeStuff;
{ Prevent freeze }
inc(Counter);
if counter > 10000 then
begin
Counter:= 0;
Application.ProcessMessages;
if Application.Terminated then Exit;
end;
end;

Pascal compiles and closes straight away despite readln;

program words;
uses crt;
type
T2DArray = array[1..100, 1..100] of string;
var
ch:char;
x,y:integer;
MapArray: T2DArray;
begin
x:=0;
y:=0;
repeat
MapArray[10, 10] := 'you are at a tree';
writeln(MapArray[x,y]);
write('current positon is ');
write(x);write(',');write(y);
ch:=ReadKey;
case ch of
#0 : begin
ch:=ReadKey; {Read ScanCode}
case ch of
'w' : y:=y+1;
'a' : x:=x-1;
's' : y:=y-1;
'd' : x:=x+1;
end;
end;
#27 : WriteLn('ESC');
end;
until ch=#27;
readln;
end.
i have this simple piece of code that will allow me to assign things to XY coordinates of a 2d array. the code compiles and closes straight away despite the readln; at the bottom.
All the best Arran.
Always enable range-checking {$R+} during development. You have a 1-based array but your x and y values are zero the first time you read from it.

Resources