This question already has answers here:
Allocatable array valued function. gfortran vs ifort
(1 answer)
Assignment of Allocatables of Different Shapes in Fortran [duplicate]
(1 answer)
Closed 5 years ago.
I've got a simple Fortran function that converts a comma delimited string into an array of character(len=255). I can't figure out how to create a variable that can receive the output of this function.
Here's my comma delimited string to array function:
function CommaDelimitedStringToArray(commastr) result (slist)
character(*), intent(in) :: commastr
! Local vars
character(255), dimension (:), allocatable :: slist
integer :: scount
! Lots of code removed - I set scount to be the number
! of elements in the comma delimited string, with a
! minimum value of 1
! Create the slist and populate it...
allocate (slist(scount))
! Lots more code removed. At the end of this function I know I have
! slist defined with the correct size and correct contents
end function CommaDelimitedStringToArray
Now I want to actually use this function. I've tried this:
character(255) :: commastr
character(255), dimension (:), allocatable :: mylist
commastr = "this,that,theother,etc"
mylist = CommaDelimitedStringToArray(trim(commastr))
But mylist does not receive the array from the function call.
In my testing if I allocate mylist to the correct size before calling the function it does receive the array correctly. But, obviously, in the real world I don't know the size before I call the function.
How do I declare/use mylist so it will correctly receive the array?
EDIT - My compiler reports itself as "IntelĀ® Parallel Studio XE 2016 Update 3 Composer Edition for Fortran Windows Integration for Microsoft Visual Studio 2015, Version 16.0.0062.14" running on Win 10.
Compiler flags are:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /Fd"Debug\vc140.pdb" /traceback /check:bounds /check:stack /libs:static /threads /dbglibs /c
Related
subroutine iswap (file,b)
implicit none
integer b,m
character*(*) file
m=1
do while (file(m:).ne.' ')
m=m+1
enddo
m=m-1
open(1, File = file(1:m),form='formatted')
write (1,*) b
close(1)
end
subroutine iswap1 (file,b1,c1)
implicit none
integer m,b1,c1
character*6 file
m=1
do while (file(m:).ne.' ')
m=m+1
enddo
m=m-1
call iswap(file(1:m)//'.jk',b1)
call iswap(file(1:m)//'.bk',c1)
end
program callex
implicit none
character*6 unit
call iswap1(unit,2,3)
end
I'm trying to write the code that generates two files ".jk" and ".bk", each containing the value 2 and 3. The code I wrote is not not creating any file. Could you please guide me in correcting this code keeping the code format same? The main program calls "iswap1" subroutine, which then calls "iswap2" subroutine that writes values to files with the extension mentioned in "iswap1" subroutine. Thanks!
Here's the code roughly written in idiomatic modern Fortran:
program callex
implicit none
character(len=80) :: fname = "thefile"
call iswap1(fname,2,3)
contains
subroutine iswap (file,b)
implicit none
integer, intent(in) :: b
character(len=*), intent(in) :: file
integer :: unit
open(newunit=unit, File = file ,form='formatted')
write (unit,*) b
close(unit)
end subroutine iswap
subroutine iswap1 (file,b1,c1)
implicit none
integer, intent(in) :: b1,c1
character(len=*), intent(in) :: file
call iswap(trim(file)//'.jk',b1)
call iswap(trim(file)//'.bk',c1)
end subroutine iswap1
end program callex
Some notable changes from your original version:
Use contained procedures to get argument checking.
character variables declared with length per modern syntax.
Initial character variable, fname initialized (and made a bit longer because why not). Also I initialized fname to a non-empty string because otherwise on Unix type systems the generated files will be hidden as the name would start with ..
Dummy character variables declared with len=* meaning they get the length from the caller.
Declare intent for dummy arguments.
Use trim instead of a loop to get rid of trailing spaces.
Use NEWUNIT= when opening units rather than manually allocating unit numbers.
I'm new to Fortran. I was given a file that is supposed to be in Fortran 90, but written to be compiled with the Lahey Fujitsu compiler (the sparse documentation states that it should be compiled with lf95 filename.f -out compiled_name #imsllf95.cmd). However, some lines are commented with c, which as I understand was the way to comment in Fortran 77. Also, matrices are declared like REAL*8, DIMENSION(23,8) :: xxx19, which again I think is from Fortran 77.
For the most part, I can compile the file with gfortran or ifort except for a section that requires the computation of a matrix inverse. Apparently, in the LF95 compiler (using a propietary module IMSLF90), a matrix inverse was computed with .i.. If I delete those inversions, the file compiles and runs with no problem (apart from the fact that it gives the wrong result).
I'm trying to find the version of Fortran this code is written in, so that I can then search for some code written in that same version so that I can invert the matrices in the code.
EDIT: The file has extension .f, even though the compiling instructions seem to imply that it is Fortran 95.
Here I have some sections of the code:
PROGRAM estimate_group
implicit none
INTEGER :: i,j,k,full,group1
REAL*8, DIMENSION(500) :: theta_start,theta_input
OPEN(68, STATUS="REPLACE",file='fit_measures.txt')
c OPEN(68, file='fit_measures.txt')
REWIND(68)
DO full=1,1
PRINT *, "=================================="
PRINT *, "FULL LOOP #: ", full
PRINT *, "=================================="
WRITE(68, *) "=================================="
WRITE(68, *) "FULL LOOP #: ", full
WRITE(68, *) "=================================="
DO group1=2,28
c Additional If statement to focus on top level and scale
c IF ( ((group1>=22) .AND. (group1<=28)) .OR. (group1==2)) THEN
IF ( group1==2) THEN
c READING IN THETA VECTOR FROM PREVIOUS ITERATIONS
c (starting values taken from prior runs theta output)
c ====================================================
IF ((group1==2) .AND. (full==1)) THEN
theta_input=0.0*theta_input
OPEN(67, file='theta_input1.txt')
REWIND(67)
DO i=1,500
READ(67,*) theta_input(i)
END DO
ELSE
theta_input=0.0*theta_input
OPEN(66,file='theta_input.txt')
REWIND(66)
DO i=1,500
READ(66,*) theta_input(i)
END DO
END IF
SUBROUTINE estimate(group1, theta_start)
INTEGER, INTENT(IN) :: group1
REAL*8, INTENT(IN), DIMENSION(500) :: theta_start
c Variable Declarations:\
INTEGER :: i,j,k,m,l,t0,i0,improve,max_m
REAL*8, DIMENSION(23,8) :: xxx19
xxx19(1:23,1) = (/554.0,541.1,583.3,593.2,615.8,582.0,582.5,546.5,
& 538.4,494.1,503.3,494.1,486.9,478.6,432.6,439.6,
& 380.4,355.4,305.9,271.8,254.6,208.8,202.8/)
Real*8 is not part of Fortran, and has never been part of Fortran. So the strict answer to your question is it is not Fortran of any vintage.
However going on what you have shown apart from Real*8 it is Fortran 90 or later. Fixed source form is still part of the language (though I would fail any students I have for using it) so it not an indicator of the vintage of the code. However after a quick look at the above I can see the following features which came into the standard language in Fortran 90:
Mixed case (outside character variables and constants)
Underscore in symbol name
Implicit None
:: in variable declarations and comma separated attribute lists
Variable names longer than 6 characters
Double inverted commas (") to delimit character strings
Do ... End Do (I assume you have missed out the End Do for some reason as otherwise the fragments above make no sense whatsoever)
== to test equality
Intent for dummy arguments
Array sections
Array constructors
There may be others.
This question already has answers here:
Why is the counter variable unexpectedly increased in every subroutine call? [duplicate]
(1 answer)
Does Fortran preserve the value of internal variables through function and subroutine calls?
(3 answers)
Why is there an implied SAVE attribute in Fortran? [duplicate]
(1 answer)
Fortran assignment on declaration and SAVE attribute gotcha
(2 answers)
Closed 4 years ago.
I have the following simple code (which is an example of something I am trying to do in a much more complicated code):
module linkmod
type link
character(len=1) :: name
type(link), pointer :: next => null()
end type link
contains
recursive subroutine tell_name(a)
type(link), target :: a
type(link), pointer :: b !b is useless, except to illustrate my point
integer :: num_outputs = 0
b => a
if (associated(b%next)) call tell_name(b%next)
print *, b%name
num_outputs = num_outputs + 1
print *, num_outputs
end subroutine tell_name
end module linkmod
program driver
use linkmod
type(link) :: a
type(link), pointer :: b
a%name = 'a'
allocate(a%next)
b => a%next
b%name='b'
allocate(b%next)
b => b%next
b%name = 'c'
allocate(b%next)
b => b%next
b%name = 'd'
call tell_name(a)
end program
I compile and run and get the following output:
d
1
c
2
b
3
a
4
Now, I get lucky here because this is the behavior I need, namely, when a call to tell_name() is exited, b in the calling instance has retained the value it had before the calling instance made the call, but num_outputs has been set to what it became in the called instance. (Apologies if that was hard to read. I tried my best there.)
The thing is, I don't really understand why things work this way. Why do not both b and num_outputs retain the values they were assigned in the called instance? Or, alternatively, why do they not both re-acquire the values they had in the calling instance, previous to the call?
What is the general rule here? On the other hand, what if I wanted num_outputs in a calling instance to be unaffected by what happens in any called instance. How would I arrange that?
(BTW, I wrote up an alternative version of the code where I replaced the recursive subroutine with a derived type procedure, called as
call b%next%tell_name()
I get the exact same behavior with it.)
I would like to use deferred-length character strings in a "simple" manner to read user input. The reason that I want to do this is that I do not want to have to declare the size of a character string before knowing how large the user input will be. I know that there are "complicated" ways to do this. For example, the iso_varying_string module can be used: https://www.fortran.com/iso_varying_string.f95. Also, there is a solution here: Fortran Character Input at Undefined Length. However, I was hoping for something as simple, or almost as simple, as the following:
program main
character(len = :), allocatable :: my_string
read(*, '(a)') my_string
write(*,'(a)') my_string
print *, allocated(my_string), len(my_string)
end program
When I run this program, the output is:
./a.out
here is the user input
F 32765
Notice that there is no output from write(*,'(a)') my_string. Why?
Also, my_string has not been allocated. Why?
Why isn't this a simple feature of Fortran? Do other languages have this simple feature? Am I lacking some basic understanding about this issue in general?
vincentjs's answer isn't quite right.
Modern (2003+) Fortran does allow automatic allocation and re-allocation of strings on assignment, so a sequence of statements such as this
character(len=:), allocatable :: string
...
string = 'Hello'
write(*,*)
string = 'my friend'
write(*,*)
string = 'Hello '//string
write(*,*)
is correct and will work as expected and write out 3 strings of different lengths. At least one compiler in widespread use, the Intel Fortran compiler, does not engage 2003 semantics by default so may raise an error on trying to compile this. Refer to the documentation for the setting to use Fortran 2003.
However, this feature is not available when reading a string so you have to resort to the tried and tested (aka old-fashioned if you prefer) approach of declaring a buffer of sufficient size for any input and of then assigning the allocatable variable. Like this:
character(len=long) :: buffer
character(len=:), allocatable :: string
...
read(*,*) buffer
string = trim(buffer)
No, I don't know why the language standard forbids automatic allocation on read, just that it does.
Deferred length character is a Fortran 2003 feature. Note that many of the complicated methods linked to are written against earlier language versions.
With Fortran 2003 support, reading a complete record into a character variable is relatively straight forward. A simple example with very minimal error handling below. Such a procedure only needs to be written once, and can be customized to suit a user's particular requirements.
PROGRAM main
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: INPUT_UNIT
IMPLICIT NONE
CHARACTER(:), ALLOCATABLE :: my_string
CALL read_line(input_unit, my_string)
WRITE (*, "(A)") my_string
PRINT *, ALLOCATED(my_string), LEN(my_string)
CONTAINS
SUBROUTINE read_line(unit, line)
! The unit, connected for formatted input, to read the record from.
INTEGER, INTENT(IN) :: unit
! The contents of the record.
CHARACTER(:), INTENT(OUT), ALLOCATABLE :: line
INTEGER :: stat ! IO statement IOSTAT result.
CHARACTER(256) :: buffer ! Buffer to read a piece of the record.
INTEGER :: size ! Number of characters read from the file.
!***
line = ''
DO
READ (unit, "(A)", ADVANCE='NO', IOSTAT=stat, SIZE=size) buffer
IF (stat > 0) STOP 'Error reading file.'
line = line // buffer(:size)
! An end of record condition or end of file condition stops the loop.
IF (stat < 0) RETURN
END DO
END SUBROUTINE read_line
END PROGRAM main
Deferred length arrays are just that: deferred length. You still need to allocate the size of the array using the allocate statement before you can assign values to it. Once you allocate it, you can't change the size of the array unless you deallocate and then reallocate with a new size. That's why you're getting a debug error.
Fortran does not provide a way to dynamically resize character arrays like the std::string class does in C++, for example. In C++, you could initialize std::string var = "temp", then redefine it to var = "temporary" without any extra work, and this would be valid. This is only possible because the resizing is done behind the scenes by the functions in the std::string class (it doubles the size if the buffer limit is exceeded, which is functionally equivalent to reallocateing with a 2x bigger array).
Practically speaking, the easiest way I've found when dealing with strings in Fortran is to allocate a reasonably large character array that will fit most expected inputs. If the size of the input exceeds the buffer, then simply increase the size of your array by reallocateing with a larger size. Removing trailing white space can be done using trim.
You know that there are "complicated" ways of doing what you want. Rather than address those, I'll answer your first two "why?"s.
Unlike intrinsic assignment a read statement does not have the target variable first allocated to the correct size and type parameters for the thing coming in (if it isn't already like that). Indeed, it is a requirement that the items in an input list be allocated. Fortran 2008, 9.6.3, clearly states:
If an input item or an output item is allocatable, it shall be allocated.
This is the case whether the allocatable variable is a character with deferred length, a variable with other deferred length-type parameters, or an array.
There is another way to declare a character with deferred length: giving it the pointer attribute. This doesn't help you, though, as we also see
If an input item is a pointer, it shall be associated with a definable target ...
Why you have no output from your write statement is related to why you see that the character variable isn't allocated: you haven't followed the requirements of Fortran and so you can't expect the behaviour that isn't specified.
I'll speculate as to why this restriction is here. I see two obvious ways to relax the restriction
allow automatic allocation generally;
allow allocation of a deferred length character.
The second case would be easy:
If an input item or an output item is allocatable, it shall be allocated unless it is a scalar character variable with deferred length.
This, though, is clumsy and such special cases seem against the ethos of the standard as a whole. We'd also need a carefully thought out rule about alloction for this special case.
If we go for the general case for allocation, we'd presumably require that the unallocated effective item is the final effective item in the list:
integer, allocatable :: a(:), b(:)
character(7) :: ifile = '1 2 3 4'
read(ifile,*) a, b
and then we have to worry about
type aaargh(len)
integer, len :: len
integer, dimension(len) :: a, b
end type
type(aaargh), allocatable :: a(:)
character(9) :: ifile = '1 2 3 4 5'
read(ifile,*) a
It gets quite messy very quickly. Which seems like a lot of problems to resolve where there are ways, of varying difficulty, of solving the read problem.
Finally, I'll also note that allocation is possible during a data transfer statement. Although a variable must be allocated (as the rules are now) when appearing in input list components of an allocated variable of derived type needn't be if that effective item is processed by defined input.
NOTE: I'm still investigating this issue - please don't look into it yet - the mistake may be elsewhere
I would like an argument to a subroutine to be OPTIONAL, but that argument also happens to be an assume shape array. When I try to compile the module containing this subroutine, I get the following error:
PGF90-S-0189-Argument number 3 to (routine): association of scalar actual argument to array dummy argument (location)
The routine looks like this:
SUBROUTINE EXAMPLE(A, B, C)
IMPLICIT NONE
INTEGER, INTENT(IN) :: A, B
INTEGER, OPTIONAL, DIMENSION(:), INTENT(IN) :: C
INTEGER :: TEST
IF (PRESENT(C)) THEN
TEST=C(1)
PRINT *,TEST
ELSE
PRINT *,A,B
ENDIF
END SUBROUTINE EXAMPLE
It is contained within a module. I get the error when I try to call it with only two arguments from a subroutine which is USEing the module.
I have only found one possibly related question on the Portland Group forums here:
http://www.pgroup.com/userforum/viewtopic.php?t=624&sid=d76fdf8ca2bf4fc3109f4f49b1de0ad7
The answer boils down to the user using an optional argument which has not been allocated - I don't know if this applies in my case as I'm not using 'C' outside of the IF(PRESENT(C)) block, but could there be an implicit allocation going on when defining a variable as assumed shape, which cannot be carried out when it is not passed in the first place?
This problem is now resolved - you can indeed use assumed shape arrays as optional arguments. As pointed out in the comments - the error stemmed from an old version of a source file which was not being regenerated by a pre-processing step due to a bug. As a result, the call was not what I thought it was - it actually contained a single integer as the third argument.
Thanks for the help all.