Array of Strings in Fortran 77
Asked Answered
O

4

7

I've a question about Fortran 77 and I've not been able to find a solution.

I'm trying to store an array of strings defined as the following:

character matname(255)*255

Which is an array of 255 strings of length 255.

Later I read the list of names from a file and I set the content of the array like this:

matname(matcount) = mname

EDIT: Actually mname value is hardcoded as mname = 'AIR' of type character*255, it is a parameter of a function matadd() which executes the previous line. But this is only for testing, in the future it will be read from a file.

Later on I want to print it with:

write(*,*) matname(matidx)

But it seems to print all the 255 characters, it prints the string I assigned and a lot of garbage.

  • So that is my question, how can I know the length of the string stored?
  • Should I have another array with all the lengths?
  • And how can I know the length of the string read?

Thanks.

Ohaus answered 7/4, 2009 at 12:32 Comment(0)
E
4

The function Timotei posted will give you the length of the string as long as the part of the string you are interested in only contains spaces, which, if you are assigning the values in the program should be true as FORTRAN is supposed to initialize the variables to be empty and for characters that means a space.

However, if you are reading in from a file you might pick up other control characters at the end of the lines (particularly carriage return and/or line feed characters, \r and/or \n depending on your OS). You should also toss those out in the function to get the correct string length. Otherwise you could get some funny print statements as those characters are printed as well.

Here is my version of the function that checks for alternate white space characters at the end besides spaces.

  function strlen(st)
  integer           i,strlen
  character         st*(*)
  i = len(st)
  do while ((st(i:i).eq.' ').or.(st(i:i).eq.'\r').or.
 +  (st(i:i).eq.'\n').or.(st(i:i).eq.'\t'))
    i = i - 1
  enddo
  strlen = i
  return
  end

If there are other characters in the "garbage" section this still won't work completely.

Assuming that it does work for your data, however, you can then change your write statement to look like this:

write(*,*) matname(matidx)(1:strlen(matname(matidx)))

and it will print out just the actual string.

As to whether or not you should use another array to hold the lengths of the string, that is up to you. the strlen() function is O(n) whereas looking up the length in a table is O(1). If you find yourself computing the lengths of these static strings often, it may improve performance to compute the length once when they are read in, store them in an array and look them up if you need them. However, if you don't notice the slowdown, I wouldn't worry about it.

Epitasis answered 7/4, 2009 at 16:35 Comment(1)
I had to modify the type definition of the function receiving the string as parameter to: character mname*(*). Before, the end of that variable was random garbage, now it is padded with spaces. Thanks for the explanation, was very clarifying. Also I didn't know about the * notation.Ohaus
Z
5

You can use this function to get the length (without blank tail)

integer function strlen(st)
      integer       i
      character     st*(*)
      i = len(st)
      do while (st(i:i) .eq. ' ')
        i = i - 1
      enddo
      strlen = i
      return
      end

Got from here: http://www.ibiblio.org/pub/languages/fortran/ch2-13.html

PS: When you say: matname(matidx) it gets the whole string(256) chars... so that is your string plus blanks or garbage

Zohar answered 7/4, 2009 at 12:37 Comment(1)
Thank you too, I would like to vote you but I still don't have enough reputation.Ohaus
E
4

The function Timotei posted will give you the length of the string as long as the part of the string you are interested in only contains spaces, which, if you are assigning the values in the program should be true as FORTRAN is supposed to initialize the variables to be empty and for characters that means a space.

However, if you are reading in from a file you might pick up other control characters at the end of the lines (particularly carriage return and/or line feed characters, \r and/or \n depending on your OS). You should also toss those out in the function to get the correct string length. Otherwise you could get some funny print statements as those characters are printed as well.

Here is my version of the function that checks for alternate white space characters at the end besides spaces.

  function strlen(st)
  integer           i,strlen
  character         st*(*)
  i = len(st)
  do while ((st(i:i).eq.' ').or.(st(i:i).eq.'\r').or.
 +  (st(i:i).eq.'\n').or.(st(i:i).eq.'\t'))
    i = i - 1
  enddo
  strlen = i
  return
  end

If there are other characters in the "garbage" section this still won't work completely.

Assuming that it does work for your data, however, you can then change your write statement to look like this:

write(*,*) matname(matidx)(1:strlen(matname(matidx)))

and it will print out just the actual string.

As to whether or not you should use another array to hold the lengths of the string, that is up to you. the strlen() function is O(n) whereas looking up the length in a table is O(1). If you find yourself computing the lengths of these static strings often, it may improve performance to compute the length once when they are read in, store them in an array and look them up if you need them. However, if you don't notice the slowdown, I wouldn't worry about it.

Epitasis answered 7/4, 2009 at 16:35 Comment(1)
I had to modify the type definition of the function receiving the string as parameter to: character mname*(*). Before, the end of that variable was random garbage, now it is padded with spaces. Thanks for the explanation, was very clarifying. Also I didn't know about the * notation.Ohaus
P
1

Depending on the compiler that you are using, you may be able to use the trim() intrinsic function to remove any leading/trailing spaces from a string, then process it as you normally would, i.e.

character(len=25) :: my_string
my_string = 'AIR'
write (*,*) ':', trim(my_string), ':'

should print :AIR:.

Edit: Better yet, it looks like there is a len_trim() function that returns the length of a string after it has been trimmed.

Primarily answered 7/4, 2009 at 19:27 Comment(0)
C
0

intel and Compaq Visual Fortran have the intrinsic function LEN_TRIM(STRING) which returns the length without trailing blanks or spaces.

If you want to suppress leading blanks or spaces, use "Adjust Left" i.e. ADJUSTF(STRING)

In these FORTRANs I also note a useful feature: If you pass a string in to a function or subroutine as an argument, and inside the subroutine it is declared as CHARACTER*(*), then using the LEN(STRING) function in the subroutine retruns the actual string length passed in, and not the length of the string as declared in the calling program.

Example: CHARACTER*1000 STRING

        .
        .

  CALL SUBNAM(STRING(1:72)

  SUBROUTINE SYBNAM(STRING)
  CHARACTER*(*) STRING
  LEN(STRING) will be 72, not 1000
Cottar answered 18/6, 2013 at 3:15 Comment(1)
Using a structure for the string, and the Length of it, sometimes makes sense.Penchant

© 2022 - 2024 — McMap. All rights reserved.