# Allocation of array for reading strings from a text file

**URL:** <https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986>\
**Category:** Help\
**Created:** [June 16, 2023, 5:54pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986 "2023-06-16T17:54:11Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 16, 2023, 5:54pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/1 "2023-06-16T17:54:11Z")

</div>

I want to fill an array with strings of varying lengths, while keeping the array’s length fixed. These strings are the entries of a text file. Since I fill this array element by element while traversing the text file line by line, I don’t have any prior information regarding the longest string or the number of elements. The solution I have in mind is to iterate through all the elements to determine their total number and find the longest string. Then, I will allocate the array. Afterward, I will revisit the text file and fill MyArray accordingly. However, this approach has the drawback of requiring two passes through the text file (which can become time-consuming if one deals with long text files). I am uncertain if there is an alternative approach where I can simultaneously read the text file, fill the array, and adjust the length to accommodate the maximum length found so far (comparing the current element with the previous elements). So the question is whether my approach is efficient and if not, what is the alternative?

So, for the approach in my mind, an example would be:

```auto
program allocate_array
  implicit none
  
  character(len=:), allocatable :: myArray(:)
  character(100) :: tempString
  integer :: temp_strLen
  integer :: numElements, maxLength, i, iostatus

  ! Open the file
  open(1, file="input.txt", status="old", action="read")

  ! Initialize variables
  numElements = 0
  maxLength = 0
  i = 1
  ! Read the file and determine the maximum length and number of elements
  do
    read(1, '(A)', iostat=iostatus) tempString
    if (iostatus < 0) exit
    print*, 'line(', i, ') = ', tempString
    i = i + 1
    numElements = numElements + 1
    maxLength = max(maxLength, len(trim(tempString)))
 end do
 
  print*, 'maxLength = ', maxLength 
  ! Allocate the array with the maximum length
  allocate(character(len=maxLength) :: myArray(numElements))
  
  ! Rewind the file to the beginning
  rewind(1)

  ! Read the file again and fill the array
  do i = 1, numElements
     read(1, '(A)') tempString
     temp_strLen = len(trim(tempString))
     myArray(i)(1:temp_strLen) = tempString(1:temp_strLen) 
  end do

  ! Close the file
  close(1)

  ! Print the array
  do i = 1, numElements
    print*, myArray(i)
  end do
  
end program allocate_array

```

with input.text containing:

```auto
a
ab
abcd
abc
de

```

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [June 16, 2023, 6:19pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/2 "2023-06-16T18:19:28Z")

</div>

You could read the entire text file into a string using unformatted stream, as done in the code below, and then use the positions of the newlines to determine the length of the longest line.

```auto
program read_file_into_string
implicit none
character (len=*), parameter :: fname = "file.txt"
integer :: i,ipos,iu,len_text
integer, parameter :: n = 10
character (len=:), allocatable :: text
open (newunit=iu,file=fname,action="read")
inquire(unit=iu,size=len_text) ! get file size
close (iu)
! allocate string large enough to hold file if possible
allocate (character (len=len_text) :: text)
open (newunit=iu,file=fname,action="read", &
      form="unformatted",access="stream")
read (iu) text ! read file into variable text
ipos = index(text,new_line("")) ! pos of first newline
print "('first line: ',a)","'" // text(1:ipos-1) // "'"
! find position of next-to-last newline character in text
ipos = index(text(:len_text-1),new_line(""),back=.true.)
print "('last line: ',a)", &
      "'" // text(ipos+1:len_text-1) // "'"
end program read_file_into_string

```

Storing the text you gave in file.txt and running, the output is

```auto
first line: 'a'
last line: 'de'

```

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [June 16, 2023, 8:03pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/3 "2023-06-16T20:03:51Z")

</div>

This is the kind of common operation that should be part of standard fortran, but it isn’t.

One workaround is to read the strings one by one and put them into a linked list. The members of the linked list can be allocated upon demand. When the linked list is complete, the array can be allocated to the correct size, the data copied from the linked list to the array, and the linked list can be deallocated.

That is basically what the fortran i/o library is doing already anyway, so when a programmer does this, it is duplicating effort that was already done.

---

<div class="post-metadata">

**Author:** ![Harper](https://avatars.discourse-cdn.com/v4/letter/h/b5ac83/32.png) [@Harper](https://fortran-lang.discourse.group/u/Harper)\
**Post date:** [June 16, 2023, 11:23pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/4 "2023-06-16T23:23:50Z")

</div>

Thank you @Beliavsky. One very minor remark: the line

```auto
integer, parameter :: n = 10

```

was superfluous. Without that line the program still compiled, ran and gave the same output with gfortran and ifort.

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [June 17, 2023, 1:38pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/5 "2023-06-17T13:38:13Z")

</div>

Instead of using an allocatable array of deferred length strings which you would have to eventually allocate to a fixed length, I think it would be better to put the deferred len string in a derived type and allocate that to the number of lines of text.

ie.

```auto
type :: vlstring_t
  character(len=:), allocatable :: string
end type
integer :: iun, nrecs, istat
type(vlstring_t), allocatable :: text_file(:)
character(len=132) :: buffer
character(len=1) :: dummy
open(newunit=iun, file="yourfile.txt", form="formatted", status="unknown")
! count number of records (note you don't have to read the line of text just the first char)
nrecs = 0
count_loop: do
    read(iun, '(a1)', iostat=istat) dummy
    if (istat /= 0) exit count_loop
    nrecs = nrecs+1
 end do count_loop

allocate(text_file(nrecs))
rewind(iun)
read_loop: do i=1,nrecs
    buffer=repeat(" ", 132)
    read(iun,'(a)', iostat=istat) buffer
    if (istat /= 0) then
      print *,' error while reading text file'
      exit read_loop
    end if
   text_file(i)%string = trim(buffer)
end do read_loop
close(iun)

```

I’ve been using this code fragment to read text files ever since deferred length string became a thing in Fortran. This has the advantage of taking up less memory than allocating the deferred length string to a fixed length. Note that counting the number of lines by just reading the first character of a record is an old trick I’ve seen in Fortran code for many years. I’m not sure if it’s faster than reading the entire line (with modern compilers) but I think it was in the old days.  
Also, you probably don’t want to use 1 for a unit number. Using the newunit option on open is a much better approach.

Edit: It just occured to me that having an option for the INQUIRE statement that returns the number of records (lines of text) in a formatted text file would be a Good Thing. You can get file size in “storage units” but I don’t think that translates to records of variable length. Maybe something to consider for Fortran 2200.

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 17, 2023, 2:24pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/6 "2023-06-17T14:24:13Z")

</div>

Thank you very much, @Beliavsky. I didn’t know that the entire text could be read into a string.  
I have two questions:

- Is it possible that while reading the text, we ignore lines starting with # (comments) or put the lines starting with special characters into another string?

- in your code, len\_text gives the size of the file and not the number of lines. So, “text” is ONE string, please correct me if I am mistaken. Is it possible to have information about the number of lines (and possibly lines starting without special characters such as #) in the first part of the code (lines 7-10 in your code) and then declare :

```auto
allocate (character (len=len_text) :: text(numElemenrts) )

```

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 17, 2023, 2:25pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/7 "2023-06-17T14:25:30Z")

</div>

Thanks @RonShepard. I am not familiar with “linked list”. I will search for it.

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 17, 2023, 2:56pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/8 "2023-06-17T14:56:37Z")

</div>

Thanks @rwmsu for your answer. It gives me lots of insights.  
Could you please let me know if my understanding of your code is correct?  
So, you define

```auto
type :: vlstring_t
  character(len=:), allocatable :: string
end type

type(vlstring_t), allocatable :: text_file(:)

```

Is this equivalent to the following:

```auto
  character(len=:), allocatable :: myArray(:)

```

so when you write:

```auto
text_file(i)%string == trim(buffer)

```

without doing

```auto
allocate(character(len= **maxLength** ) :: text_file(nrecs))

```

Does it mean that each array of text\_file has a different length? or it somehow does something as

```auto
maxLength = max(maxLength, len(trim(tempString)))

```

at runtime?

PS: I am grateful that both you and @Beliavsky have shown me another way to use the unit number. It has always been annoying for me to ensure that the same unit is not used twice in the code

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [June 17, 2023, 3:23pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/9 "2023-06-17T15:23:58Z")

</div>

@mary,

```auto
character(:), allocatable :: string(:)

```

is not equivalent to embedding a single deferred length string in a derived type. All Fortran arrays  
irrespecitve of type must have a fixed length or dimension(s). In your approach you would have to eventually do a

```auto
allocate(character(len=maxlen) :: strings(nrecs))

```

in other words you can’t have a Fortran array with variable length dimensions (sometimes called a ragged array). In your approach you would eventually have an array of size nrecs with each array component of length maxlen. If your text files has records that vary for one character per line to 132 characters per line you are wasteing a lot of memory if you have several thousand lines of text. Basically with your approach you are ending up with an array that is equivalent to doing

```auto
character(len=maxlen) :: strings(maxsize) ! where maxlen and maxsize are set to some fixed values. 

```

By embedding the string in a derived type array, you have an true array in which each component has a variable length (at the expense of having to deal with derived type syntax). You now have a array that mirrors the way the text is stored in the file. ie. the length of each line of text is the same as in the text file. Note this is also why you can’t have an array of pointers in Fortran and have to do a similar approach (embedding in a derived type).

I have proposed in the past a syntax that would allow you to do what you are trying to do using curly brackets to signal an array like object with variable size storage of components.

ie.

```auto
character(len=:), allocatable :: strings{:}

```

that would effectively do the same thing as the derived type but this proposal has been met with resounding silence.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [June 17, 2023, 4:56pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/10 "2023-06-17T16:56:49Z")

</div>

> [@rwmsu](#):
>
> Note that counting the number of lines by just reading the first character of a record is an old trick I’ve seen in Fortran code for many years. I’m not sure if it’s faster than reading the entire line (with modern compilers) but I think it was in the old days.

One does not need to read even a single character from each line. Just the statement `read(iun, '(a)', iostat=istat)` is enough to skip to the next record and to set `istat` correctly when the end-of-file has been reached. In fact, if there are embedded empty records, then attempting to read a single character might trigger an end-of-record condition, so that situation would be treated differently with the two approaches. In any case, testing for `istat < 0` would narrow the termination conditions to just the end-of-file case.

> [@mary](#):
>
> Is it possible that while reading the text, we ignore lines starting with # (comments) or put the lines starting with special characters into another string?

Yes, once you have read the line (or the full file), you can parse it any way you want. You can have zero, one, or multiple outputs for each input line.

If you do read the full file into a string, then there might be some nonportable machine-dependence involved in how the end-of-records are identified. Maybe someone with more experience with Windows operating systems can fill in the details. Specifically, on POSIX machines with POSIX file systems, an end-of-record is identified by a single newline character, which in fortran is given by the intrinsic function `new_line(c)` where `c` is a character of the correct KIND. This covers linux, MacOS, SunOS, BSD, and any other unix-based or unix-like computer system. However, Microsoft operating systems, including the various MS-DOS and Windows versions, use instead a two-character sequence `<charriage-return><new-line>` to designate end of records. I believe a fortran i/o library can either read that two-character sequence into memory or it can convert it into the one-character sequence. This gotcha only involves the case where you use stream access to read the full file into memory. If you read the lines one at a time with the usual formatted i/o, then the fortran i/o library handles things correctly on any operating system. I also do not know what happens if you are running on a POSIX machine, but you are reading a nonstandard file system (e.g. a Windows file mounted over a network), or visa versa. One would need to read the standard very closely to see what is supposed to happen in these cases, and then there is also the possibility that the fortran i/o library does not handle everything consistently.

So I might suggest that the more portable approach might be to read the lines one at a time, but I have little experience with Microsoft operating systems, so I’m not certain about these potential problems. Maybe others can fill in these details.

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [June 17, 2023, 5:18pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/11 "2023-06-17T17:18:34Z")

</div>

@RonShepard ,

One can also test against the intrinsic parameters iostat\_end and iostat\_eor in iso\_fortran\_env but like a lot of new Fortran features I forget they exist and resort to old (and sometimes bad) habits.

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 18, 2023, 12:58am UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/12 "2023-06-18T00:58:56Z")

</div>

@rwmsu Thank you very much for your explanation. Now, everything is clear to me.

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 18, 2023, 1:12am UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/13 "2023-06-18T01:12:02Z")

</div>

Thanks a lot, @RonShepard for your response. I thought maybe in “inquire”, there might be an option that can automatically identify lines starting with or without some characters. Otherwise, I think that I can identify those lines by using “index”.

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 18, 2023, 2:22am UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/14 "2023-06-18T02:22:49Z")

</div>

I tried to replace the last part of your code with following:

```auto
  do while (.not. end_file)
     ipos = index(text(i_start:len_text),new_line("")) ! pos of first newline
     if (ipos == 0) then
        end_file = .true.
     else
        print*, 'line(', i, ') = ', text(i_start:i_start+ipos-1)
        i_start = ipos + 1
        i = i + 1
     end if
  end do

```

with the following variables declared at the beginning of the program:

```auto
  integer :: i_start = 1, i = 1
  logical :: end_file = .false. 

```

But it ends up in an infinite loop, and it prints only the first line.  
So, I assume that I did not fully understand how this new\_line is working.  
In the text file:

```auto
a
ab
abcd
abc
de

```

So, this means that the text variable in Fortran is not considered as a" “ab” “abcd” “abc” "de. Is my understanding correct?

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [June 18, 2023, 2:40am UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/15 "2023-06-18T02:40:22Z")

</div>

To say what the “best” method is depends on whether you are reading from stdin or just  
files, whether you need to operate on the data before hitting EOF, what the biggest file  
is you need to read, and how many times you need to do it. That being said, here is  
one self-contained example. A bit long, but it is extracted from something relatively  
general.

Note that a simple but perhaps non-obvious way to handle files like stdin you cannot  
read twice is to write it into a Fortran scratch file so you have an actual file you can rewind  
and read multiple times; one of the few things not mentioned so far that can be useful  
depending on the method you use. For small files I often do not need to know the original  
line lengths and for simplicity just read everything into an array of standard strings.

Here is a module that defines a procedure called fileread() that works for simple cases  
where that is OK. There are several Open Source versions of routines that do this using  
various methods. This one is a cut-down version of one  
from [General Purpose Fortran](https://urbanjost.github.io/general-purpose-fortran/man3.html).

If you use fpm(1) you can just use that or the module [M\_io](https://urbanjost.github.io/M_io/man3.html).

An abridged version that is a self-contained module that creates the readfile(3f) procedure:

> **M\_slurp module**
>
> ```fortran
> MODULE M_slurp
> use, intrinsic :: iso_fortran_env, only : stdin=>input_unit, stdout=>output_unit, stderr=>error_unit
> implicit none
> private
> public fileread
> integer,parameter,private:: sp=kind(1.0), dp=kind(1.0d0)
> 
> character(len=*),parameter,private :: gen='(*(g0,1x))'
> 
> CONTAINS
> 
> subroutine fileread(FILENAME,pageout)
> implicit none
> character(*),intent(in) :: FILENAME ! file to read
> character(len=:),allocatable,intent(out) :: pageout(:) ! page to hold file in memory
> character(len=1),allocatable :: text(:) ! array to hold file in memory
> 
> call filebyte(FILENAME,text) ! allocate character array and copy file into it
> 
> if(.not.allocated(text))then
> write(*,*)'*fileread* failed to load file '//FILENAME
> else ! convert array of characters to array of lines
> pageout=page(text)
> deallocate(text) ! release memory
> endif
> 
> contains
> function page(array) result (table)
> 
> !@(#) page(3fp): function to copy char array to page of text
> 
> character(len=1),intent(in) :: array(:)
> character(len=:),allocatable :: table(:)
> integer :: i
> integer :: linelength
> integer :: length
> integer :: lines
> integer :: linecount
> integer :: position
> integer :: sz
> character(len=1),parameter :: nl = char(10)
> character(len=1),parameter :: cr = char(13)
> lines = 0
> linelength = 0
> length = 0
> sz=size(array)
> do i = 1,sz
> if( array(i) == nl )then
> linelength = max(linelength,length)
> lines = lines + 1
> length = 0
> else
> length = length + 1
> endif
> enddo
> if( sz > 0 )then
> if( array(sz) /= nl )then
> lines = lines+1
> endif
> endif
> 
> if(allocated(table))deallocate(table)
> allocate(character(len=linelength) :: table(lines))
> table(:) = ' '
> 
> linecount = 1
> position = 1
> do i = 1,sz
> if( array(i) == nl )then
> linecount=linecount+1
> position=1
> elseif( array(i) == cr )then
> elseif( linelength /= 0 )then
> table(linecount)(position:position) = array(i)
> position = position+1
> endif
> enddo
> end function page
> end subroutine fileread
> 
> subroutine filebyte(filename,text,length,lines)
> implicit none
> 
> !@(#) M_slurp::filebyte(3f): allocate text array and read file filename into it
> 
> character(*),intent(in) :: filename ! filename to shlep
> character(len=1),allocatable,intent(out) :: text(:) ! array to hold file
> integer,intent(out),optional :: length ! length of longest line
> integer,intent(out),optional :: lines ! number of lines
> integer :: nchars=0 ! holds size of file
> integer :: igetunit ! use newunit=igetunit in f08
> integer :: ios=0 ! used for I/O error status
> integer :: length_local
> integer :: lines_local
> integer :: i
> integer :: icount
> character(len=256) :: message
> character(len=4096) :: label
> character(len=:),allocatable :: line
> length_local=0
> lines_local=0
> message=''
> open(newunit=igetunit, file=trim(filename), action="read", iomsg=message,&
> &form="unformatted", access="stream",status='old',iostat=ios)
> label=filename
> if(ios == 0)then ! if file was successfully opened
> inquire(unit=igetunit, size=nchars)
> if(nchars <= 0)then
> call stderr_local( '*filebyte* empty file '//trim(label) )
> return
> endif
> ! read file into text array
> if(allocated(text))deallocate(text) ! make sure text array not allocated
> allocate ( text(nchars) ) ! make enough storage to hold file
> read(igetunit,iostat=ios,iomsg=message) text ! load input file -> text array
> if(ios /= 0)then
> call stderr_local( '*filebyte* bad read of '//trim(label)//':'//trim(message) )
> endif
> else
> call stderr_local('*filebyte* '//message)
> allocate ( text(0) ) ! make enough storage to hold file
> endif
> 
> close(iostat=ios,unit=igetunit) ! close if opened successfully or not
> 
> if(present(lines).or.present(length))then ! get length of longest line and number of lines
> icount=0
> do i=1,nchars
> if(text(i) == NEW_LINE('A'))then
> lines_local=lines_local+1
> length_local=max(length_local,icount)
> icount=0
> endif
> icount=icount+1
> enddo
> if(nchars /= 0)then
> if(text(nchars) /= NEW_LINE('A'))then
> lines_local=lines_local+1
> length_local=max(length_local,icount)
> endif
> endif
> if(present(lines))lines=lines_local
> if(present(length))length=length_local
> endif
> end subroutine filebyte
> 
> subroutine stderr_local(message)
> character(len=*) :: message
> write(stderr,'(a)')trim(message) ! write message to standard error
> end subroutine stderr_local
> 
> end module M_slurp
> 
> ```

A little program to test the module reads the file “testin” in and prints the  
lines surrounded with braces and then removes lines beginning with “#”;  
except I either made a typo or hit a gfortran bug (works with ifx):kkkkkk

```fortran
program testit
use M_slurp, only : fileread
implicit none
character(len=:),allocatable :: pageout(:) ! page to hold file in memory
integer :: i
logical,allocatable :: keep(:)

   call fileread('testin',pageout)

   write(*,*)'write file enclosed in braces'
   write(*,*)'size=',size(pageout),',len=',len(pageout)
   write(*,'(*(g0))')('[',trim(pageout(i)),']',new_line('A'),i=1,size(pageout))

   ! remove lines starting with "#"
   ! A bug inn gfortran? works with ifx
   keep=index(adjustl(pageout),'#').ne.1
   pageout=pack(pageout,keep)

   write(*,*)'remove lines starting with "#"'
   write(*,*)'size=',size(pageout),',len=',len(pageout)
   write(*,'(*(i5,": ",a,/))')(i,trim(pageout(i)),i=1,size(pageout))

end program testit

```

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [June 18, 2023, 4:41am UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/16 "2023-06-18T04:41:35Z")

</div>

> [@mary](#):
>
> But it ends up in an infinite loop,

I think the problem is how you are using the `index()` function. You will need something like the following:

> [@mary](#):
>
> `ipos = index(text(i_start:len_text),new_line('a'))`  
> […]  
> `print*, 'line(', i, ') = ', text(i_start:i_start+ipos-1)`

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 18, 2023, 2:06pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/17 "2023-06-18T14:06:18Z")

</div>

Thanks @RonShepard. But, I have the same issue when I replace “`ipos = index(text(i_start:len_text),new_line(""))`” by “`ipos = index(text(i_start:len_text),new_line('a'))`”.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [June 18, 2023, 5:08pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/18 "2023-06-18T17:08:26Z")

</div>

I think you might have missed the important part of my correction.

> [@mary](#):
>
> print\*, ‘line(’, i, ') = ', text(i\_start:i\_start+ipos-1)

The `index()` function returns the position within its dummy argument of the located character. The returned value is not the position within the original character string.

If you examine the values of `i_start` and `ipos` before the print statement, you will see this.

The other change, which you did notice, was the argument to the `new_line()` intrinsic function. I know absolutely for certain that `new_line('a')` works because that is the example given in the standard document itself. It is unclear to me if a null string (a zero length string) is an acceptable argument. I can see some reasons that it should work, since even a null string has a KIND value, but the standard document does not explicitly state that as being allowed, so I think it is safer to use a nonnull string as the argument. BTW, you can also use `achar(10)` as that argument in a portable way if your compiler uses ascii as its default KIND (which all compilers I know of right now do) or if the ascii `<newline>` character is mapped to the equivalent local character. Of all fortran compilers, the chances are probably 99.99% that one or the other of those conditions is true.

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 19, 2023, 3:17pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/19 "2023-06-19T15:17:09Z")

</div>

> [@mary](#):
>
> `print*, 'line(', i, ') = ', text(i_start:i_start+ipos-1)`

Thank you, @RonShepard. I corrected this part of the code, but I still encountered a problem. As you mentioned, the issue was that the value returned by `index()` was relative to the dummy argument and not the original string. Below, I am sharing the corrected version in case someone else makes the same mistake and is looking for a solution:

```auto
  do while (ipos.ne.0)
     ipos = index(text(i_start:len_text),new_line("")) ! note that ipos is relative to (i_start:len_text) and not absolute
     if (ipos == 0) exit
     print*, 'ipos = ', ipos
     print*, 'line(', i, ') = ', text(i_start:i_start+ipos-1)
     i = i + 1
     i_start = ipos + i_start ! istart is an absolute-value w.r.t to the entire original text
  end do

```

---

<div class="post-metadata">

**Author:** ![mary](https://avatars.discourse-cdn.com/v4/letter/m/e99b99/32.png) [@mary](https://fortran-lang.discourse.group/u/mary)\
**Post date:** [June 19, 2023, 3:18pm UTC](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986/20 "2023-06-19T15:18:14Z")

</div>

Thank you @urbanjost . I am going to study the solution you proposed.

[Next page](https://fortran-lang.discourse.group/t/allocation-of-array-for-reading-strings-from-a-text-file/5986.md?page=2)
