Pascal and NSDs? - pascal

I have to make an assignment (in Dutch) for Programming Logic. We have to use Structorizer and than convert/export it into Pascal code (yes, I know, prehistoric! But they say it's like learning "latin", if you learn it you have like a base.)
Now, I already had to figure out several bugs while converting my var's. But the main question I'd like to ask is this:
How come if I type in STOP (where in code it says : Read naam) the while loop actually continues and prints out the next line : write naam ' moet', lidgeld:0:2, ' euro lidgeld betalen.'
Instead of just jump out of the while loop because of the 'STOP' and print out the bottom lines?
In other code, it is fairly easy to check the {} and step by step monitoring it. But here with this code I'm totally lost. I used already an IF statement after read naam to make 'stop' work, but then it still prints out again write naam ' moet', lidgeld:0:2, ' euro lidgeld betalen.'
Pascal Code:
{ Generated by Structorizer 3.26-05 }
program Vereniging;
var
{ TODO: check and accomplish variable declarations }
leeftijd: integer ; kinderen : integer ; leden : integer ; inkomen : real ; totaal : real ; lidgeld : real ; gemiddelde : real ; naam : string;
begin
lidgeld := 0;
leden := 0;
totaal := 0;
gemiddelde := 0;
writeln('Geef naam en voornaam in: ');
readln(naam);
writeln;
writeln('Geef de leeftijd in: ');
readln(leeftijd);
writeln;
writeln('Geef het aantal kinderen ten laste in: ');
readln(kinderen);
writeln;
writeln('Geef het jaarinkomen in: ');
readln(inkomen);
while (naam <> 'stop') or (naam <> 'STOP') do
begin
lidgeld := 10;
if (leeftijd > 50) then
begin
lidgeld := lidgeld - 2;
leden := leden + 1;
totaal := totaal + lidgeld;
gemiddelde := totaal / leden;
end;
if (kinderen > 0) and (kinderen < 6) then
begin
lidgeld := lidgeld - kinderen;
leden := leden + 1;
totaal := totaal + lidgeld;
gemiddelde := totaal / leden;
end
else
begin
lidgeld := lidgeld - 5;
leden := leden + 1;
totaal := totaal + lidgeld;
gemiddelde := totaal / leden;
end;
if (inkomen < 12500) then
begin
lidgeld := lidgeld - 2.5;
leden := leden + 1;
totaal := totaal + lidgeld;
gemiddelde := totaal / leden;
end;
if (leeftijd > 50) and (kinderen >= 5) and (inkomen < 12500) then
begin
lidgeld := lidgeld - 8.5;
leden := leden + 1;
totaal := totaal + lidgeld;
gemiddelde := totaal / leden;
end;
writeln;
writeln(naam, ' moet ', lidgeld:0:2, ' euro lidgeld betalen.');
writeln;
writeln('Geef naam en voornaam in: ');
readln(naam);
writeln;
writeln('Geef de leeftijd in: ');
readln(leeftijd);
writeln;
writeln('Geef het aantal kinderen ten laste in: ');
readln(kinderen);
writeln;
writeln('Geef het jaarinkomen in: ');
readln(inkomen);
writeln;
end;
writeln;
writeln('Het totaal aantal leden : ', leden);
writeln;
writeln('Het totaal aantal lidgeld : ', totaal:0:2, ' euro.');
writeln;
writeln('Het gemiddelde : ', gemiddelde:0:2, ' euro.');
writeln;
writeln('Druk op <ENTER> om het programma af te sluiten');
readln();
end.
NSD picture

The condition on your WHILE...DO loop is wrong - regardless of what you type in, at least one of those two conditions will be true, and the loop will execute (because A OR B is TRUE if either A is TRUE or B is TRUE):
If you type in stop, then the condition (naam <> 'STOP') will be true, and the loop will execute.
If you type in STOP, then the condition (naam <> 'stop') will be true, and the loop will executed.
What you want to do is compare with 'STOP' in a case-insensitive manner, so that regardless of what you type - STOP, stop, Stop, StOp, etc. - the test will be TRUE. Or, alternatively, if you type anything other than some variation on the word stop, the test will be FALSE.

I know, prehistoric...
Even if prehistoric, many programming languages still have to learn something from pascal. And many programmers too.
If you really want that, after typing "STOP" in reply to the program's prompt "Geef naam en voornaam in: ", the program stops to ask questions, then you have to add the following line:
if (naam='stop') or (naam='STOP') then break;
exactly after this line from you program:
readln(naam);
Otherwise, as said in the previous answer, you must change the cycle prologue like this:
while (naam<>'stop') AND (naam<>'STOP') do begin...
but this will not prevent the program to continue to ask for "Geef de leeftijd", "Geef het aantal kinderen", "Geef het jaarinkomen in".
Is it clear? The main bug depicted in your question is your understanding of programming, not the pascal language.

Related

Got an issue with the graph unit in my Pascal program

I'm new to this forum. I'm here to ask you guys your help.
I have an assignment where I have to code a game in Pascal, which is a brick breaker in my case. Though I stumbled upon a problem that I don't quite manage to solve and it's probably related to the graph unit.
It's supposed to display a wall of bricks of various colours in the graphic interface (generated by the graph unit) but nothing appears. The window stays all black. And I know it's not due to having wrtiten a wrong path to the BGI graphic file in the initialisation of the graph unit as I used the same initalisation in an other program where I managed to draw things in the graphic interface.
Finally, my game is in french, so just a few words that you'll need to know: Niveau means level, Jouer means play and Règles means rules. You'll see by choosing a level in the menu that the application will compile but nothing will be displayed in the graph window.
I'd be very glad if you help me out (please).
Here is the main program:
program principal;
uses
Crt, Keyboard, sysutils, jeu, graph;
var
t : TKeyEvent;
c : char;
x, y, mur : Integer;
F , F2 : Text;
V: r;
GraphicsDriver, GraphicsMode, ErrCode : Smallint;
s : String;
begin
x := 62;
y := 12;
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, y);
writeln('Niveaux');
GoToXY(55, y + 2);
writeln('Regles');
GoToXY(x, y);
InitKeyBoard();
repeat //boucle pour déplacer le curseur de haut en bas dans la première fenêtre du menu
t := GetKeyEvent();
t := TranslateKeyEvent(t);
c := GetKeyEventChar(t);
if c = 's' then
begin
GoToXY(x - 1, y + 2);
x := 61;
end;
if c = 'z' then
begin
GoToXY(x, y);
x := 62;
end;
until c = 'm';
ClrScr();
case x of
62: begin
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, y);
writeln('Niveau 1');
GoToXY(55, y + 2);
writeln('Niveau 2');
GoToXY(55, y + 4);
writeln('Niveau 3');
GoToXY(63, 14);
end;
61: begin //affichage des règles
DoneKeyBoard();
assign(F2, 'Regles.txt');
reset(F2);
while not eof(F2) do
begin
readln(F2, S);
writeln(S);
end;
RetourArriereMenu(X, Y, mur, T, C, f, f2, V, GraphicsDriver, GraphicsMode, ErrCode, s);
end;
end;
x := 63;
repeat //boucle pour déplacer le curseur de ahut en bas dans la fenêtre de la séléction des niveau
t := GetKeyEvent();
t := TranslateKeyEvent(t);
c := GetKeyEventChar(t);
if c = 's' then
begin
if y < 16 then
begin
GoToXY(x, y + 2);
y := y + 2;
end;
end;
if c = 'z' then
begin
if y > 12 then
begin
GoToXY(x, y - 2);
y := y - 2;
end;
end;
until (c = 'm') or (c = 'w');
if c = 'm' then
begin
DoneKeyboard();
case y of //pour chaque niveau séléctionné, une valeur est assignée à mur (ça serivira au déroulement des procédures ci-dessous)
12: mur := 1;
14: mur := 2;
16: mur := 3;
end;
ClrScr();
GraphicsDriver := Detect; //initialisation de l'unité graph
InitGraph(GraphicsDriver, GraphicsMode,'C:\PP\BGI');
ErrCode := GraphResult;
If GraphResult <> grOK Then //affichage d'un message d'erreur si ça n'arrive pas à trouver le fichier graphique dans le répertoire indiqué ci-dessus
Begin
Writeln('Une erreur graphique s est produite: ', GraphErrorMsg(ErrCode));
Writeln('Le fichier graphique (.BGI) n a pas ete trouve, donc veuillez changer le chemin dans InitGraph');
Readln;
Halt(1);
End
Else
begin
remplissageDoc(mur,F);
MiseEnPlaceMur(mur,F,V);
end;
readln;
closegraph;
end;
if c= 'w' then
RetourArriereMenu(X,Y,mur,T,C,f,f2,V, GraphicsDriver, GraphicsMode, ErrCode,s);
end.
Here is the unit in which is stored all the procedures needed to run the main program
unit jeu;
interface
uses
sysutils, Crt, Keyboard, graph;
const
MAXtabX = 100;
MAXtabY = 50;
Type r = array [1..MAXtabX,1..MAXtabY] of Integer;
procedure remplissageDoc(m: Integer; var f: Text); //remplir les documents aléatoirement à chaque lancement de niveau. m correspond au niveau que le joueur a choisi
procedure MiseEnPlaceMur(m: Integer; var f: Text; res: r); //affichage du mur avec pour chaque bloque des vies (soit 1 soit 2 soit 3)
procedure RetourArriereMenu(X,Y: Integer; var m: Integer; var T: TkeyEvent; var C: char; var f,f2: Text; var res: r; var GraphicsDriver, GraphicsMode, ErrCode : Smallint; s: String); //pour retourner en arrière dans n'importe quel endroit du menu
procedure DessinerBrique(i,j: Integer; res: r; x1,y1,x2,y2: Integer); //dessine une brique
implementation
procedure DessinerBrique(i, j : Integer; res : r; x1, y1, x2, y2 : Integer);
begin
writeln(x1, ',', y1, ' ', x2, ',', y2, '-', res[i][j]);
setcolor(15);
rectangle(x1, y1, x2, y2);
if res[i][j]= 1 then
begin
setfillstyle(1,1);
floodfill((x1+x2)div 2,(y1+y2)div 2,15);
end;
if res[i][j] = 2 then
begin
setfillstyle(1, 2);
floodfill((x1 + x2) div 2, (y1 + y2) div 2, 15);
end;
if res[i][j]= 3 then
begin
setfillstyle(1,4);
floodfill((x1 + x2) div 2, (y1 + y2) div 2, 15);
end;
end;
procedure remplissageDoc(m : Integer; var f : Text);
var
a : Integer;
begin
if m = 1 then
begin
assign(f, 'Niveau 1.txt');
rewrite(f);
for a := 1 to 30 do //30 chiffres vont êtres saisis dans le fichier
begin
write(f, 1);
writeln;
end;
close(f);
end;
if m = 2 then
begin
assign(f, 'Niveau 2.txt');
rewrite(f);
randomize();
for a := 1 to 30 do
begin
write(f, random(2) + 1);
writeln;
end;
close(f);
end;
if m = 3 then
begin
assign(f, 'Niveau 3.txt');
rewrite(f);
randomize();
for a := 1 to 30 do
begin
write(f, random(3) + 1);
writeln;
end;
close(f);
end;
end;
procedure MiseEnPlaceMur(m : Integer; var f : Text; res : r);
var
i, j : Integer;
x1, y1, x2, y2 : Integer;
s : String;
begin
i := 1;
x1 := 200;
x2 := 245;
y1 := 0;
y2 := 25;
reset(f);
read(f, s);
while not eof do
begin
for j:= 1 to length(s) do
begin
res[i][j] := StrToInt(s[j]); //remplissage du tableau des vies
DessinerBrique(i, j, res, x1, y1, x2, y2);
x1 := x2;
x2 := x2 + 10;
if (j = 5) or (j = 10) or (j = 15) or (j = 20) or (j = 25) then //pour avoir des 6 lignes de 5 briques
begin
x1 := 200;
x2 := 245;
y1 := y2;
y2 := y1 + 25
end;
end;
end;
i := i + 1;
close(f);
end;
procedure RetourArriereMenu(X, Y : Integer; var m : Integer; var T : TkeyEvent; var C : char; var f, f2 : Text; var res : r; var GraphicsDriver, GraphicsMode, ErrCode : Smallint; s : String); //retourner en arrière à n'importe quel moment dans le menu
begin
InitKeyBoard();
T := GetKeyEvent();
T := TranslateKeyEvent(T);
C := GetKeyEventChar(T);
if C = 'w' then
begin
X := 62;
Y := 12;
ClrScr();
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, Y);
writeln('Niveaux');
GoToXY(55, Y + 2);
writeln('Regles');
GoToXY(X,Y);
repeat
T := GetKeyEvent();
T := TranslateKeyEvent(t);
C := GetKeyEventChar(t);
if C = 's' then
begin
GoToXY(X - 1, Y + 2);
X := 61;
end;
if C = 'z' then
begin
GoToXY(X, Y);
X := 62;
end;
until C = 'm';
ClrScr();
case X of
62: begin
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, Y);
writeln('Niveau 1');
GoToXY(55,Y + 2);
writeln('Niveau 2');
GoToXY(55,Y + 4);
writeln('Niveau 3');
GoToXY(63, 14);
x := 63;
end;
61: begin
DoneKeyBoard();
assign(F2, 'Regles.txt');
reset(F2);
while not eof(F2) do
begin
readln(F2, S);
writeln(S);
end;
RetourArriereMenu(X, Y, m, T, C, f, f2, res, GraphicsDriver, GraphicsMode, ErrCode, s);
end;
end;
x:=63;
repeat
t := GetKeyEvent();
t := TranslateKeyEvent(t);
c := GetKeyEventChar(t);
if c = 's' then
begin
if y < 16 then
begin
GoToXY(x, y + 2);
y := y + 2;
end;
end;
if c = 'z' then
begin
if y > 12 then
begin
GoToXY(x, y - 2);
y := y - 2;
end;
end;
until (c = 'm') or (c = 'w');
if c = 'm' then
begin
DoneKeyboard();
case y of
12: m := 1;
14: m := 2;
16: m := 3;
end;
ClrScr();
GraphicsDriver := Detect;
InitGraph(GraphicsDriver, GraphicsMode, 'C:\PP\BGI');
ErrCode := GraphResult;
If GraphResult <> grOK Then
Begin
Writeln('Une erreur graphique s est produite: ', GraphErrorMsg(ErrCode));
Writeln('Le fichier graphique (.BGI) n a pas ete trouve, donc veuillez changer le chemin dans InitGraph');
Readln;
Halt(1);
End
Else
begin
remplissageDoc(m, f);
MiseEnPlaceMur(m, f, res);
end;
readln;
closegraph;
end;
if c = 'w' then
RetourArriereMenu(X, Y, m, T, C, f, f2, res, GraphicsDriver, GraphicsMode, ErrCode, s);
end;
end;
end.
Graphics mode is failing to initialize but you are ignoring the result. Read GraphResult exactly once, and act on that.
Edit: put the BGI fonts in your .exe directory and use '' for the BGI path.
Code Organization
Your code is very disorganized and uses a lot of meaningless variable names — making it very hard to understand what you are trying to do. That and you keep trying to switch back and forth between graphics mode and text mode (and not quite getting it right).
This “answer” is designed to help you better organize your code.
Since this is a graphical game, forget WriteLn and everything else that is not graphical. The very first thing you should do is initialize graphics mode. Put that in a procedure if you wish:
procedure Initialiser;
var
gd, gm : integer;
begin
gd := Detect;
InitGraph( gd, gm, '' );
if GraphResult <> grOK then
begin
WriteLn( 'Impossible de démarrer le mode graphique.' );
Halt( 1 )
end;
ClearDevice
end;
begin
Initialiser;
end.
Next you want to do a menu. Make that a function:
type
ActionDeMenu = (Niveau1, Niveau2, Niveau3, Aider, Quitter);
function Menu : ActionDeMenu;
begin
// dessinez votre menu ici
// obtenir l'entrée de l'utilisateur
// retourner le choix de l'utilisateur
end;
You can then update your main program. You might as well put it in a loop; Break to quit.
begin
Initialiser;
repeat
case Menu of
Niveau1: Jouer( 1 );
Niveau2: Jouer( 2 );
Niveau3: Jouer( 3 );
Aider: Aider;
Quitter: Break
end
until false;
CloseGraph
end.
After that you need to write procedures to show help and to play the game at a specified level of difficulty:
procedure Aider;
begin
// afficher l'aide
// l'utilisateur doit appuyer sur Entrée (ou quelque chose) pour continuer
end;
procedure Jouer( niveau : integer );
begin
// initialiser le niveau de jeu
// jouer le jeu
// affichage gagné/perdu
end;
As you can see, we keep breaking tasks down into simpler tasks that:
do not need to be repeated
keep tasks separate
are simple
With just this organic sense of organization you can make the game much more understandable and easier to implement.

Get the minimum amount of degrees recorded in a day

I need to make a program that gets the minimum amount of degrees recorded in a day at what hour, I made the program, I am getting the correct hour at which the min amount of degrees were recorded but I am not getting the correct amount of degrees
Program P1;
Type
Hour = 0..23;
Degrees = -40..40;
Temperature = array [Hour] of Degrees;
var
t : Temperature;
i, min_t, max_t, hour_t_min, hour_t_max : integer;
procedure test;
begin
for i := 0 to 23 do
begin
writeln('Enter the temperature at hour ', i);
readln(t[i]);
min_t := t[0];
if min_t > t[i] then
begin
min_t := t[i];
ora_t_min := i;
end;
if max_t < t[i] then
begin
max_t := t[i];
ora_t_max := i;
end;
end;
writeln('temp min ', min_t, ' at hour ', hour_t_min);
writeln('temp max ', max_t, ' at hour ', hour_t_max);
end; {procedure}
begin { main }
test;
end.
Min_t (and max_t) should be initialized outside and before the loop.
You are assigning min_t:=t[0] in each loop, this is wrong, and max_t is not being initialized. Also, I think this is a typo, ora_t_min and ora_t_max should be changed to hour_t_min and hour_t_max:
Something like this:
min_t := 40;
max_t := -40;
for i := 0 to 23 do
begin
writeln('Enter the temperature at hour ', i);
readln(t[i]);
if min_t > t[i] then begin min_t := t[i]; hour_t_min := i; end;
if max_t < t[i] then begin max_t := t[i]; hour_t_max := i; end;
end;
writeln('temp min ', min_t, ' at hour ', hour_t_min);
writeln('temp max ', max_t, ' at hour ', hour_t_max);
end;

procedures don't work properly when dealing with files in pascal

In this program when I try to put the code blocks [1] and [2] in procedures they don't work properly when calling them, and when I keep them in the main program only the first one works properly and the second doesn't and when I comment out the first one the second one works as it's supposed...can you please spot the error, I think it's with getting the files names from the user cause when I choose the file's name it works properly
program Linked_lists_files;
type
Node = ^T;
T = record
num : integer;
next : Node;
End;
var
File1 : Text;
N, i, j, cmp, y, x, Num, matrixvalue : integer;
Head, Tail, Head2, Tail2, Head3, Tail3 : Node;
s : string;
matrix : array [1..20, 1..20] of Integer;
// procedures
// [1]
Procedure fillFile();
Begin
write('Input file name to create : ');
readln(s);
assign(File1,s);
rewrite(File1);
Repeat
write('Enter a number : ');
readln(N);
if (N>=0) then
writeln(File1, N);
Until (N<0);
close(File1);
End;
// [2]
Procedure GetFromFile();
Begin
cmp := 0;
write('Enter file name to read from : ');
readln(s);
assign(File1, s);
reset(File1);
while not eof(File1) Do
Begin
readln(File1, N);
if (Head = Nil) then
Begin
new(Head);
Tail := Head;
End
Else
Begin
new(Tail^.next);
Tail := Tail^.next;
End;
Tail^.num := N;
Tail^.next := Nil;
cmp := cmp + 1;
End;
Close(File1);
Write('Elements of the list : ');
Tail := Head;
if (Head<>nil) then
Begin
while(Tail <> nil) Do
Begin
write('[',Tail^.num,']', ' ');
Tail := Tail^.next;
End;
End
Else
Writeln('[!] The list is empty');
writeln;
writeln('Number of elements in the list : ', cmp);
End;
// [3]
Procedure SaveFromFile();
Begin
Head := Nil;
write('Enter file name to read from : '); readln(s);
writeln('[+] Fill in your list');
Repeat
write('+ Enter an integer : ');
read(y);
if (y>=0) then
Begin
if (Head = Nil) then
Begin
new(Head);
Tail := Head;
End
Else
Begin
new(Tail^.next);
Tail := Tail^.next;
End;
Tail^.num := y;
Tail^.next := Nil;
End;
Until y<0;
assign(File1, s);
rewrite(File1);
Tail := Head;
while(Tail <> nil) Do
Begin
Num := Tail^.num;
Tail := Tail^.next;
Writeln(File1, Num);
End;
Close(File1);
Writeln('[+] Elements of the lists have been successfully added to the new file');
End;
// [4]
Procedure SquareMatrix();
Begin
cmp := 0;
x := 0;
writeln('[+] Fill in your list');
Repeat
write('+ Enter an integer : ');
read(y);
if (y>=0) then
Begin
if (Head3 = Nil) then
Begin
new(Head3);
Tail3 := Head3;
End
Else
Begin
new(Tail3^.next);
Tail3 := Tail3^.next;
End;
Tail3^.num := y;
Tail3^.next := Nil;
cmp := cmp + 1;
End;
Until y<0;
while (cmp<>1) Do
Begin
if (cmp mod 2 <> 0) and (cmp <> 1) then
x := x + 1;
cmp := cmp div 2;
End;
if (x>0) then
writeln('[-] False')
Else
writeln('[+]True');
End;
// [5]
Procedure ElementsOfSM();
Begin
cmp := 0;
x := 0;
writeln('[+] Fill in your list');
Repeat
write('+ Enter an integer : ');
read(y);
if (y>=0) then
Begin
if (Head = Nil) then
Begin
new(Head);
Tail := Head;
End
Else
Begin
new(Tail^.next);
Tail := Tail^.next;
End;
Tail^.num := y;
Tail^.next := Nil;
cmp := cmp + 1;
End;
Until y<0;
Tail := Head;
i := 1;
j := 1;
while(Tail <> nil) Do
Begin
matrixvalue := Tail^.num;
matrix[i,j] := matrixvalue;
Tail := Tail^.next;
j := j + 1;
if (j = sqrt(cmp)+1) then
Begin
i := i + 1;
j := 1;
End;
End;
for i:=1 to cmp Do
for j:=1 to cmp Do
Begin
if (matrix[i,j]<>0) then
writeln('[',matrix[i,j],']',' : ','[',i,',',j,']');
End;
End;
// [6]
Procedure Element();
Begin
write('Enter the number of the line : ');
read(i);
write('Enter the number of the column : ');
read(j);
write('The element corresponding to ','[',i,',',j,'] is : ','[',matrix[i,j],']');
writeln;
End;
// [7]
Procedure WriteP();
Begin
write('Enter the number of the line : ');
read(i);
write('Enter the number of the column : ');
read(j);
write('Enter the value you want to pass in : ');
read(N);
matrix[i,j] := N;
writeln('The new matrix');
for i:=1 to cmp Do
for j:=1 to cmp Do
Begin
if (matrix[i,j]<>0) then
writeln('[',matrix[i,j],']',' : ','[',i,',',j,']');
End;
writeln;
End;
// [8]
Procedure Content();
Begin
write('Enter the number of the line : ');
read(i);
write('Enter the number of the column : ');
read(j);
writeln('The value stored inn this cell is : ','[', matrix[i,j],']');
End;
// Start of main program
Begin
Head := Nil;
Repeat
writeln('*********** MENU ***********');
writeln('[1] fillFile');
writeln('[2] GetFromFile');
writeln('[3] SaveFromFile');
writeln('[4] SquareMatrix');
writeln('[5] ElementsOfSM');
writeln('[6] Element');
writeln('[7] WriteP');
writeln('[8] Content');
writeln('*********** End ***********');
write('Choose one : ');
read(N);
case N of
1 : fillFile();
2 : GetFromFile();
3 : SaveFromFile();
4 : SquareMatrix();
5 : ElementsOfSM();
6 : Element();
7 : WriteP();
8 : Content();
End;
Until (N<>1) and (N<>2) and (N<>3) and (N<>4) and (N<>5) and (N<>6) and (N<>7) and (N<>8) and (N<>9);
End.
The problem you describe is being caused by the known behaviour of the Read statement; basically, the second (and subsequent) times you call it, it returns immediately, without waiting for any keyboard input and without reading anything.
This happen because FPC is closely based on Object Pacal in the commercial Delphi development package, and in Delphi's case, this is the officially documented behaviour.
From the Delphi (v7) online help:
Delphi syntax:
Text files:
procedure Read( [ var F: Text; ] V1 [, V2,...,Vn ] );
Description
The Read procedure can be used in Delphi code in the following ways.
[...]
With a type string variable:
Read reads all characters up to, but not including, the next end-of-line
marker or until Eof(F) becomes true; it does not skip to the next line after reading. If the resulting string is longer than the maximum length of the string variable, it is truncated.
After the first Read, each subsequent Read sees the end-of-line marker and returns a zero-length string (emphasis added).
Use multiple Readln calls to read successive string values.
Fortunately, the solution is simple, use readln, instead of read, as in
readln(s);
Update Make sure you replace all instances of read by readln, as you have left a number of them unchanged, as #TomBrunberg has commented.
After that, run your code again and select 1 from the menu and you will find that fillFile executes, but the program terminates on the until ... line. And that's because it is a very bad idea to use the same global variable, in this case N for several different purposes throughout the program. So, you should edit your code further (and carefully) so that as far as possible it only uses global variables for global purposes. Turn all all the other variables into local variables, preferably with different names than the global ones. If after that you are still having problems, submit a new question focused on that.

Difference between two dates in Pascal

This program is supposed to find the difference between two dates but it has a bug and I can't find it.
It keeps returning a big number - please help
Program tp4;
Type
dt = Record
jour : Integer;
mois : Integer;
annee : Integer;
End;
Var
date : dt ;
y,x,i,s : Integer;
Begin
x := 0;
s := 0;
For y:=1 To 2 Do
//2 dates
Begin
Writeln('Entrez un date : jour mois année ');
Readln( date.jour, date.mois, date.annee);
While ((date.jour<=0) Or (date.jour>31) Or (date.mois>12) Or (date.annee<=0) ) Do
//verfication loop
Begin
Writeln('Entrez une date valide : jour mois année ');
Readln(date.jour ,date.mois ,date.annee);
End;
s := s+date.jour ;
For i:= 1 To date.mois-1 Do
Case i Of
3,5,7,8,10,12,1 : s := s+31;
4,6,9,11 : s := s +30;
2 : If ((date.annee Mod 100)=0) And ((date.annee Mod 400) = 0 ) Then //convert months to days
s := s+29
Else If date.annee Mod 4 = 0 Then
s := s+29
Else s := s+28;
End; //Convert years to days
For i:= 1 To date.annee Do
If (i Mod 100 = 0) And (i Mod 400 = 0) Then s := s+366
Else If (i Mod 4 =0) Then s := s+366
Else s := s+365;
x:=s-x ;
End;
If (x)<=0 Then
Writeln('la difference est :',-x)
Else Writeln('la difference est :',x);
Readln;
End.
**input**
12 03 2019
13 03 2019
**output**
737510
I think the error was somewhere in s and x (x:=s-x; etc.), I did refactoring:
Program tp4;
Type dt = Record
jour : Integer;
mois : Integer;
annee : Integer;
End;
Type
arrayDate = array[1..2] of dt;
Var
y,i,f,s : Integer;
arrDate: arrayDate;
function Leap (Y : Word): Boolean;
Begin
If (Y Mod 4) <> 0 Then Leap := FALSE
Else If (Y Mod 100) <> 0 Then Leap := TRUE
Else Leap := (Y Mod 400) = 0;
End;
function Lenght (date: dt) : Integer;
Begin
Lenght := 0;
Lenght := Lenght + date.jour;
For i := 1 To date.mois Do
Case i Of
3, 5, 7, 8, 10, 12, 1 : Lenght := Lenght + 31;
4, 6, 9, 11 : Lenght := Lenght + 30;
2 : If Leap (date.annee) Then Lenght := Lenght + 29 Else Lenght:= Lenght + 28;
End;
For i := 1 To date.annee Do //Convert years to days
If Leap (i) Then Lenght := Lenght + 366 Else Lenght := Lenght + 365;
End;
Begin
For y := 1 To 2 Do //2 dates
Begin Writeln ('Entrez un date : jour mois année ');
Readln (arrDate[y].jour, arrDate[y].mois, arrDate[y].annee);
While ((arrDate[y].jour <= 0)
Or (arrDate[y].jour > 31)
Or (arrDate[y].mois > 12)
Or (arrDate[y].annee <= 0)) Do //verfication loop
Begin
Writeln ('Entrez une date valide : jour mois année ');
Readln (arrDate[y].jour, arrDate[y].mois, arrDate[y].annee);
End;
End;
f := Lenght(arrDate[1]);
s := Lenght(arrDate[2]);
Writeln ('la difference est :', Abs(s - f)); // absolute |s-f|
Readln;
End.
You are using the For y ... loop to request input and to calculate number of days for each input. Within the loop, the s variable is the days counter.
The error you do is that you zero s bfore the For y ... loop and not at the beginning of the loop. Therefore, the second time you request a date, s still has the value from the first date, on top of which you then start to calculate the days for the second date.
The correction is of course to move s := 0; to the beginning of the For y ... loop,
or change the first assignment of s from
s := s + date.jour;
to
s := date.jour;
Finding the difference between two dates 6,000 years apart in a loop? And (ab)using the name of a standard function "Length"? Ouch!
Try this:
//----------------------------------------------------------------------
// Convert a date to its Julian Day Number
//----------------------------------------------------------------------
procedure cj(dd, mm, yyyy: longint; var jdn, dow: longint);
var
cj_y,
cj_c,
cj_x,
cj_y: double;
begin
if dd = 0 then
begin
jdn:= -1
dow:= -1;
end
else
begin
cj_y:= yyyy + (mm - 2.85) / 12;
cj_c:= 0.75 * trunc(cj_y * 0.01);
cj_x:= frac(cj_y);
cj_y:= trunc(cj_y);
jdn:= trunc(
trunc(
trunc(367 * cj_x) + 367 * (cj_y) -
1.75 * cj_y + dd) - cj_c) +
1721115.0;
dow:= jdn mod 7;
end;
end; {cj}
Formula as given is valid for days after 1582-10-15, a small tweak will allow dates going back to 0000-03-01.
Follow the link in https://groups.google.com/g/comp.lang.pascal.borland/c/itwgcfYpLEU which I posted in August 1998 in comp.lang.pascal.borland for explanations.

Find block number and floor by flat number

Imagine - there's a house with 80 flats. It has 4 floors and 5 blocks. Each block has 4 flats.
User is asked to input flat number and Pascal program is supposed to calculate and output flat number. This must be calculated using some kind of formula. The only tip I have is that I have to use div and mod operations.
This is how the house looks like -
So far, I've created program, that loops through all 80 flats and after each 16 flats increases block value and after each 4 blocks increases stair.
This is my code:
program project1;
var
i, floors, blocks, flats, flat, block, floor, blockCounter, floorCounter : integer;
begin
floors := 4;
blocks := 5;
flats := 80;
while true do
begin
write('Flat number: ');
read(flat);
block := 1;
floor := 1;
blockCounter := 0;
floorCounter := 0;
for i := 1 to 80 do
begin
blockCounter := blockCounter + 1;
floorCounter := floorCounter + 1;
if (floorCounter = 4) then
begin
floorCounter := 0;
floor := floor + 1;
end;
if (blockCounter > 16) then
begin
block := block + 1;
blockCounter := 0;
floorCounter := 0;
floor := 1;
end;
if (i = flat) then
begin
writeln('Flat nr. ', flat, ' is in ', floor, '. floor and in ', block, '. block!');
end;
end;
end;
end.
Is there anyone who can help me with this?
I've finally solved my problem myself.
I finally undersood how div works, so I was able to solve this.
program Maja;
var dzivoklis, kapnutelpa, stavs : integer;
begin
while true do
begin
write('Ievadi dzivokla numuru: ');
read(dzivoklis);
kapnutelpa := ((dzivoklis - 1) div 16) + 1;
stavs := (((dzivoklis - 1) mod 16) div 4) + 1;
writeln('Kapnutelpa: ', kapnutelpa);
writeln('Stavs: ', stavs);
writeln();
end;
end.

Resources