Strings as Subprogram Arguments

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