character(len=16) :: str, tmpStr
len_trim(str) == 0 - does not work, if string is all blanks then
len_trim(str)=len(str)=16
str == "" - does not work
str == " " - does not work
tmpStr = adjustl(str)
tmpStr =="" - does not work
tmpStr ==" " - does not work
tmpStr(1:1) == "" -does not work
tmpStr(1:1) == " " - does not work
So how do i check if the string is empty?
Thanks!
> Hi,
> I have an array of strings, some of them can be empty (all blanks). I
> would like test which ones are not empty but i don't know how. I'm
> using Intel fortran (F90), and i tried following:
>
> character(len=16) :: str, tmpStr
>
> len_trim(str) == 0 - does not work, if string is all blanks then
> len_trim(str)=len(str)=16
> str == "" - does not work
> str == " " - does not work
The usual way to check if a character variable contains all blanks is
str == " "
so you will need to define "does not work" as well as why you believe that
the contents are really all blanks. Showing a real program that runs
will be of the essence. Without it you will only collect a variety
of off the wall speculations about what errors you might be making somewhere
else in your program. This is a Fortran newsgroup and not a mindreading
newsgroup. Particularly before folks have had their first morning coffee!
The many times repeated advice is that since you are asking a question
you are unsure of something. The odds are that you are not even sure of
what does not work so you description of what does not work "doesn't work"
either. Show the "does not work" rather than giving a defective description
of it.
> tmpStr = adjustl(str)
> tmpStr =="" - does not work
> tmpStr ==" " - does not work
> tmpStr(1:1) == "" -does not work
> tmpStr(1:1) == " " - does not work
>
> So how do i check if the string is empty?
> Thanks!
See above. Empty is not a useful notion in Fortran character variables
as they are always "full" and of their fixed declared length. You can
only test their contents.
Well, the problem is i do not know if the string array I receive in my
subroutine is initialized or not (actually it is not), and i have to
be able to deal with it if it is not initialized. I made some test and
found out the problem are uninitialized strings.
> Showing a real program that runs
> will be of the essence.
Ok, in brief:
program test_for_blank_strings
character(len=16) :: str(3)
str(1)=" "
str(2)=""
do i=1,3
print*, "i= ",i," BEGIN:",str(i),":END len=",len(str(i)), &
", len_trim=",len_trim(str(i))
if ( str(i)=="" ) print*, "Empty 1"
if ( str(i)==" ") print*, "Empty 2"
if ( str(i)(1:1)=="") print*, "Empty 3"
if ( str(i)(1:1)==" ") print*, "Empty 4"
end do
end
Output (check i=3 case):
i=1 BEGIN: :END len=16 , len_trim=0
Empty 1
Empty 2
Empty 3
Empty 4
i=2 BEGIN: :END len=16 , len_trim=0
Empty 1
Empty 2
Empty 3
Empty 4
i=3 BEGIN::END len=16 , len_trim=16
> This is a Fortran newsgroup and not a mindreading
> newsgroup. Particularly before folks have had their first morning coffee!
>
Well, my targeted audience were those who already had their morning
coffee :)
> See above. Empty is not a useful notion in Fortran character variables
> as they are always "full" and of their fixed declared length. You can
> only test their contents.
I am fully aware of that, the problem is that i have no (or lets say
hardly any) control over the string array that gets in my subroutine
and i have to handle it.
Thanks,
Luksa
-|Hi,
-|I have an array of strings, some of them can be empty (all blanks). I
-|would like test which ones are not empty but i don't know how. I'm
-|using Intel fortran (F90), and i tried following:
-|
-|character(len=16) :: str, tmpStr
-|
-|len_trim(str) == 0 - does not work, if string is all blanks then
-|len_trim(str)=len(str)=16
-|str == "" - does not work
-|str == " " - does not work
-|
-|tmpStr = adjustl(str)
-|tmpStr =="" - does not work
-|tmpStr ==" " - does not work
-|tmpStr(1:1) == "" -does not work
-|tmpStr(1:1) == " " - does not work
-|
-|So how do i check if the string is empty?
-|Thanks!
Here is a working example. output is: Check for null worked.
Skip Knoble
character(len=100) ch
ch = ' '
if (trim(ch)=='') then
write(*,*) "Check for null worked."
else
write(*,*) "Check for null did not work."
end if
end
This is how I interpret your question, but I may be wrong:
implicit none ! all variables must be
typed
character(len = 3), dimension(10) :: c ! an array of 'strings'
integer :: i
c = ' ' ! all 'strings' set to
blank
do i = 1, 10, 2
c(i) = 'abc' ! odd 'strings' set to
something
end do
do i = 1, 10
if(c(i) == ' ') then
print *, 'blank for i = ', i
else
print *, c(i), ' for i = ', i
end if
end do
end
Regards,
Mike Metcalf
In your program string 3 is not initialised, that means it
probably contains nul characters (or other rubbish), not
spaces/blanks. This means that as far as Fortran is concerned
it is not equal to ' '.
Regards,
Arjen (who has had plenty of coffee, at the end of a long day)
You have just learned that this uninitialized character variable
did not have all blanks (in this version of this compiler on this run)
or even a blank in character 1. The contents may be garbage from the
compiler and never change (unless you get a new version) or they may
change with each execution. It depends!
In general you are on your own as the Fortran standard does not even
support testing the variable if it has not yet received a value.
You might test to see if all characters are printing characters but
that will only eliminnate utter garbage. You would still accept ordinary
garbage!
>> This is a Fortran newsgroup and not a mindreading
>> newsgroup. Particularly before folks have had their first morning coffee!
>>
> Well, my targeted audience were those who already had their morning
> coffee :)
>
>> See above. Empty is not a useful notion in Fortran character variables
>> as they are always "full" and of their fixed declared length. You can
>> only test their contents.
>
> I am fully aware of that, the problem is that i have no (or lets say
> hardly any) control over the string array that gets in my subroutine
> and i have to handle it.
It needs to be set to a known default with all blanks high on the list.
> Thanks,
> Luksa
str(1)=" " ! sets str(1)(1:) to blank and then blank-fills (2:16)
str(2)="" ! does nothing and blank-fills (1:16)
Note that an unitialized string will almost cetainly contain some
random values, as shown by your str(3). You cannot set a string to
'null'.
Regards,
Mike Metcalf
Thank you all.
Luksa
> Note that an unitialized string will almost cetainly contain some
> random values, as shown by your str(3). You cannot set a string to
> 'null'.
A true "missing value" indicator would come in handy in Fortran, but I would
not expect the Fortran standard to mandate one or to specify what that
indicator might be!
Sentinel values, such as -99999 are one solution, except when it becomes
valid. For example 9/9/99 as a "never expires" date triggered year 2000
bugs.
Once upon a time I worked on a machine that had minus zero as an integer.
This did come in handy to "hack" in "missing" values while doing some
statistical analysis. Not portable :-).
- e
You are not correct. The Intel compiler version did "print" something,
it printed the "non-display" character NULL (ASCII(0))
>
> Thank you all.
> Luksa
> On Nov 19, 4:22 pm, Gordon Sande <g.sa...@worldnet.att.net> wrote:
> > On 2008-11-19 11:04:44 -0400, Luksa <klu...@gmail.com> said:
> >
> > You have just learned that this uninitialized character variable
> > did not have all blanks
> >
> And that Intel fortran prints nothing if i try to print an
> uninitialized string.
I wouldn't count on it printing nothing. That part is not the corect
lesson to learn.
Doing anything that tries to reference the value of an uninitialized
variable is nonstanard and can produce almost any result. That is
"illegal" code of a type which the compiler is not required to diagnose
and is allowed to do anything with. The result need not be consistent
from run to run; it could well depend on "aparently "strange" things. It
could also cause a program abort. (There are compilers where that
happens). Printing and testing the value are both references that this
applies to. Just because it printed nothing in the cases you checked,
that does not mean it necessarily wil in general.
By the way, in addition to all the other comments, note that len_trim
should indeed give you the expected result of 0 if the string is all
blank (but, as noted, uninitialized doesn't mean blank). I'd say that
the test to see if the string equals blank was more intuitive, but the
len_trim one shoudl work in that case.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
> Well, the problem is i do not know if the string array I receive in my
> subroutine is initialized or not (actually it is not), and i have to
> be able to deal with it if it is not initialized. I made some test and
> found out the problem are uninitialized strings.
Patient: Doctor, it really hurts when I do this.
Doctor: Well, don't do that.
Fortran does not have the ability to determine if most variables
have been initialized ("defined" I think is the term used in the
standard), and in many cases, it is illegal for the programmer to
reference (e.g. to use in an expression) such a variable. Character
variables are like this. Variables can also become undefined even
after they have been defined, and it is illegal to reference the
variables in this state too.
If you are writing library routines intended to be used by others in
their programs, then it is legitimate for you to require that all
necessary variables (e.g. intent(in) and intent(inout) if you are
declaring intent explicitly) be defined upon entry to your routine.
$.02 -Ron Shepard
> A true "missing value" indicator would come in handy in Fortran, but I
> would not expect the Fortran standard to mandate one or to specify what
> that indicator might be!
There is one in f03 for strings: arrange things such that the input
string has allocatable length. The not allocated, allocated to zero
length, and allocated and set to "" or even repeat(achar(0),len(string))
are all different and distinguishable states.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
> On Nov 19, 4:22 pm, Gordon Sande <g.sa...@worldnet.att.net> wrote:
>> On 2008-11-19 11:04:44 -0400, Luksa <klu...@gmail.com> said:
>>
>> You have just learned that this uninitialized character variable
>> did not have all blanks
>>
> And that Intel fortran prints nothing if i try to print an
> uninitialized string. I realized this only after i made the example
> program with string enclosed between BEGIN: and :END. Gfortran at
> least print rubbish,
Different rubbish that was nonprinting is a more technically correct
statement. Since you have a nonstandard (nonconforming is better) program
then anything that you care to say might be true. Some are more useful for
real programs. All you really know is that different compilers produce
different uninitialized states.
> but Intel no.
> Well, now the mystery is solved.
>
> Thank you all.
> Luksa
Or maybe it prints a series of nonprinting characters or even blanks.
Try marking the beginning and end of the ouput with quotes of some sort.
It is hard to tell one nonprinting character from another with only
printed output. See any definition of nonprinting!
You might also try printing with a Z format to see the native contents.
> Once upon a time I worked on a machine that had minus zero as an
> integer. This did come in handy to "hack" in "missing" values while
> doing some statistical analysis. Not portable :-).
While machines with INTEGER negative zero are rare, those
with floating point negative zero are not.
Fortran 2003 has some support for negative zero for REAL data.
See the SIGN function, for example.
"Case (iv): If B is of type real and is zero, then
(1) If the processor cannot distinguish between positive
and negative real zero, the value of the result is |A|.
(2) If B is positive real zero, the value of the result is |A|.
(3) If B is negative real zero, the value of the result is -|A|.
Many systems did this before the standard included it, by just
copying the sign bit from one place to another.
-- glen
I just corrected (or changed, whichever way you view this) my
Fortran interface to SQLite (http://flibs.sf.net): I use a derived
type to retrieve the columns from a database table and not all
fields are routinely set by a user.
So, the change in the definition of the derived type now causes
all fields to be initialised.
That is a partial solution to the above problem: use derived
types if possible and set initial values for their components.
Regards,
Arjen
It may have been possible to see this by writing the results to a file instead of the screen. Then, if you are lucky, you may have a file-editor that will display ASCII(0) differently from blanks. Or a utility that shows file-contents in hex might have helped.
David Jones
Darn it, I never did get to use this for SQLite...couldn't get approval
to install SQLite without finding budget for >IT< to test it for
compatibility and security issues.
snip
>
> Regards,
>
> Arjen
>
--
Gary Scott
mailto:garylscott@sbcglobal dot net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
most decent editors have a means of displaying record contents in hex or
octal. I find that an essential feature in an editor.
>
> David Jones
Oh good grief, SQLite is among the best tested software in the
field of databases, what more do they need?
(That does not imply that my interface is tested to the same
degree, mind you)
Regards,
Arjen
You're assuming there must be some rational logic behind Corporate IT
practices.
--
JB
No, if the string is all blanks, LEN_TRIM(str) = 0.
LEN(str) is 16 always.
> str == "" - does not work
> str == " " - does not work
>
> tmpStr = adjustl(str)
> tmpStr =="" - does not work
> tmpStr ==" " - does not work
> tmpStr(1:1) == "" -does not work
> tmpStr(1:1) == " " - does not work
>
> So how do i check if the string is empty?
If you want to test whether the string contains all blanks,
you need
if (str == ' ') then ...
>Well, the problem is i do not know if the string array I receive in my
>subroutine is initialized or not (actually it is not), and i have to
>be able to deal with it if it is not initialized. I made some test and
>found out the problem are uninitialized strings.
A string will not be initialuzed unless you initialize it first.
Only then can you test for its being all blanks.
May I suggest adding permanent diagnostics for bad strings to your
subroutine(s)? It sounds like your application context would warrant
the minor effort and save future frustration.
Okay, the following generalizes on what you have above. This checks for
four simple kinds of problems. cmin, cmax are processor dependent but
should work well in most modern ascii-based contexts. Customize as
needed.
charcater c*1
integer len2, i, cval
integer, parameter :: cmin=33, cmax=126
if (len (str) == 0) then <null string error>
len2 = len_trim (str)
if (len2 == 0) then <blank string error>
do i = 1, len2
c = str(i:i)
cval = ichar (c)
if (c == ' ') then
<leading or embedded blank error>
if (cval < cmin .or. cval > cmax) then
<invalid character error>
end do
Caveat, what Gordon Sande said:
> ... You might test to see if all characters are
> printing characters but that will only eliminnate
> utter garbage. You would still accept ordinary
> garbage!
But the above four tests will probably catch the vast majority of bad
inputs over time for you and your clients, including the real cause of
your initial complaint. HTH.
--Dave
> A string will not be initialuzed unless you initialize it first.
> Only then can you test for its being all blanks.
Depending on the implementation, it might also be possible to
initialize strings, either to blanks or (better) to an invalid
value.
gfortran has the -finit-character=xxx option for this.
That seems like a quite bad thing to do in about 99.9 percent of the
cases I can imagine (but I'm not especially imaginative). What are
some of the "recommended" uses for this? (recommended meaning not
otherwise considered bad programming practice)
>>gfortran has the -finit-character=xxx option for this.
> That seems like a quite bad thing to do in about 99.9 percent of the
> cases I can imagine (but I'm not especially imaginative). What are
> some of the "recommended" uses for this? (recommended meaning not
> otherwise considered bad programming practice)
Most likely since they have one for integer and real, it makes
sense to have one for character, too.
For real you can initialize to NaN, which is nice.
For integer, initialize to a large negative value that isn't
likely to be used in your program. It will likely cause bad
things to happen, which you can then fix.
For character, it isn't so obvious what to set it to.
-- glen
subroutine print_what (n)
character(len=3) :: static
character(len=n) :: automatic(n)
print *, static !gives xxx the first time
print *, automatic(1) !gives ?
static = 'yyy'
automatic = 'zzz'
end
Dick Hendrickson
1) Yes, a string must be initialised before you can decide how you
will test it for being "empty".
For example, you have to initialise the string which will contain the
name of a file, to all blanks, before you can partially fill it from
the left, with the characters of the name to be used, and have the
operating system be able to match this file name. Having a mixture of
blanks and binary zeroes in the last part of the string will not work.
2) Testing for a leading blank is not good enough if a (non-file name)
string starts with any blanks.
3) You should not rely on comparing an n-length string with a another
blank string unless you specify an equal length string portion to
compare with using the (1:n) override.
4) in more recent Fortran compilers, you can asiign the string to a
new variable while using the intrinsic function TRIM, to test if the
resulting string is equal to '' (nul).
Safer and easier to FIRST initialise all character string variables
either directly, or with a DATA statement, or by direct input of data.
So essentially as a means of checking for programming errors
(unitialized variables)?
I mostly wouldn't recommend it.
I certainly would *NEVER* recommend it as being a way to make sure
strings are initialized to anything valid (such as blanks). Programs
just should not be written to depend on that. No way. Besides being
nonstandard and nonportable, it is a clear invitation to being sloppy in
ways that will cause other problems as well.... To the extent that it
pretty much isn't worth me making the disrecommendation, because odds
are that anyone who intentionally codes with practices like that isn't
going to pay much attention to any of my recommendations anyway.
Even the excuse of making old code work isn't going to "fly" very well,
as this mostly wouldn't have worked in old code anyway. Having compilers
that essentially initialized data to all zeros was common enough, but
initializing character data to blanks is not. Much more likely would be
that the character data also got initialized to binary zeros.
The only use I could see countenancing would be as a debugging aid. And
note that having the Fortran code check for such a flag value in normal
operation doesn't count as such debugging. That would count as making
the Fortran code nonstandard, since it would involve testing the value
of undefined variables.
But alas, even as a debugging aid, it has the problem that there aren't
any "invalid" values for type character in typica implementations. All
256 bit patterns are valid and are reasonably likely to be used in some
programs. They aren't all printable, but that doesn't make them invalid.
> 3) You should not rely on comparing an n-length string with a another
> blank string unless you specify an equal length string portion to
> compare with using the (1:n) override.
Unless I misunderstand what you are saying, that is perfectly standard
and has been so since string type was introduced into the language. I
don't recall ever running into a compiler that failed to do it
correctly.
> 4) in more recent Fortran compilers, you can asiign the string to a
> new variable while using the intrinsic function TRIM, to test if the
> resulting string is equal to '' (nul).
I'm not sure I am correctly parsing what you are trying to say there,
but it sounds incorrect. Using TRIM in conjunction with assignment to a
new variable mostly has no effect at all because of the semantics of
character assignment; it won't get you a null string. If x and y are
character variables, then
x = trim(y)
has *EXACTLY* the same effect as
x = y
There are no exceptions prior to f2003, and the exception in f2003 seems
to be one of the features that pretty much nobody has yet implemented. I
haven't quite figured out why that particular feature is so slow in
getting implemented. It is a really useful feature, and it doesn't seem
to me as hard as some of the other slow-to-come things (notably
paramterized derived types). The feature in question is
allocatable-length strings.
I think the only recommended use is for debug some sloppy written and
often old code; it is possibly not the most useful option for this but
it can help finding bugs. -finit-local-zero is the arguably more
useful option for old code - and new code should not even rely on to-
zero initialized integers.
(On the other hand, there are programmers which happily code such that
it only works (by change) with a single compiler and ignore all
diagnostic/debugging options offered by the compiler; in this regard
I'm not sure whether this option is not too powerful for such
programmers.)
> I certainly would *NEVER* recommend it as being a way to make sure
> strings are initialized to anything valid (such as blanks). Programs
> just should not be written to depend on that. No way.
I fully agree, especially for new code.
> But alas, even as a debugging aid, it has the problem that there aren't
> any "invalid" values for type character in typica implementations. All
> 256 bit patterns are valid and are reasonably likely to be used in some
> programs. They aren't all printable, but that doesn't make them invalid.
Well, in a normal program characters such as § appear quite rarely
which I would count as "invalid" character for all practical use. If
your program uses §, you can probably find another printable character
which is (almost) never used in your program. I don't recommend using
non-printable characters as they make debugger harder than needed.
Regarding valid values: "-huge()" for integers or "NaN" for real/
complex numbers are also useful. They can also appear for valid
reasons, but still they can help with debugging a code.
Tobias
PS: I have not used those options a lot; the NaN initialization I
found most useful, even though initializing with signaling NaN does
not work yet in gfortran; if it did, I think I'd use the option even
more frequently.
I wouldn't say so rare. It is somewhat common to encrypt strings and
limiting the encryption algorithim to only "valid" ascii printing
values is often not desirable for good encryption security. Yes its
non-standard, but security doesn't always care about that sort of
thing.
That's more like a debug aid, and is not something portable.
You would not use that instead of some form of initialization
within the Fortran code.
I've been bitten by "-huge()"; "+huge()" is much better choice...
To see why:
DO i=1,AnUninitializedInt(j)
iarray(i) = 42
END DO
The C debug run-time library initialized the heap to 0xCDCDCDCD,
which is negative (and close enough to -huge())... AnUninitializedInt(j)
had that value, but in the debugger, the problem didn't show up.
Sure enough, the crash occurred only when the release version of
the program was run outside of the debugger :-D
--
Jugoslav
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.