Decoding a PASCAL line of code - pascal

I am new to PASCAL and I am working on a PASCAL code. I would really appreciate if somebody helped me understand this piece of code.
readagain1:
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+1)], fileio_dcb.usr_buf^[WRD((2*j)+0)])):4:16);
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+3)], fileio_dcb.usr_buf^[WRD((2*j)+2)])):4:16);
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+5)], fileio_dcb.usr_buf^[WRD((2*j)+4)])):4:16);
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+7)], fileio_dcb.usr_buf^[WRD((2*j)+6)])):4:16);
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+9)], fileio_dcb.usr_buf^[WRD((2*j)+8)])):4:16);
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+11)], fileio_dcb.usr_buf^[WRD((2*j)+10)])):4:16);
Write(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+13)], fileio_dcb.usr_buf^[WRD((2*j)+12)])):4:16);
WriteLn(' ', (BYWORD(fileio_dcb.usr_buf^[WRD((2*j)+15)], fileio_dcb.usr_buf^[WRD((2*j)+14)])):4:16);
j := j+8;
IF (j < 100) THEN GOTO readagain1;
j := 0;
int_dcb.txt_buf.r := 0;
WriteLn;
WriteLn('Reading txt_buf ; ');
readagain1 is a label that has already been declared.
Hexdecimal numbers are being read from a file into a buffer(fileio_dcb.usr_buf) ans some operation is being performed on the hex number read. I would appreciate any help with understanding the operation being performed on the number.

My guess is that each iteration it writes out 13 (=100/8 rounded up) lines with 8 (16-bit) word sized hex numbers per line. Each line has a leading space.
It is probably an atypical (non Borland) dialect that can write hexvalues using :4:16 (I assume this means base 16, 4 digits wide). Most typical dialects (and the standard?) only use :x:y for floating point.
BYWORD() and WRD() are not standard identifiers, my guess this is some embedded dialect that combines two bytes into a word. Maybe it can only read words from aligned addresses, and are these builtins/macros workarounds for that.
Note that this is all based on "most likely it does that". The fragment is not complete enough, and the dialect not standard.

Related

Invalid Floating Point Operation?

I am a beginner in Pascal. I made this simple calculating program and keep getting exitcode : 207 message when running this code. Some website says that it is because of the invalid floating point operation. So I suppose its because of the division of zero. But I don't know how to avoid that.
uses crt;
var
a, b, c, d, e, f : real;
begin
c := a + b;
d := a - b;
e := a * b;
f := a / b;
writeln(' Basic Math Operation ');
writeln('Write First Number a ');
readln(a);
writeln('Write Second Number b ');
readln(b);
writeln('The addition of a + b =', c);
writeln('The substraction of a - b =', d);
writeln('The multiplication of a x b =', e);
writeln('The division of a / b =', f);
readln;
end.
I also tried to add this but keep getting the same exitcode : 207
if (b=0) then
writeln(' Can't do division by 0 !')
else
writeln('The division of a / b =', f);
or this one that i found on a forum
except on EDivByZero do ShowMessage('Can't do division by 0 !');
What shall i do???
Assuming you are using Free Pascal:
By default, simple variables in Pascal are not initialized after their declaration. Any assumption that they contain 0 or any other default value is erroneous: They can contain rubbish. To remedy this, the concept of initialized variables exists. The difference with normal variables is that their declaration includes an initial value, as can be seen in the diagram in the previous section.
Remark 2 exceptions to this rule exist:
Managed types are an exception to this rule: Managed types are always initialized with a default value: in general this means setting the reference count to zero, or setting the pointer value of the type to Nil. See section 3.9, page 226
Global variables are initialized with the equivalent of zero.
a, b, c, d are initialised to 0 at the start of the program. Therefore f:=a/b produces division by zero error. You should move the line readln(a) and readln(b) at the start of the program to assign a value to the variables before use. Also check whether b is inputted as 0 to avoid similar issues.

I'm having some problems with even and odd numbers in Pascal

I'm having some problems with my program in Pascal. I need to create a program which will calculate even and odd sums of a number's decomposition. For example, if my number is 10 the program should write that sum of even numbers is 30 (since 2,4,6,8,10 are the even numbers) and it should write that sum of odd numbers is 25 (since 1,3,5,7,9 are odd numbers). Here is what i tried
program odd_even;
var
a,sumeven,sumodd,even,odd : integer;
begin
writeln('Enter a number : ');
readln(a);
if a mod 2 = 0 then a=even;
if a mod 2 not=0 then a=odd;
for a:1 to a do begin
sumeven:=0;
sumeven:=sumeven+even
writeln('Sum of even numbers is : ',sumeven);
sumodd:=0;
sumodd:=sumodd+odd;
writeln('Sum of odd numbers is : ',sumodd),
end;
readln
end.
The compiler says that my if part is illegal but I don't understand how I can fix it, I also tried with else but it says the same thing. If someone could help me out I would be really thankful.
First of all, welcome to the world of programming!
There are several errors in your code:
The initialization of your result variables
sumEven:=0;
sumOdd:=0;
should be before your for loop
checking odd/even
if a mod 2 = 0 then a=even;
if a mod 2 not=0 then a=odd;
should be inside your loop and you should check not whether a (your input number) is odd/even but the value of your loop variable:
for i := 1 to a do
begin
if (i mod 2 <> 0) then sumOdd := sumOdd+1 else sumEven := sumEven+1 ;
end;
Printing the results should be of course after your loop.
Good luck!

how to write reciprocal value of a number in pascal?

I'm having some problems with a program in pascal.
I need to enter a number and than I need the program to write an addition of reciprocal value of that number. It sholud be something like this : let's say the number is 5 (n=5) then I need my program to write 1/1 + 1/2 + 1/3 + 1/4 + 1/5 and a result of this addition , I need to use for,to,do in order to get a solution, so if someone could help me, I'd be really thankful.
I tried something like this :
program reciprocaladdition;
var x : integer:
begin
writeln('enter number');
readln(x);
for x:=1 to x do writeln(1/x:0:2)
readln
end.
but it doesnt give me whaat i need so if someone could help me id be thankful.
Your has a couple of typos:
the colon after integer should be a semicolon; and
the writeln needs a semicolon after it because there is another statement (readln) after it.
Apart from that, it compiles and runs fine in Lazarus + FPC. In the corrected version below, I've added code to calculate and display the sum of the intermediate values.
program reciprocals;
var
x : integer;
Sum : Double; // a floating-point datatype
begin
writeln('enter number');
readln(x);
Sum := 0;
for x:=1 to x do begin
writeln(1/x:0:2);
Sum := Sum + 1/x;
end;
writeln('Sum: ', Sum:0:2);
readln
end.
This produces the output
enter number
3
1.00
0.50
0.33
Sum: 1.83
Does that do what you want it to? If not, please say why.

ISO pascal and recursivity

I can not find out what is the correct behaviour of this program according to ISO pascal standard. I tried to read the ISO 7185 Standard document but did not find anything on this topic. What should be the result 4 or 24 ?
program Undetermined;
var
n: Integer;
function fact: Integer;
begin
fact := 1;
if n > 1 then
begin
n := n - 1;
fact := (n + 1) * fact
end
end;
begin
n := 4;
writeln( fact )
end.
EDIT : I realised that there is a second problem in my example. So consider the new code :
program Undefined;
var
n: Integer;
function power2: Integer;
begin
power2 := 1;
if n > 0 then
begin
n := n - 1;
power2 := 2 * power2
end
end;
begin
n := 4;
writeln( power2 )
end.
The result should be 16 or 2 (according to my compiler) ?
EDIT : thanks for the answer event if they did not solve my problem. I finally got the right answer on an other forum : the ISO-standard specify the behaviour I expected but the compiler I use (fpc) does not conform the standard on that point with the default settings.
There are two separate issues here:
Does fact denote the result of the function, or a recursive call?
If it does denote a recursive call, is the result 24 or implementation defined?
1. Does fact denote the result of the function, or a recursive call?
Since fact doesn't occur on the left side of an assignment, it doesn't correspond to the result of the function, so it should invoke the function recursively. The compiler treating fact and fact() differently in this context sounds like a bug.
The standard says:
Within an activation, an applied occurrence of a label or variable-identifier, or of a procedure-identifier or function-identifier local to the block of the activation, shall denote the corresponding program-point, variable, procedure, or function, respectively, of that activation; except that the function-identifier of an assignment-statement shall, within an activation of the function denoted by that function-identifier, denote the result of that activation.
2. If it does denote a recursive call, is the result 24 or implementation defined?
Even if you disregard the recursion related issue, and use fact(), you still can't expect to always get 24 as a result.
It boils down to: "Is (n+1) or fact() evaluated first in the expression (n + 1) * fact?
The order of evaluation is implementation defined in this case. This means that different implementations following the standard can give different results, and you can't expect 24 for all of them.
To quote the standard:
6.7.2 Operators
6.7.2.1 General
Table 3 | Dyadic arithmetic operations
...
* Multiplication
...
A factor, a term, or a simple-expression shall be designated an operand. The order of evaluation of the operands of a dyadic operator shall be implementation-dependent.
NOTE | This means, for example, that the operands may be evaluated in textual order, or in reverse order, or in parallel, or they may not both be evaluated.
Free Pascal's ISO dialect mode is very young (1-2 years), as FPC generally is a Borland and not ISO oriented compiler.
The Mac Pascal mode is more tested, and is in general very ISO like. Compiling in macpascal mode will yield the "16" answer without ().
Probably ISO mode should do the same and not use the borland/delphi like return value is a pseudo variable. Please file a bug.

reading data from txt file in fortran

I am writing a FORTRAN program that reads data from a text file and writing it to the console. the data file looks something like this
1234567890123456 123456.789 987654.321 673647.890 654356.890
6172876534567890 768909.098 234543.890 654321.908 987890.090
I have the following lines of FORTRAN code that reads data and just writes them to the console
OPEN(1,FILE='data.txt')
READ(1,'(I16,3F9.3)') A ,B, C, D
WRITE (*, '(I16,3F9.3)') A,B,C,D
CLOSE(1)
Instead of getting displayed as the same values in the text file, the following is the output
1234567890123456*********89987.656 0.322
6172876534567890*********98234.547 0.891
Can you please help me with this.
Thanks much
List-directed IO (i.e., *) is easier, especially on input. Nevertheless, there are times to use full IO control so that is worth understanding. On input, the data items and descriptors must line up by column. For input, in Fw.d, the d doesn't matter if you have a decimal point in the data item. The fields must be wide enough on both input and output. There need to be enough descriptors, of types which match the variables and the data items. Compare to this example program:
program test_read
implicit none
integer, parameter :: VLI_K = selected_int_kind (18)
integer, parameter :: DR_K = selected_real_kind (14)
integer (VLI_K) :: i
real (DR_K) :: a, b, c, d
open (unit=15, file="data.txt", status='old', &
access='sequential', form='formatted', action='read' )
read (15, 110) i, a, b, c, d
110 format (I16, 4(1X, F10.0) )
write (*, 120) i, a, b, c, d
120 format ( I18, 4 (2X, F12.3) )
read (15, *) i, a, b, c, d
write (*, 120) i, a, b, c, d
end program test_read
I had the hardest time ever trying to use read, but finally...
If you want to read a matrix stored in a .txt file use this:
program FILEREADER
real, dimension(:,:), allocatable :: x
integer :: n,m
open (unit=99, file='array.txt', status='old', action='read')
read(99, *), n
read(99, *), m
allocate(x(n,m))
do I=1,n,1
read(99,*) x(I,:)
write(*,*) x(I,:)
enddo
end
And the "array.txt" file must be like this for instance (And placed in the same folder of the main):
4
3
0.0 1.0 2.0
3.0 4.0 5.0
6.0 7.0 8.0
9.0 10.0 11.0
Hope it works for everyone out there
Slight modification to the #Andrés Argüello Guillén answer.
Unlike most other solutions, my code does not force you to specify in advance the number of rows and columns.
CHARACTER(128) :: buffer
integer strlen, rows, cols
real, dimension(:,:), allocatable :: x
OPEN (1, file = 'matrix.txt', status='old', action='read')
!Count the number of columns
read(1,'(a)') buffer !read first line WITH SPACES INCLUDED
REWIND(1) !Get back to the file beginning
strlen = len(buffer) !Find the REAL length of a string read
do while (buffer(strlen:strlen) == ' ')
strlen = strlen - 1
enddo
cols=0 !Count the number of spaces in the first line
do i=0,strlen
if (buffer(i:i) == ' ') then
cols=cols+1
endif
enddo
cols = cols+1
!Count the number of rows
rows = 0 !Count the number of lines in a file
DO
READ(1,*,iostat=io)
IF (io/=0) EXIT
rows = rows + 1
END DO
REWIND(1)
print*, 'Number of rows:', rows
print*, 'Number of columns:', cols
allocate(x(rows,cols))
do I=1,rows,1
read(1,*) x(I,:)
write(*,*) x(I,:)
enddo
CLOSE (1)
matrix.txt
0.0 1.0 2.0
3.0 4.0 5.0
6.0 7.0 8.0
I used fixed format because the editing and inspecting of input files having fixed column structure is easier than that of zigzag data.
My problem was how the Fortran run-time reader procedures interpret the presence and absence of decimal dots. I am not sure that my solution was the best but I read the data lines as character arrays, split them to fields having length 12 characters then I read the fields by read(*) statements.
The reason is that you're specifying a width that is too small for the real numbers. Usually when the width doesn't fit, fortran will display asterisks, which happens in your case.
You have 9 digits, but you'll need at least 10, since the comma takes up a column as well.
So replacing 3F9.3 with 3F10.3 should do the trick.
It is usually better to read data in non fixed format. And to leave some leading spaces so that numbers can fit when writing them out.
integer(8) :: i
real(4) :: x, y, z
open(unit=1, file='data.txt')
read(1,*)i, x, y, z
write(*,'(i16, 3f11.3)')i, x, y, z
end

Resources