I have to create a program that reverses phrases.
For example: when I write hello guys
, I want syug olleh
This is what
@Rook's answer works for odd length of string too? Anyway here's my attempt, inspired by his answer which takes into account trailing blanks too:
! Reverse the string
function reverse_string(string) result(gnirts)
character(len=*) :: string
character(len(string)) :: gnirts
character(1) :: temp
integer :: i, length
length = len(string)
do i = 1,length
gnirts(length-i+1:length-i+1) = string(i:i)
end do
end function reverse_string
One simple way to do it ...
character(80) :: string = "Whatttt's up doc?"
character :: temp
integer :: i, length
write (*,*) string ! Writes it out proper.
length = len_trim(string) ! ignores trailing blanks.
! use len(string) to reverse those as well
do i = 1, length/2
temp = string(i:i)
string(i:i) = string(length+1-i:length+1-i)
string(length+1-i:length+1-i) = temp
end do
write(*,*) string ! Writes it out backwards.
end
Others will come up with more intelligent ones (and shorter) for sure.
Well, of course we want to be able to do this via a constant expression, so we attempt the following:
program reverse
implicit none
character(20), parameter :: input = 'Forward'
integer i
character(len(input)), parameter :: output = &
transfer([(input(i:i),i=len_trim(input),1,-1)],trim(input))
write(*,'("#",a,"#")') input, output
end program reverse
We get the same output with both gfortran and ifort:
#Forward #
#drawroF#
I can't see what I might be doing wrong... is it the same bug in both compilers?
Here's a shorter way to do it:
forall (i=1:len(string)) string(i:i) = string(len(string)-i+1:len(string)-i+1)
It even saves a handful of bytes ! I'm not sure I'd suggest this was more intelligent though.
Unlike arrays, characters don't have advanced ways of selecting "elements": substrings must be contiguous (which in particular excludes "reverse order"). The approaches of other answers here follow from that: using expressions which individually select length-1 substrings to build up a new string. An example would be a simple loop selecting matching substrings.
If we construct an array from individual substrings we can use transfer to put the re-ordered elements back as a string.
Similar to an array constructor implied loop we can use an I/O implied loop with internal write:
implicit none
character(*), parameter :: string = 'abcde'
character(len(string)) :: reverse
integer i
write(reverse,'(*(A))') (string(i:i),i=len(string),1,-1)
write(*,'(A)') string, reverse
end
This approach, however, cannot be used "in-place" (unlike the transfer
one) as the internal file cannot appear in the I/O output item list. An intermediate variable could be used.