1

I am trying to write a code where I want to read a variable (Delta), and based on that I am trying to copy the corresponding file (TESTDIR/Delta0.5_DOS_2D_TBM.data DOS.data for Delta=0.5) to the present directory.

        Program Modify_variable_based_file
        character(LEN=100):: command
        character(LEN=10):: chDelta
        real*8:: Delta

        Print*,'Enter Delta'
        Read*,Delta

        write(chDelta,'(f0.1)') Delta
        print*,'chDelta=',chDelta,' Delta=',Delta

        command='cp TESTDIR/Delta' // trim(adjustl(chDelta)) //'_DOS_2D_TBM.data DOS.data'
        call system(command)

        End Program Modify_variable_based_file

However, I can see chDelta is .5 instead of 0.5 when I input Delta. Can you suggest me the correct format? And is there an alternative where I can avoid the string conversion?

Note that here my files are named with number having the most significant digit on the left of the decimal, i.e. if it Delta is 1.5, file is Delta1.5_DOS_2D_TBM.data. Zero arises before the decimal only when there are no other significant digits.

hbaromega
  • 2,317
  • 2
  • 24
  • 32
  • So you want `chDelta` to be "0.5" when `Delta` is 0.5? – Ross Sep 18 '15 at 18:25
  • Isn't it simpler to read 0.5 as a character string (chDelta) and, if necessary, read Delta from chDelta using internal file...? – roygvib Sep 18 '15 at 18:34
  • @Ross, yes I do want so. @roygvib, no that's not possible, there are large number of files, which are generated by running a loop over a variable, `0.5` is a typical example. – hbaromega Sep 18 '15 at 18:39
  • We need more examples, then. What if it's 0.25? – Ross Sep 18 '15 at 18:55
  • 1
    So your question is actually this: http://stackoverflow.com/q/17886390/577108 ? – haraldkl Sep 18 '15 at 20:27
  • @haraldkl, I am afraid it is not. @Ross, the program should take the input as it is. If it is `0.25`, the file it should look for is `TESTDIR/Delta0.25_DOS_2D_TBM.data`. If it is `00.25`, the file should be `TESTDIR/Delta00.25_DOS_2D_TBM.data`. If there's no such format, which allows this, I'll be left with no choice than reading input as a `string`. But I don't know about the options right now. – hbaromega Sep 19 '15 at 13:53
  • 1
    I'm confused. If delta is of type real (p.s. real*8 isn't Fortran) how can you expect to distinguish between 0.25 and 00.25 and indeed 0.250 and 00.250 as, for a real number, they are all the same thing? – Ian Bush Sep 19 '15 at 14:09
  • @IanBush, now I understand the problem (why did you say "real*8 isn't Fortran?") . So unless it's a string, the program cannot retain it's format. So either I should make it a string (suggested by roygvib or use extra padding for 0 in the left (suggested by heraldkl). – hbaromega Sep 19 '15 at 14:39
  • So I have done the following modification: `command='cp TESTDIR/Delta0' // trim(adjustl(chDelta)) //'_DOS_2D_TBM.data DOS.data'`. Let me know if the question sounds poor. I'll delete then. Thanks all. – hbaromega Sep 19 '15 at 14:46
  • @roygvib I have updated my question a bit. – hbaromega Sep 19 '15 at 16:22

1 Answers1

1

If you need only one digit after the decimal point, you can use f20.1 etc such that

character(LEN=100) :: chDelta    !! use a sufficiently large buffer

write( chDelta,'(f20.1)' ) Delta
chDelta = adjustL( chDelta )

Then the chDelta corresponding to Delta=0.5 becomes "0.5" (note that adjustL() removes all the blanks before 0). Similarly, you can retain 4 digits by using the format

write( chDelta,'(f20.4)' ) Delta

which gives chDelta = "0.5000". To obtain a flexible number of nonzero digits after the decimal point, we may need to remove unnecessary zeros manually. This can be done, for example, by searching for the last nonzero digit and removing the trailing zeros.

real*8 x( 5 )
character(100) str

x(:) = [ 1.0d0, 0.2d0, 1.23d0, -123.456d0, 123.678901d0 ]

do i = 1, 5
    write( str, "(f20.4)" ) x(i)
    call truncate( str, 4 )
    print *, "file", trim(str), ".dat"
enddo
...

subroutine truncate( str, dmax )
    implicit none
    character(*), intent(inout) :: str
    integer,      intent(in)    :: dmax   !! maximum number of nonzero digits
    integer :: dot, k, last

    str = adjustL( str )
    dot = index( str, '.' )

    do k = dot + dmax, dot, -1
        if ( str( k:k ) /= '0' ) then
            last = k
            exit
        endif
    enddo
    if ( last == dot ) last = last + 1   !! retain at least one digit

    str = str( 1:last )
end

Then the output becomes

file1.0.dat
file0.2.dat
file1.23.dat
file-123.456.dat
file123.6789.dat
roygvib
  • 7,218
  • 2
  • 19
  • 36
  • Thanks @roygvib, actually `adjustl` is already there in `command`, so I may not need to do it, but `f20.1` is definitely a correct format for `0.5`. And you have provided a very generic solution, that's truly useful. :) – hbaromega Sep 20 '15 at 19:51
  • Nice if it worked :) Although I tried G format as well, it didn't work either (for example, g0.1 gives ".5" for 0.5). So the conversion is a bit awkward... Cheers – roygvib Sep 21 '15 at 03:37