How to directly read a 4-byte data into a 8-byte variable in fortran? - io

Suppose there is a 4-byte int data stored in a binary data file e.g. data.bin
But I want to read it directly to a 8-byte variable?
There is a test code:
INTEGER*4 :: I,J,K
INTEGER*8 :: L
OPEN(6,FILE='data.bin',,FORM='UNFORMATTED',ACCESS='STREAM',ACTION='READWRITE',STATUS='REPLACE')
I=1; J=2; K=3;
WRITE(6) I,J,K
REWIND(6)
READ(6) L
READ(6) I
WRITE(*,*) L, I
CLOSE(6)
It turns out tha I=3, but L is neither 1 nor 2
How could I read the first int data (I=1) into L?

Related

How to open complex number file in python that generated by C program?

My code
with open('car.FT','r', encoding="utf-8",errors='ignore') as h:
for line in h:
print(line)
File "car.FT" is output of Fourier transform that has complex values stored.It is written through a C program but I want to open this file in python.
The output is not readable with this above piece of code used.
The file is written in C :
typedef struct complex { /* Define a complex type */
float r,i; /* Real and imaginery parts */
} COMPLEX;
/* buffer for input image being converted into complex type */
COMPLEX IN_BUF[ROWS][COLS];
///PROCESSING ON IN_BUF////
fwrite(IN_BUF, sizeof(COMPLEX), ROWS*COLS, fout);
Here below is the data actually in the file. That I want to read.
I want to read this above file data in python.
Judging by the C code the numbers are written as binary float numbers, and what you are showing is the hex output of the file contents. In this case, you have to read the binary contents, while you are trying to read it as a text file.
You have to open the file in binary mode (rb), read and convert each float value (which is 4 bytes long) using struct.unpack, and convert pairs of float to complex. Here is a simple implementation (untested):
from struct import unpack
numbers = []
with open(filename, "rb") as f:
data = f.read() # read all data
count = len(data) // 8 # each complex number takes 8 bytes
i = 0
for index in range(count):
# "f" means float (4 bytes); unpack returns a tuple with one value
real = unpack("f", data[i:i + 4])[0]
i += 4
im = unpack("f", data[i:i + 4])[0]
i += 4
numbers.append(complex(real, im))
print(numbers)

How can a pointet to char act like an array?

I am trying to understand pointers in C.
char *name = "HASAN";
When I store " HASAN" using char *, the string is stored somewhere in the memory as an array of characters.
I can access to every single character of the string by treating "name" as an array.
//second character of HASAN is A.
printf("%c", name[1]);
But I have learnt that "name" is just a pointer that stores the address of the first character 'A' of the string "HASAN".
So, how can " name", a pointer act like an array?
It quite simple.
As standards says:
*(name + N) == name[N]
And it does not matter how name is declared as arrays decay to pointers.
char *name = "HASAN";
or
char name[] = "HASAN";
Consider the following two examples:
char arr[] = "HASAN"; // array
It allocates 6 consecutive bytes of memory and associates the address of the first allocated byte with arr.
On the other hand,
char ptr* = "HASAN"; // pointer
The pointer variable ptr* stores 6 consecutive bytes for the variable and 4 extra bytes for pointer variable itself and assigns the address of the string literal to ptr. So, in this case, a total of 10 bytes are allocated.

How to read from a string as if reading from a file in fortran?

The following code is attempting to read a file into a memory block storing characters and read data from that block instead of the original file. ( The code is modified based on here )
program read_file
implicit none
integer :: n
character(len=:), allocatable :: s
character(len=5) :: a, b
open(unit=10, file="read_file.f", action="read",
1 form="unformatted", access="stream")
inquire(unit=10, size=n)
allocate(character(n) :: s)
read(10) s
close(10)
print "(A)", s
read ( s, * ) a
read ( s, * ) b
print *, a
print * , b ! meant to read from the previously visited place
end program read_file
When trying to read from the character block 's', the program always reads from the beginning of it rather than reads continuously as reading a text file. So 'a' and 'b' are exactly the same. Is there a way to read 's' as if it read from a file ? Thanks!

Equivalent to SAS function repeat in PROC IML

I want to define a string in a PROC IML, say "aaaaa" (five "a").
In a DATA step, I would use the repeat() function, which creates a string repeating substrings, as explained in the documentation.
data _null_;
x=repeat('a',4); /* string with five 'a' */
put x;
run;
However, in SAS/IML, the repeat() function is different : it creates a matrix repeating elements of another one (documentation here).
So if I use this function, I will get a vector with five "a" elements.
proc iml;
x=repeat('a',5); /* 5 'a' strings */
print x;
quit;
In that example, I could obviously not bother and go directly with :
x="aaaaa";
But what if I needed a larger string (say 100 "a" for example) ? I could also create it outside of the PROC IML and import it after but there must be a more clever way to address the problem, isn't there ?
There is no need to write a loop. Use the ROWCATC function to concatenate the elements across columns:
proc iml;
N = 10;
x = rowcatc(repeat("a", 1, N)); /* repeat 'a' N times */
print x (nleng(x))[L="Length"];
A slightly harder problem is to concatenate elements and insert some sort of delimiter beteen the elements (blanks, comas, etc). That problems is discussed in the article "Convert a vector to a string."
As IML works with matrices, that is what you normally would want.
To get columns instead of rows:
proc iml;
x=repeat('a', 1, 5);
print x;
quit;
x
a a a a a
You could convert the vector to string using a loop. But in that case it would make more sense to skip repeat and directly use a loop to produce a string:
proc iml;
x="";
do i = 1 to 5;
x = x + 'a';
end;
print x;
quit;
x
aaaaa

Copying string failure in Fortran

I would like to have a procedure which makes a local copy b of input character a (of not assumed length) into an allocatable array of characters. I do have the following code
program test_copystr
character(len=6) :: str
str = 'abc'
call copystr(str)
contains
subroutine copystr(a)
character(len=*), intent(in) :: a
!> Local variables
integer :: i
character, allocatable :: b(:)
allocate(b(len_trim(a)))
do i=1, len_trim(a)
b(i) = a(i:i)
end do
print *, b
b(1:len_trim(a)) = a(1:len_trim(a))
print *, b
end subroutine copystr
end program test_copystr
where I'm trying to assign a to b in two different ways. The result is
abc
aaa
I thought that both assignments should yield the same output. Can anyone explain me that difference? (To compile this code I'm using gfortran 5.2.0 compiler.)
As you know b is an array of characters while a is a scalar; when the subroutine is called it is a 6-character string. These are different things. The statement
b(1:len_trim(a)) = a(1:len_trim(a))
specifies the array section b(1:3) on the lhs, that is all 3 elements of b, and the substring a(1:3) on the rhs. Now, when assigning a substring of length 3 to a single character such as any element of b Fortran assigns only the first character of the string.
In this case every element of b is set to the first character of a. It is as if the compiler generates the 3 statements
b(1) = 'abc'
b(2) = 'abc'
b(3) = 'abc'
to implement the array assignment. This is what Fortran's array syntax does with an array on the lhs and a scalar (expression) on the rhs, it broadcasts the scalar to each element of the array.
The first method you use, looping across the elements of b and the characters of a is the regular way make an array of characters equivalent to a string. But you could try transfer -- see my answer to this question Removing whitespace in string

Resources