PASCAL Can I take array elements and assign them to integer variables? - arrays

I am currently trying to write a program which provides a quarterly overview of the amount of money that a user defined number of salesmen has made for a whole year.
Here is the code I have at the moment:
program Verkopers;
var month, day, sellernr:array[0..99] of integer;
sale:array[0..99] of real;
count, num: integer;
begin
num := 0;
writeln('Enter seller number. To stop enter "0"');
readln(sellernr[num] );
while (sellernr[num] <> 0) do
begin
writeln('Enter date in DD MM format');
readln(day[num] , month[num] );
writeln('Enter sale amount');
readln(sale[num] );
num := num + 1;
writeln('');
writeln('Enter seller number. To stop enter "0"');
readln(sellernr[num] );
end;
writeln('Seller Nr.':10, 'Date':14, 'Amount':16);
for count := 0 to num-1 do
begin
writeln(sellernr[count], day[count]:20,'/',month[count], sale[count]:14:2);
end;
writeln('');
writeln('ENTER to stop');
readln();
end.
So as you see, the program asks for the seller number, then date in DD MM format and then the amount of the sale.
It the prints out to the screen.
What I have to do next is provide the per quarter overview. I have to take each seller number which the user has defined in the array sellernr and add up the total sales per quarter.
That's where I have a problem. How do I take the values that are stored in the array and recognise when they are equal (ie when sellernr[x] and sellernr[y] are the same)
Say the seller numbers the user inputs are 10, 50, 100. I must then take only the array elements which correspond to, first, 10 and print out, for example:
Seller Quarter1 Quarter2 Quarter3 Quarter4
10 $360.32 $567.21 $988.27 $1023.66
How can I take sellernr[x] which correspond to a particular user-defined value?

You can do something like this:
program Verkopers;
var
SalesByQuarters:array[1..4]of real;//here you will store the sums
ReporSeller:integer; //this will be the nr. of the seller for report
begin
...//append your code with this
writeln('Write seller number for report: ');
readln(ReporSeller);
for count:=1 to 4 do
SalesByQuarters[count]:=0;//initialize the output variables for each quarter
for count:= Low(sellernr) to High(sellernr) do
begin
if sellernr[count]=ReporSeller then //count will store the proper index
SalesByQuarters[((month[count]-1) div 3) +1]:=
SalesByQuarters[((month[count]-1) div 3) +1]+sale[count];
end; //((month[count]-1) div 3) +1 gives us the number of quarter.
// You can get it in a different way (if/case/etc)
write('Report for seller ');
writeln(ReporSeller);
for count:=1 to 4 do
begin
write('Quarter ');
writeln(count);
writeln(SalesByQuarters[count]:14:2); //output the stored sums
end;
readln;
end.
You can also beautify the output by something like this:
writeln('Seller Quarter1 Quarter2 Quarter3 Quarter4');
writeln(ReporSeller:6,
' $', SalesByQuarters[1]:7:2,
' $', SalesByQuarters[2]:7:2,
' $', SalesByQuarters[3]:7:2,
' $', SalesByQuarters[4]:7:2);

Related

Dynamic array of string skips the first index

I am doing a program in which the user inputs the wage, name and the number of working hours per month for a certain number of employees. This piece of code is supposed to recieve Nemp employees and then ask for Nemp names. The problem is, it always skips the first name, it displays 'Employee name:' twice and doesn't allow the user to insert the first one. I don't understand why this is happening, any help would be greatly appreciated!
program test;
uses crt;
var
i, Nemp : integer;
employee: array of string;
BEGIN
read(Nemp);
SetLength (employee, Nemp);
for i:=1 to Nemp do
Begin
writeln ('Employee name: ');
readln (employee[i]);
end;
END.
Dynamic arrays are zero based. You should loop from zero to Nemp-1. Or loop from zero to High(employee).
And as #Rudy and #trincot points out, to read the length of the employee array, use ReadLn(Nemp) to avoid unwanted input effects.
A tip:
Enable range and overflow check in the compiler when debugging. That would have detected the error at the high range.

Initialization of field in array of records (Pascal) [duplicate]

This question already has an answer here:
Lazarus readln doesn't read the variable
(1 answer)
Closed 4 years ago.
I have a small code where I want to initialize an array of records by fields and then just output this records on screen.
Data types:
type
grade = 1..5;
Person = record
Name: string[16];
isMale: boolean;
grades: array [1..6] of grade;
end;
var
Table: array [1..10] of Person;
R: Person;
N,J,I: Integer;
Part of code with initialization and output:
readln(n);
if N>10 then N:=10; if N<1 then N:=1;
for I:=1 to N do begin
R:=Table[I];
//write('Gender?'); readln(j); R.isMale:=j>=0; <= This works just fine
write('Name? '); readln(R.Name);
write('Gender? '); readln(j); R.isMale:=j>=0;
write('Grades? '); for j:=1 to 6 do read(R.grades[J]); writeln;
end;
for I:=1 to N do begin
R:=Table[I];
write(I,' ', R.Name,' ',R.isMale);
end;
When I enter info about first person it works fine, but then every other person's name input is skipped (output is "Name? Gender? ). If I switch entering boolean and string, code works correct, but that's not a logic order.
Why is this happening?
At the end of the loop, you should assign the record to the array. Note that, unlike with classes, assigning a record copies the data in the record, it does not reference the record. So instead of what you have, rather do:
for I := 1 to N do
begin
//write('Gender?'); readln(j); R.isMale:=j>=0; <= This works just fine
write('Name? ');
readln(R.Name);
write('Gender? ');
readln(j);
R.isMale := j >= 0;
write('Grades? ');
for j := 1 to 5 do
read(R.grades[J]);
readln(R.grades[6]); // readln reads the end-of-line too.
writeln;
Table[I] := R; // copy the data from R into the table
end;
That way, the data from the record R is copied into the table. There is no need to copy R from the table at the beginning of the loop, as the table is empty anyway.
Unlike with classes, with records like this, you could do the following too:
write('Name? ');
readln(Table[I].Name);
write('Gender? ');
readln(j);
Table[I].isMale := j >= 0;
// etc...
And in the final loop:
Writeln(I, ' ', Table[I].Name, ' ', Table[I].IsMale);
without using R at all.

Populate a database gives strange results

I have a database and I need to populate it's first 2 columns on every row. The first column is the date and the second column is an id.
My code is as follows:
.......
febr29:array[1..12] of byte = (31,29,31,30,31,30,31,31,30,31,30,31);
.......
procedure TForm.populate_database;
var
i,j,m,n: Integer;
begin
for i := 1 to 12 do
for j := 1 to febr29[i] do
for m := 1 to 9 do
for n := 1 to 15 do begin
database.tbl1.Append;
database.tbl1['date']:= inttostr(j)+'.'+inttostr(i)+'.2016';
database.tbl1['id']:='a'+inttostr(m)+inttostr(n);
database.tbl1.Post;
end;
end;
So basically I need to have all the ids on all the days of the year. But I have a problem with the code above: it gives me some strange output in the database, as in the following picture:
What am I doing wrong?
If your ID field is supposed to identify the data row, it would be better to declare it in the database as an integer column, not a character/string one.
It would also be better & less error prone not to try and calculate it from your loop variables, but use a running counter instead
procedure TForm.populate_database;
var
i,j,m,n: Integer;
ID : Integer;
begin
ID := 0;
for i := 1 to 12 do
for j := 1 to febr29[i] do
for m := 1 to 9 do
for n := 1 to 15 do begin
Inc(ID);
database.tbl1.Append;
database.tbl1['date']:= inttostr(j)+'.'+inttostr(i)+'.2016';
database.tbl1['id'].AsInteger :=ID;
database.tbl1.Post;
Of course, if you must have the 'a' prefix and a character coumn type for some reason, you could do
database.tbl1['id'].AsString :='a' + IntToStr(ID);
but even that may give you results you aren't expecting, unless to pad the result of IntToStr(ID) to a fixed length with leading zeroes.

Pascal Arrays Can't figure out how to print info from arrays

I'm trying to write a program tracks the products made by 7 machines in a factory, which all make the same 10 kinds of products.
The program asks the user to enter the machine id (A, B, C...G)
Then the product id (0, 1, 2...9)
and finally the program asks for a 0 or 1 to mark the product as either good quality or bad quality.
I put all of that information into three arrays. What I have to do next is the part I'm stuck with. I have to create two tables from all that information.
The first table is a table of good quality products. It has to be a two dimensional table with the MachineIDs running along the top and the ProductIDs running down the side.
There needs to be a running total for every single machine and every single product. So, in the cell [A0] needs to be a total of how many times machineA has made product0 and it was marked as GOOD. Then [A1] and so on all the way to [G9]
The second table is exactly the same only this time only the bad products are counted.
At the bottom there needs to be a total of ALL products made by each machine. Down the right hand side there has to be a total of ALL the individual products made be all machines.
Here's my code so far.
program Production;
var machine: array of char;
var product: array of integer;
var quality: array of integer;
var min, number, extra: integer;
var machineID: array[1..7] of char;
var productID: array[1..10] of char;
var x, y, count: integer;
begin
x:= 0;
y:= 0;
number := 0;
min := 5;
extra := 5;
SETLENGTH( machine, min );
SETLENGTH( product, min );
SETLENGTH( quality, min );
writeln('Input Machine ID ( A, B, C, D, E, F or G ) ');
readln(machine[number] );
while (machine[number] <> '*') do
begin
while ( ORD( machine[number] ) < 65 ) or ( ORD( machine[number] ) > 71 ) do
begin
writeln('Input Invalid. Please try again.');
readln(machine[number] );
end;
writeln('Input Product Number ( 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9 ) ');
readln(product[number] );
while ( product[number] < 0 ) or ( product[number] > 9 ) do
begin
writeln('Input Invalid. Please try again.');
readln(product[number] );
end;
writeln('Quality Control Check. Input 0 for GOOD or 1 for BAD.');
readln(quality[number] );
while ( quality[number] <> 0 ) and ( quality[number] <> 1 ) do
begin
writeln('Input Invalid. Please try again.');
readln(quality[number] );
end;
number := number + 1;
writeln('Input Machine ID ( A, B, C, D, E, F or G ) ');
readln(machine[number] );
end;
for count := 0 to number - 1 do
begin
writeln('Machine ID = ',machine[count] );
writeln('Product ID = ',product[count] );
writeln('Quality = ',quality[count] );
end;
writeln('');
writeln('');
writeln('EXIT');
readln;
end.
Could anyone tell me even how I would go about it? I'm completely at a loss.
I would approach the problem a bit differently. After I've recorded all the input from the user for one piece of data (machine, product and quality), I'd store it in a table - or in this case in a three-dimensional array. If I recall correctly, you can create such thing as follows:
var myTable: array[1..7, 1..10, 1..2] of integer;
The dimensions of the table would come as follows:
1..7 would be the machine Ids
1..10 would be the product Ids
1..2 would be the good/bad.
Once I got all the input from the user, I would simply increment the appropriate field in the table. E.g. assume the user inputs are: { machine B, product 2, Good } then we would
myTable[1, 2, 0] := myTable[1, 2, 0] + 1;
Therefore when we would want to print out our table we could just:
for i := 0 to 7 do
begin
for j := 0 to 10 do
begin
write(myTable[i,j,0] + ' '); { i,j,0 for the good; i,j,1 for the bad values }
end;
writeln('');
end;

2D Array - in PASCAL with loop

I need to write a program which demonstrates 2d array, the program need to ask for student name and then the mark.. and this is for 15 students. At the end program outputs 15 names with their marks next to it.
I don't know how to manipulate 2D arrays accurately, I managed to do simple version without using for loop.
`
table: array[1..2, 1..15] of string; {2 rows for 15 columns}
begin
clrscr;
writeln('Enter 15 student names, and a set of marks after each ');
writeln('With marks you can enter more marks after comma for e.g. 34, 26, 31 etc.');
writeln('Enter NAME and SURNAME of STUDENT NR 1 or q to quit ');
read(table[1][1]); {read name in row 1 col 1}
readln;
writeln(' Enter MARKS of STUDENT NR 1 ');
read(table[2][1]); { read mark in row 2 col 1}
readln;
clrscr;
writeln('Enter NAME and SURNAME of STUDENT NR 2 or q to quit ');
read(table[1][2]);
readln;
writeln('Enter MARKS of STUDENT NR 2 ');
read(table[2][2]);
readln; read marks into row 2 column 2}
`
etc. up to student nr 15... but I know I could use two for loops to do that for me instead of copying code for each student... same for output... I've spend many hours to figure out how to do it with different tries... but still Im confused with using two for loops and indexing this array correctly.
could someone help me with this appropriate looping ?
Thanks
Wow, Pascal, haven't seen it for a very long time! It's a good language for learning to program.
Try something like this..
program testarray2d;
uses crt;
var
table: array[1..2, 1..15] of string; {2 rows for 15 columns}
counter: Integer;
Begin
writeln('Enter 15 student names, and a set of marks after each ');
writeln('With marks you can enter more marks after comma for e.g. 34, 26, 31 etc.');
For counter := 1 to 15 do
Begin
writeln('Enter NAME and SURNAME of STUDENT NR ');
write(counter);
write(' or q to quit ');
readln(table[1][counter]);
writeln('Enter MARKS of STUDENT NR ');
write(counter);
readln(table[2][counter]);
clrscr;
End;
End.
Please let me know if it works, because I haven't tested it.

Resources