Reading and processing file in Pascal won't work after first line - loops

I'm having trouble reading more than one line from a data file in Pascal. It gives me an "Invalid numeric format" run-time error when I try to read in more than one line (I tested just the first line separately and it works fine). This makes me think that it has something to do with the carriage return at the end of a line.
Here is the code that should read in all of the lines from my .DAT file:
program commission;
var
moreRec:Boolean;
FileOut:Text;
FileIn:Text;
DRONE_ID:String[9];
DRONE_NAME:String[18];
SALES:Real;
COMM:Real;
procedure header;
begin
writeln(FileOut, Space(16),'SALES COMMISSION REPORT');
writeln(FileOut);
writeln(FileOut,' SSN',Space(10),'SALESPERSON',Space(9),'SALES COMMISSION');
writeln(FileOut);
end;
procedure readRec;
begin
if EOF(FileIn) THEN
moreRec:=false
else
read(FileIn, DRONE_ID);
read(FileIn, DRONE_NAME);
read(FileIn, SALES);
COMM:=SALES*0.03;
end; {readRec}
procedure initial;
begin
moreRec:=true;
Assign(FileIn, 'PRG2-150.DAT ');
Reset(FileIn);
Assign(FileOut,'output.txt');
Rewrite(FileOut);
readRec
end; {initial}
procedure process;
begin
write(FileOut, DRONE_ID);
write(FileOut, Space(2));
write(FileOut, DRONE_NAME);
write(FileOut, Space(5));
write(FileOut, SALES:9:2);
write(FileOut, Space(3));
writeln(FileOut, COMM:8:2);
readRec
end; {process}
procedure wrapup;
begin
Close(FileOut);
Close(FileIn);
end; {wrapup}
begin
initial;
header;
while moreRec = true do
process;
wrapup;
end.
And here is the .DAT file that I am reading from:
998874673Joe Smith 27.65
849773298Sue Williams 35.90
445861253Al Oop 54.90
584988754Diane Mindykowski 25.96
758423652Alicen Morse 53.35
485236845Burton Schuring 58.52
586974512Linda Gillam 69.35
I'm new to Pascal but I'd love to learn why my program won't read in more than one line.
Thanks

I think you'll need a
readln(FileIn);
towards the end of readRec to skip past the CR/LF delimiter to the next line.

Pascal wants the data fields in text files to be white-space delimited. The problem is that you have no space between the Drone_Id and Drone_Name fields.
998874673Joe Smith 27.65
_________^__ Insert space here.
You also should use a readln for the last field on the line (Sales).
EDIT: Sorry the space isn't needed there (I was thinking that the first field was numeric). But do make sure you use readln on the last field of the line.

Related

Mysql Database where I am creating a procedure to figure out if it is able to determine whether the input is correct or not

I was creating a procedure which can determine if the input (parameter) is correct or not. But I think it is not working.
DELIMITER //
CREATE PROCEDURE akatsuki_TailedBeast()
BEGIN
SELECT * from Shinobi_Every_Nation WHERE Caught_TailedBeastName != "NA";
END;
//
DELIMITER ;

Ab initio to read comma delimited values

What should be my DML for input file which has data like 1,2,34,43,66
The problem which i am facing when i put the below DML
record
decimal(",") val;
end;
is that the last number is not getting read properly.
Is there any way to read this by only using Input file component.
you have described only ONE numeric field, but you have 5 fields
"new line" (new record) also should be described
are you using BRE ? you could create DML in BRE
You can try the following DML I guess it should work:
record
decimal(",") val1;
decimal(",") val2;
decimal(",") val3;
decimal(",") val4;
decimal(",") val5;
string("\n") newline = NULL;
end
I presume you want to read each number as a record. The problem is: data is not compatible with your desire, last number is not delimited by a ",".
If you can't change the data, you could read all the input in a single record, using:
record
string("\n") val;
end
then use a normalize component to split the record:
out :: length(in) =
begin
out :: length_of(string_split(in.val, ","));
end;
out :: normalize(in, index) =
begin
let string(";")[5] my_vec;
my_vec = string_split(in.val, ",");
out.val :: decimal_lpad( my_vec[index], 5 );
end;
(there are probably better solutions, I am still not an expert, but there wasn't an answer yet)

PL/SQL cursor for loop and record not working

I have the following problem. I'm trying to check a number (bsn), if it's in the database or not. If it's not in the database it should give me an error, however now I'm getting always an error even if the number exists in the database. It worked fine with only one number in the database, but with more... That's the problem. Oh and I'm working with APEX, so I use this as a process.
create or replace PROCEDURE CONTROLE_BSN IS
CURSOR c_klanten
IS
SELECT bsn
FROM klant;
v_bsn VARCHAR2(10) := V('P7_BSN');
e_geen_bsn EXCEPTION;
BEGIN
FOR r_record IN c_klanten
LOOP
IF r_record.bsn != v_bsn THEN
RAISE e_geen_bsn;
END IF;
END LOOP;
EXCEPTION
WHEN e_geen_bsn THEN
raise_application_error(-20001, 'This bsn-number does not exists.');
END CONTROLE_BSN;
Your logic is flowed. As soon as you have two different bsn in your table, your test will be true for at least one of them:
FOR r_record IN c_klanten
LOOP
IF r_record.bsn != v_bsn THEN --< when N different records,
-- this is true for at least N-1 of them
RAISE e_geen_bsn;
END IF;
END LOOP;
Maybe you should go for something a little bit simpler than that. Why not write your cursor like this instead:
CURSOR c_klanten
IS
SELECT count(*) n
FROM klant
WHERE nbc = v_bsn;
That way, you will easily get the number of matching bsn. Either 0, 1 or more. And then perform the appropriate action.
Perhaps the following would help:
create or replace PROCEDURE CONTROLE_BSN IS
CURSOR c_klanten(p_bsn) IS
SELECT count(*) as bsn_count
FROM klant
where bsn = p_bsn;
v_bsn VARCHAR2(10) := V('P7_BSN');
e_geen_bsn EXCEPTION;
BEGIN
FOR r_record IN c_klanten(v_bsn)
LOOP
IF r_record.bsn_count = 0 THEN
RAISE e_geen_bsn;
END IF;
END LOOP;
EXCEPTION
WHEN e_geen_bsn THEN
raise_application_error(-20001, 'This bsn-number does not exists.');
END CONTROLE_BSN;
Best of luck.

Putting a line of text into an array delimited by quotes?? Delphi

Okay I am still very new to delphi coding and coding in general. I have researched on splitting strings into an array or list delimited by : or , but in this case I need to do it by a string that is delimited by " ".
Example: "fname","lastname","someplace,state","some business,llc","companyid"
and what I need is the array to be
(item[0] = fname) (item[1] = lastname) (item [2] = someplace,state) (item[3] = some business, llc.) (item[4] = companyid)
So as you can see I cannot read in a line of text using the comma as a delimeter because it would throw everything off.
Is there any way to read in a line of text and split it into an array like the example above??
See documentation for TStrings.CommaText.
Here is an example:
program Project1;
{$APPTYPE CONSOLE}
uses
System.SysUtils,Classes;
var sl: TStringList;
s: String;
begin
sl := TStringList.Create;
try
sl.CommaText := '"fname","lastname","someplace,state","some business,llc","companyid"';
for s in sl do
WriteLn(s);
ReadLn;
finally
sl.Free;
end;
end.
The documentation also says:
Note: CommaText is the same as the DelimitedText property with a delimiter of ',' and a quote character of '"'.
So if using DelimitedText, just make sure QuoteChar is " and the Delimiter is ,.

Pascal runtime error (range overrun) while reading array from file

I am trying to write a program to read a long list of book(1000 books),isbn etc
but when the program runs, it shows range overrun
the format of txt is
1
1234567890
ABC book
peter
20
2
1234567896
...
the code is:
const maxbk=1000;
type bookrecord = record
book_no:string;
isbn:string;
book_name:string;
author:string;
borrowed:string;
end;
var booklist : array[1..maxbk] of bookrecord;totalbook:integer;
procedure readbooklist(var bklist:array of bookrecord;var totalbk:integer);
var f:text;temp:string;code:integer;
begin
totalbk:=0;
assign(f,'bklist.txt');
reset(f);
while not eof(f) do
begin
readln(f,bklist[totalbk+1].book_no);
readln(f,bklist[totalbk+1].isbn);
readln(f,bklist[totalbk+1].book_name);
readln(f,bklist[totalbk+1].author);
readln(f,bklist[totalbk+1].borrowed);
totalbk:=totalbk+1;
end;
close(f);
writeln('read file done');
end;
begin
readbooklist(booklist,totalbook);
end.
who can help to fix the problem??
I think the problem is in your handling of the array parameter. Try this (highlighted in bold are the changes I've added):
const maxbk=1000;
type bookrecord = record
book_no:string;
isbn:string;
book_name:string;
author:string;
borrowed:string;
end;
var booklist : array[1..maxbk] of bookrecord; totalbook:integer;
procedure readbooklist(var bklist:array of bookrecord;var totalbk:integer);
var f:text;temp:string;code:integer;
begin
totalbk:=Low(bklist);
assign(f,'bklist.txt');
reset(f);
while not eof(f) do
begin
readln(f,bklist[totalbk].book_no);
readln(f,bklist[totalbk].isbn);
readln(f,bklist[totalbk].book_name);
readln(f,bklist[totalbk].author);
readln(f,bklist[totalbk].borrowed);
totalbk:=totalbk+1;
end;
totalbk := totalbk - Low(bklist);
close(f);
writeln('read file done');
end;
begin
readbooklist(booklist,totalbook);
end.
Also, a few choice spaces would help with readability (like a space after each comma and around assignment operators).
Note, too, that your code (and the changed code I'm providing) don't check for incomplete records in your input text file or properly check for blank lines, etc (e.g., invalid book_no values). You should attempt to add some code which makes it a little more resilient to problems in the input file. As others have pointed out, there are probably better ways to structure the input and read it as well.

Resources