When a subprogram takes a string as an argument, we may want to pass strings of different lengths.
module constants integer, parameter :: MAX_CHROMOSOME_LEN = 1000000, & MAX_GENE_LEN = 20000, & MAX_MARKER_LEN = 20 end module program string_subprograms implicit none character(MAX_CHROMOSOME_LEN) :: chrom1, chrom2 character(MAX_GENE_LEN) :: eye_gene1, eye_gene2, hair_gene1 character(MAX_MARKER_LEN) :: start_seq, stop_seq integer :: start_offset, code_offset, stop_offset ... ! Find location of sequences within a chromosome start_offset = locate(chrom1, start_seq) stop_offset = locate(chrom1, stop_seq) code_offset = locate(chrom1, gene_seq) ... end program
Unlike other arrays, it is not necessary to pass the maximum length of a string. We simply define dummy string variables with a * for the size, and the compiler takes care of the rest. The compiler will pass the length of the string to the subprogram for us, and we can retrieve it using len(string), where string is the name of the dummy argument.
subroutine sub(string) character(*) :: string ! Produces the correct length of the string passed in each time print *, len(string) end subroutine
The locate function above can then be implemented as follows:
function locate(big_sequence, sub_sequence) integer :: locate character(*) :: big_sequence, sub_sequence integer :: sub_len character :: trimmed_seq ! Indicate that sub_sequence was not found locate = -1 ! Set locate to index of first match, if found trimmed_seq = trim(sub_sequence) sub_len = len(trimmed_seq) do i = 1, trim_len(big_sequence) if ( big_sequence(i:i+sub_len) == trimmed_seq ) then locate = i exit endif enddo end function