Can't exit a while loop - pascal

I can't get readln to change the condition
program CFS;
{Defining Constants}
const
{Pay Rates}
ManagerBasic = 8000;
AssistManagerBasic = 7000;
SupervisorBasic = 5000;
SalesStaffBasic = 3000;
{Allowances}
DailyAllowance = 0.11;
TravelAllowance = 0.06;
EntertainmentAllowance = 0.035;
CommissionRate = 0.03;
{Deductions}
SocialSecurity = 0.06;
EnvironmentLevy = 0.01;
Insurance = 0.02;
{creating and initialising variables where necessary}
var
Name : string;
//i : integer = 0;
StaffType : string;
TotalSales : real = 0.0;
CommissionEarned : real = 0.0;
MajorLoop : integer = 1;
begin
{this is just the psueudocode comments for the real program}
writeln('The Caribbean Fashion Store');
writeln('Electronic Communication Calculator Version 1.0.1');
writeln('Build No. 001');
writeln('Sands, Sheba');
{We will use a while loop as a means of making the program start and stop at the user s will. First we ask for a choice:'}
writeln();
writeln('To process an employee, type 1 and press Enter, otherwise type 0 and press Enter');
while (MajorLoop = 0) do
begin
writeln('To process another employee, type 1 and press Enter, otherwise type 0 and press Enter');
end;
writeln(ManagerBasic/DailyAllowance);
{read is placed to stop the program}
readln();
end.

In the var section you initialize MajorLoop with the value 1 so the loop will never run.
Change your while to something like
while(MajorLoop = 1) do
begin
writeln('To process another employee, type 1 and press Enter, otherwise type 0 and press Enter');
readln(MajorLoop);
end;
This way if the user type 0 the loop ends (I'm assuming that's what you want to do).

Related

Not overloading operator

Good day, I'm doing some Codeforces exercises in my free time, and I had a problem to test if the user was a boy or a girl, well, my problem isn't that, i have just demonstrated the code.
While compiling my code in my computer ( I'm using version 3.0.4 for i386 ) i get no error, but codeforces gives me this error
program.pas(15,16) Error: Operator is not overloaded: "freq(Char;AnsiString):LongInt;" + "ShortInt"
program.pas(46,4) Fatal: There were 1 errors compiling module, stopping
The error wasn't clear enough to me, as the same script was perfectly compiled with my version.
The platform is using ( version 3.0.2 i386-Win32 ).
program A236;
uses wincrt, sysutils;
var
username : String;
function freq(char: char; username : String): Integer;
var
i: Integer;
begin
freq:= 0;
for i:= 1 to length(username) do
if char = username[i] then
freq:= freq + 1;
//writeln(freq);
end;
function OddUserName(username : String): Boolean;
var
i, counter: Integer;
begin
OddUserName:= false; // even
counter:= 0;
for i:= 1 to length(username) do
if freq(username[i], username) <> 1 then
delete(username, i, 1)
else
counter:= counter + 1;
if counter mod 2 <> 0 then
OddUserName:= true; // odd
//writeln(counter);
//writeln(OddUserName);
end;
begin
readln(username);
if not OddUserName(username) then
writeln('CHAT WITH HER!')
else
writeln('IGNORE HIM!');
//readkey();
end.
The error is supposed to be at this line probably :
function freq(character: char; username : String): Integer;
Thanks for everyone who helps.
Inside of a function, the function's name can be used as a substitute for using an explicit local variable or Result. freq() and OddUserName() are both doing that, but only freq() is using the function name as an operand on the right-hand side of an assignment. freq := freq + 1; should be a legal statement in modern Pascal compilers, see Why i can use function name in pascal as variable name without definition?.
However, it would seem the error message is suggesting that the failing compiler is treating freq in the statement freg + 1 as a function type and not as a local variable. That would explain why it is complaining about not being able to add a ShortInt with a function type.
So, you will have to use an explicit local variable instead, (or the special Result variable, if your compiler provides that), eg:
function freq(charToFind: char; username : String): Integer;
var
i, f: Integer;
begin
f := 0;
for i := 1 to Length(username) do
if charToFind = username[i] then
f := f + 1;
//writeln(f);
freq := f;
end;
function freq(charToFind: char; username : String): Integer;
var
i: Integer;
begin
Result := 0;
for i := 1 to Length(username) do
if charToFind = username[i] then
Result := Result + 1;
//writeln(f);
end;

Read / write different Records data from / to Untyped files in Pascal?

I've a programming project in my college.
Using a File type for storing data is allowed, and I did exactly like this one: pascal-programming
And, here's what I achieved so far:
I tried to write the Records data into Untyped files instead and it worked
I want to override a function with dynamic parameter (e.g: I can switch which Record I want to process, in this case there's 2 different "Records").
Open(var f: File; var data)
data = represent can receive "anything". cmiiw
The reason why I did this, I don't think it's a good idea to recreate the same function over and over, e.g: when using 3 or more different "Records"
I also encountered a problem that the files can't store or backup the actual binary files to the temporary "Records" variable, it always give the 0 values.
go to my github source code
my solution here doesn't provide any generic related procedures (check the last sentences):
program test_untyped;
{ A crude database recording }
uses crt;
type
Temployee = record
name : string[20];
address : string[40];
phone : string[15];
age : byte;
salary : longint;
end;
arr_employee = array[1..100] of Temployee;
var
F : File;
c : char;
// r : Temployee;
r, realR : arr_employee;
s : string;
i, j, n : integer;
procedure fRead;
begin
seek(F, 0);
i := 0;
repeat
clrscr;
inc(i);
writeln('increment: ', i); readln;
writeln('File position : ',filepos(F));
blockRead(F, r[i], sizeOf(Temployee));
writeln('Name = ', r[i].name); { Input data }
writeln('Address = ', r[i].address);
writeln('Phone = ', r[i].phone);
writeln('Age = ', r[i].age);
writeln('Salary = ', r[i].salary);
write('Show data again (Y/N) ?');
repeat
c:=upcase(readkey); { Ask user : Input again or not }
until c in ['Y','N'];
writeln(c);
// realR[i] := r[i]; // backup, to show later
until c='N';
end; // end fRead
procedure fWrite;
begin
seek(F, filesize(F));
repeat
clrscr;
inc(i);
writeln('berapa nilai i: ', i);
writeln('File position : ',filepos(F));
write('Name = '); readln(r[i].name); { Input data }
write('Address = '); readln(r[i].address);
write('Phone = '); readln(r[i].phone);
write('Age = '); readln(r[i].age);
write('Salary = '); readln(r[i].salary);
blockWrite(F, r[i], sizeOf(Temployee)); { Write data to file }
write('Input data again (Y/N) ?');
repeat
c:=upcase(readkey); { Ask user : Input again or not }
until c in ['Y','N'];
writeln(c);
until c='N';
end;
// procedure fDelete;
// var
// nama: string;
// delElement: integer;
// tempR: Temployee;
// begin
// seek(F, 0);
// write('search your data by name: '); readln(nama);
// while not eof(F) do
// begin
// writeln('file position: ', filePos(F));
// blockRead(F, tempR, sizeOf(Temployee));
// if (nama = tempR.name) then
// begin
// delElement := filePos(F);
// end else
// begin
// // seek(F, )
// blockWrite(F, tempR, sizeOf(Temployee));
// end;
// end;
// end; // end fDelete
procedure fDisplay;
begin
writeln('nilai i saat ini: ', i); readln;
for j := 1 to i do
begin
clrscr;
writeln('Name = ', r[j].name); { Input data }
writeln('Address = ', r[j].address);
writeln('Phone = ', r[j].phone);
writeln('Age = ', r[j].age);
writeln('Salary = ', r[j].salary);
readln;
end;
end;
begin
clrscr;
// write('Input file name to record databases : '); readln(s);
s := 'coba1.dat';
assign(F,s); { Associate it }
{$I-}
reset(F, sizeOf(Temployee)); { First, open it }
{$I+}
n:=IOResult;
if n<>0 then { If it's doesn't exist then }
begin
{$I-}
rewrite(F, sizeOf(Temployee)); { Create it }
{$I+}
n:=IOResult;
if n<>0 then
begin
writeln('Error creating file !'); halt;
end;
end
else
begin { If it exists then }
n:=filesize(F); { Calculate total record }
// seek(F,n); { Move file pointer PAST the last record }
end;
fileMode := 2;
reset(F, sizeOf(Temployee));
fRead;
fWrite;
// fDelete;
fDisplay;
close(F);
end.
I'm wondering is the Pascal can be any good to use a generic programming? at least for this semester using Pascal in my college XD
Thank you and Best Regards,
EDIT:
Pascal still doesn't support Generic Programming 'till the day I posted this question. So sad, really.
You might wanna consider read this references instead.
I don't understand the main issue here, but would suggest using a typed file instead of an untyped one.
An untyped file is much harder to maintain, and provides (in my eyes) no benefits.
Consider the code:
type
Temployee = record
name : string[20];
address : string[40];
phone : string[15];
age : byte;
salary : longint;
end;
VAR
fEmployee : File Of Temployee;
Employees : ARRAY[0..100] Of Temployee;
Employee : Temployee;
PROCEDURE OpenEmployeeFile(CONST TheFileName:AnsiString);
BEGIN
AssignFile(fEmployee,TheFileName);
IF FileExistsUTF8(TheFileName) { *Converted from FileExists* }
THEN Reset(fEmployee)
ELSE Rewrite(fEmployee);
END;
PROCEDURE CloseEmployeeFile;
BEGIN
Close(fEmployee);
END;
FUNCTION ReadEmployee(Position:WORD): Temployee;
BEGIN
Seek(fEmployee,Position);
Read(fEmployee,Result);
END;
PROCEDURE WriteEmployee(CONST Employee:Temployee; Position:WORD);
BEGIN
Seek(fEmployee,Position);
Write(fEmployee,Employee);
END;
Error handling not implemented.
Code samples as a guideline, not complete.
It provides a basic skeleton for opening and closing the employee-file, as well as reading and writing at specific positions (specific records) in the file.
Open file.
Write all the records you want.
Close file.
Or.
Open file.
Read all the records you want.
Close file.

Code not moving past Read

I'm having a problem with my code. It starts fine but when asking to get input from the user at the start it will not move onto the if statement. How can I fix this. I've tried heaps to get around this and eventually got it to read data but continually say that it is invalid.
PROGRAM AT3 (input, output);
uses crt, math;
CONST
band6 = 90;
band5 = 80;
band4 = 70;
band3 = 60;
band2 = 50;
VAR
Studname : array of string;
studmark : array of integer;
flag : boolean;
studinfo : text;
input : string;
count : integer;
num : integer;
input2: integer;
highmark, lowmark : integer;
median, average : integer;
BEGIN
lowmark := 100;
highmark := 0;
median := 0;
ASSIGN (Studinfo, 'ExamResults.txt');
flag := false;
WRITELN('welcome to the Band generator.');
WRITELN('To enter student results, please enter the number of students. To see class statistics, please type zzz. To clear the screen type clear screen. And to exit the program, type exit');
While flag = false DO
ReadLN (input);
IF input = 'zzz' THEN
WHILE not EOF(Studinfo) DO
BEGIN
WRITELN(studinfo);
END;
IF input = 'exit' THEN
Flag := true;
IF input = 'clear screen' THEN
CLRSCR
ELSE
if input2 <> 0 THEN
num := input2
ELSE
WRITELN('Please enter a valid number.');
FOR count := 0 to num-1 DO
BEGIN
WRITELN('Please enter name of student', count);
read(studname[count]);
WRITE(studinfo, studname[count]);
WRITELN('Please enter mark of student', count, 'out of 100 (nearest whole number)');
read(studmark[count]); write(studinfo, studmark[count]);
IF studmark[count] >=band6 THEN
WRITELN(studinfo, 'band6');
IF studmark[count] >=band5 THEN
WRITELN(studinfo, 'band5');
IF studmark[count] >=band4 THEN
WRITELN(studinfo, 'band4');
IF studmark[count] >=band3 THEN
WRITELN(studinfo, 'band3');
IF studmark[count] >=band2 THEN
WRITELN(studinfo, 'band2');
IF studmark[count] <band2 THEN
WRITELN(studinfo, 'band1');
IF studmark[count] >= highmark THEN
highmark := studmark[count];
IF studmark[count] <= lowmark THEN
lowmark := studmark[count];
END;
median := highmark MOD 2;
CLOSE(studinfo);
END.
Questions like this often attract a comment like "SO is not a homework-doing
service." This q is a bit exceptional because there is no polite way I can think
of to describe it. It has all the signs of having been written by someone who
doesn't really know what they are doing - but don't despair, we were all beginners once!
I'm not going to rewrite all your code for you - because you won't learn anything from that - but the following should at least give
you a functional main loop which you can then complete yourself and embellish as necessary.
The main thing I've fixed is the sequence of actions in the loop - the original
was a complete muddle, to put it mildly. I've added various comments enclosed in braces {}.
There is a more recent style of comments that uses // but I don't know what flavour
of Pascal you're using.
Code:
const
band6 = 90;
band5 = 80;
band4 = 70;
band3 = 60;
band2 = 50;
ArraySize = 20; { to set explicit array sizes }
var
studname : array[1..ArraySize] of string;
studmark : array[1..ArraySize] of integer;
flag : boolean;
studinfo : text;
kbdinput : string; { to avoid name clash with program Input param}
count : integer;
num : integer;
{input2: integer; not used}
highmark,
lowmark : integer;
median, average : integer;
begin
lowmark := 100;
highmark := 0;
median := 0;
assign (studinfo, 'c:\temp\examresults.txt'); { always use full path for file name }
Rewrite(studinfo); { set studinfo in the state to allow writing to the file}
flag := false;
writeln('welcome to the band generator.');
writeln('to enter student results, please enter the number of students when prompted.');
while flag = false do
begin
write('please enter a valid number of students. ');
readln(num);
for count := 1 to num do { not change of start and stop values}
begin
write('please enter name of student #', count, ' followed by [Enter] ');
readln(studname[count]);
write(studinfo, studname[count]);
write('please enter mark of student #', count, ' out of 100 (nearest whole number) followed by [Enter] ');
readln(studmark[count]);
write(studinfo, studmark[count]);
end;
{
if studmark[count] >=band6 then
writeln(studinfo, 'band6');
if studmark[count] >=band5 then
writeln(studinfo, 'band5');
if studmark[count] >=band4 then
writeln(studinfo, 'band4');
if studmark[count] >=band3 then
writeln(studinfo, 'band3');
if studmark[count] >=band2 then
writeln(studinfo, 'band2');
if studmark[count] <band2 then
writeln(studinfo, 'band1');
if studmark[count] >= highmark then
highmark := studmark[count];
if studmark[count] <= lowmark then
lowmark := studmark[count];
end;
median := highmark mod 2;
}
writeln('to see class statistics, please type zzz. to clear the screen type zzz and to exit the program, type exit');
readln (kbdinput);
if kbdinput = 'zzz' then
{ The following does nothing useful
while not eof(studinfo) do
begin
writeln(studinfo);
end;
}
;
if kbdinput = 'exit' then
flag := true
else
if kbdinput = 'clear screen' then
{clrscr;'}
close(studinfo);
end;
end.
Look at your line:
While flag = false DO
ReadLN (input);
Flag is never false so it reads forever. You are having problems with your begin/end blocks.

Error : Operator is not overloaded

I've created a simple block of code using Free Pascal to validate an ID number such as Abc123 being input.
When I try to run the program I get an error saying, "Operator is not overloaded" at the points where it says,
IF not (Ucase in Upper) or (Lcase in Lower) or (Num in Int) then
Specifically where the "in" appears.
Does anyone have any idea why the error occurs and what I can do to solve it?
Thanks!
Program CheckChar;
VAR
UserID, LCase, UCase, Num : String;
readkey : char;
L : Integer;
CONST
Upper = ['A'..'Z'];
Lower = ['a'..'z'];
Int = ['0'..'9'];
Begin
Write('Enter UserID ');Readln(UserID);
Ucase := Copy(UserID,1,1);
LCase := Copy(UserID,2,1);
Num := Copy(UserID,3,2);
L := Length(UserID);
While L = 6 Do
Begin
IF not (Ucase in Upper) or (Lcase in Lower) or (Num in Int) then
Begin
Writeln('Invalid Input');
End;
Else
Writeln('Input is valid');
End;
readln(readkey);
End.
in is used to test the presence of an element in a set. Here you set is a set of char, so the element to test must also be a char. In your sample the elements you tested were some strings (UCase, LCase and Num) which caused the error message.
You have to use a slice of Ucase and LCase of length one or you can also directly take a single character (astring[index]) instead of copying with Copy.
Also your while loop is totally useless. You have to test only 6 characters so let's unroll the loop instead of puting some complexity while obsvioulsy you just start learning.
Finally, one way to write your checker correctly is so:
Program CheckChar;
var
UserID : string;
readkey : char;
L : Integer;
invalid: boolean;
const
Upper = ['A'..'Z'];
Lower = ['a'..'z'];
Int = ['0'..'9'];
begin
Write('Enter UserID ');
Readln(UserID);
L := length(UserId);
if L <> 6 then invalid := true
else
begin
invalid := not (UserID[1] in Upper) or // take a single char, usable with in
not (UserID[2] in Lower) or // ditto
not (UserID[3] in Lower) or // ditto
not (UserID[4] in Int) or // ditto
not (UserID[5] in Int) or // ditto
not (UserID[6] in Int); // ditto
end;
if invalid then
Writeln('Invalid Input')
else
Writeln('Input is valid');
readln(readkey);
end.

LINQ: executing stored procedure, but skipping cursor within

I'm working on this wonky data project (C#/LINQ/MS SQL). I receive a very poorly formatted dataset and I'm working at building up some meaningful reports with the data. For one of the reports ("SwitchFlow"), I'm created a Stored Proc called "SwitchFlowGenerate". It takes two params, the date of the report and the company of origin.
At the very end of the stored proc I ended up using a cursor (uck) to loop through the data to generate a customer count field value.
When I run the stored proc within management studio it works 100%. When I had the stored proc to my LINQ-to-SQL and call it from a Visual Studio C# console app, it doesn't completely work...
From my app, the stored proc "SwitchFlowGenerate" populates the report table as it should, returns no error codes (in debug or production), but it appears to not execute the cursor portion of the stored proc (leaving the customer count field at zero).
I call the stored proc from MS SQL Management Studio simply like this:
exec switchflowgenerate '03-13-2012', 'ace'
From C#/LINQ I call it like this:
db.SwitchFlowGenerate(DateTime.Now, ldc);
(note: .Now is the same as above in MSMS)
The cursor portion of the code looks like this:
**--Update Customer Count column to reflect account switch movement
DECLARE #Adjust INT
SET #Adjust = 0
DECLARE #cc nvarchar(100)
DECLARE #stat nvarchar(100)
DECLARE SFC CURSOR FOR SELECT CustomerCount, [Status] FROM SwitchFlow WHERE ReportDate = #rptDate AND LDC = #ldc FOR UPDATE
OPEN SFC
FETCH SFC INTO #cc, #stat
WHILE (##FETCH_STATUS = 0)
BEGIN
IF #stat = 'Dropped' BEGIN SET #Adjust = -1 END
IF #stat = 'Start' BEGIN SET #Adjust = 1 END
IF #stat = 'In Queue - To Start' BEGIN SET #Adjust = 1 END
IF #stat = 'In Queue - To Drop' BEGIN SET #Adjust = -1 END
IF #stat = 'Reenrolling' BEGIN SET #Adjust = 1 END
IF #stat = '#### SAME DAY ####' BEGIN SET #Adjust = 0 END
SET ##StartingTotal = ##StartingTotal + #Adjust
UPDATE [SwitchFlow] SET CustomerCount = ##StartingTotal WHERE CURRENT OF SFC
FETCH SFC INTO #cc, #stat
END
CLOSE SFC
DEALLOCATE SFC**
Linq generates:
Generating Data For: ACE on 3/13/2012
EXEC #RETURN_VALUE = [dbo].[SwitchFlowGenerate] #rptDate = #p0, #ldc = #p1
-- #p0: Input DateTime (Size = -1; Prec = 0; Scale = 0) [3/13/2012 9:56:59 AM]
-- #p1: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [ACE]
-- #RETURN_VALUE: Output Int (Size = -1; Prec = 0; Scale = 0) [Null]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
Any help or insight would be greatly appreciated ~especially if someone has an idea of how to accomplish that without a cursor.
Thanks!!
TK

Resources