Hi all
I am gonna declare an arbitrary sized one dimensional array in fortran so that the size of array will specify
by user input. i can not use syntax below:
program main
integer :: n
print *, “Enter a positive integer number:”
read *, n
real, dimension(n) :: a
…
…
…
end program main
You need an allocatable array. Its size is determined at run-time:
program main
implicit none
integer :: n
real, allocatable, dimension(:) :: a
print *, “Enter a positive integer number:”
read *, n
...
allocate(a(n))
… ! work with a
deallocate(a)
...
end program main
So you declare your array as allocatable, and then explicitly allocate it with the size you want. When you’re done working with it, deallocate it to free the memory.
If you prefer, you can also omit the dimension attribute and declare the array like this:
real, allocatable :: a(:)
It’s a good habit to always include implicit none at the beginning of your program.
By the way, starting with Fortran 2008 and the introduction of the BLOCK construct, it’s also possible to employ an “automatic” array which may be of interest to some readers. Here’s an example: note the automatic array has the scope of the BLOCK construct.
integer :: n
print *, "Enter a positive value for n"
read *, n
print *, "you entered n=", n
block
integer :: a(n)
integer :: i
a = [( i, i=1, n )]
print *, "a = ", a
end block
end
Here’s the processor response to this example
C:\Temp>type p.f90
integer :: n
print *, “Enter a positive value for n”
read *, n
print *, “you entered n=”, n
block
integer :: a(n)
integer :: i
a = [( i, i=1, n )]
print *, "a = ", a
end block
end
C:\Temp>gfortran -Wall p.f90 -o p.exe
C:\Temp>p.exe
Enter a positive value for n
5
you entered n= 5
a = 1 2 3 4 5
@ELNS
A piece of code without goto (I don’t want to troll about goto but I think the code will be clearer because of the indentation):
do
print *, "Enter a positive value for n"
read *, n
if (n > 0) exit
end do
Note that in Fortran there is no repeat...until or do...while (with the while at the end) loops.
You could of course also use the old trick:
n = -1
do while (n<=0)
print *, "Enter a positive value for n"
read *, n
end do
But this is less elegant than the exit solution because the statement n=-1 is arbitrary: n=-2020 or n=-314159265 would do the job as well. If the language offers an elegant solution then use it, if it does not, find a trick.
Note that there is also the cycle statement to go to the next iteration of a loop.
My understanding is that the block construct simply allows programmers to organise code by grouping declarations and statements together within a defined local scope. This can have some advantages:
It avoids large declaration blocks at the beginning of programs and procedures;
it is easier to reason which variables are used in which execution statements when reading the code;
it limits the scope of variables so they can’t accidentally be used elsewhere;
it can be useful for objects with finalizers since these will be called at end block if the objects are declared within the block.
I don’t believe there is any tacit memory or speed advantage to using block constructs, they are just for programmer comfort.
The main argument against using block constructs IMHO is that a procedure would provide the same advantages in terms of code organisation, while also being reusable (callable) whereas a block construct is not.
Thank you @lkedward for that answer. Do you think there could be a speed impairment if a block is repeated a lot of time in a loop ? (if its variables need to be allocated at each iteration)
I would expect a slow down if you are declaring large arrays with dimensions only known at runtime (just like @parekhvs’s example above) - though this is true regardless of if you’re using a block construct.
However if the variables are scalar or the array size is a compile-time constant, then I would expect the compiler to be able to optimise this (i.e. allocate once). Unfortunately I’m no compiler expert, so this is my best guess.
Another great usage of block that @lkedward pointed out to me is to prevent name clashes between intrinsic functions and named variables by introducing a new local scope. An example can be found in the discussion Best practices for passing C strings.
I didn’t know about that addition for 2018 so thanks for the heads-up. The syntax seems to be very similar to that of openmp (a good thing). Nevertheless I’d say that the block construct gives you more, particularly if there are many variables or more sophisticated initializations.
do concurrent (i=1,10)
block
integer :: a, b
call load_start_values(a,b)
....
end block
end do
I agree - I don’t use do concurrent but my experience with OpenMP is that the locality clauses can quickly get long; by comparison the block construct is much cleaner and more readable.