Reputation: 31
My goal is to print out the string when it is defined. First of all, my code is:
program test
use, intrinsic :: iso_fortran_env, only : stderr=>error_unit
implicit none
character(len=1024) :: file_update
write (stderr, '(a)') 'file-update: '//file_update
end program test
When I run the above code, the output is:
file-update: �UdG��tdG�|gCG��m�F� dCG� ��3���3�P��3��UdG� �eG���eG�1
DG��UdG���g��<�CG�U��B�jdG�DG����3����3��cCG����3��dCG�<�CG����3������jdG�DG�0fCG�<�CG�0��F���G��G����F�pdG�1
DG�XmdG��pdG�ȡeG�0��F�p��3�XsdG����3����F��G����F��G��pdG�1
DG�XmdG��pdG�ȡeG�0��F�p��3�XsdG����3��7�G�
which means the variable file_update
is not defined.
What I want to achieve is add an if...else...
condition to judge if the string file_update
is defined or not.
program test
use, intrinsic :: iso_fortran_env, only : stderr=>error_unit
implicit none
character(len=1024) :: file_update
if (file_update is defined) then
write (stderr, '(a)') 'file-update: '//file_update
else
write (stderr, '(a)') 'file-update: not defined'
end if
end program test
How can I achieve this?
Upvotes: 3
Views: 216
Reputation: 32451
There is no way within a Fortran program to test whether an arbitrary variable is undefined. It is entirely the programmer's responsibility to ensure that undefined variables are not referenced.1 Recall that "being undefined" or "becoming undefined" doesn't mean that there is a specific value or state we can test against.
You may be able to find a code analysis tool which helps2 you in your assurance but still it remains your problem to write Fortran correctly.
How do you carefully write code to ensure you haven't referenced something you haven't defined?
Your compiler may be able to help, with certain options, by initializing variables to requested sentinel values for you, automatically.
Let's look at the specific case of the question. Here, we have a character variable we want to use.
As a programmer we know we haven't yet given it a value by the time we reach the point we want to use it. We could give it an initial value which is a sentinel:
character(len=1024) :: file_update = ""
or assign such a sentinel value early on:
character(len=1024) :: file_update
file_update = ""
Then when we come to look at using the value we check it:
if (file_update=="") then
error stop "Oops"
end if
(Beware such initialization in the first use here when there may be a second run through this part of code. Initialization is applied exactly once: initially.)
Which brings us to the first point above. What defines a variable? As a Fortran programmer you need to know this. Consider the program:
implicit none
character(255) name
read *, name
print *, name
end
When we reach the print
statement, we've defined the name
variable, right? We asked the user for a value, we got one and defined name
with it, surely?
Nope.
We possibly did, but we can't guarantee that. We can't ask the compiler whether we did.
Equally, you must know what undefines a variable. There are easy cases, such as a dummy argument which is intent(out)
, but less obvious cases. In
print *, F(Z) + A
for F
a function then perhaps Z
becomes undefined as a result of this statement. It's your responsibility to know whether that happens, not the compiler's. There is no way in Fortran to ask whether Z
became undefined.
The Fortran standard tells you what causes a variable to become defined or undefined, to always be defined, or to be initially defined or undefined. In Fortran 2018 that's 19.6.
Which, finally, brings me to the final point: allocatable variables. You can always (ignoring the mistakes of Fortran 90) ask whether an allocatable variable is allocated:
implicit none
character(:), allocatable :: name
! Lots of things, maybe including the next line
name = "somefile"
if (.not.allocated(name)) error stop "No name given"
...
Scalars can be allocatable, and their allocation status can be queried to determine whether the variable is allocated or not. An allocatable variable can be allocated but not defined, but using an allocatable variable covers many of those cases where a non-allocatable variable would be undefined by having an allocation status we can query: an allocatable variable is initially not allocated, becomes not allocated when associated with an intent(out)
dummy, and so on.
1 A variable being undefined because "you haven't given it a value yet since the program started" is an easy case. However, a lot of the times a variable becomes undefined, instead of being initially undefined, relate to making the compiler's life easier or allowing optimizations: placing a requirement to detect and respond to such cases is counter to that.
2 No tool can detect all cases of referencing an undefined variable for every possible program.
Upvotes: 3