4

I'm trying to output a trivial error message in Fortran90, like so:

error: failed to read '<file>'

But I cannot figure out how to produce the single quotes, escaping them leads to compilation errors. I have tried the following:

write(*, fmt="('error: failed to read: \'', a, '\'')") arg

Also, if I print the message without them:

write(*, fmt="('error: failed to read: ', a)") file

an extra newline (i.e. two in total) is produced on the command line. I obtain arg by executing call getarg(1, arg), maybe that has something to do with it.

Here is a minimal working example which demonstrates the newline problem:

program foo                                                        
    character(len=100) :: arg

    call getarg(1, arg)

    write(*, fmt="('error: failed to read: ', a)") arg
end program foo

I find formatted output in fortran to be very unintuitive, if someone could additionally direct me to a resource that explains this in more detail that would be great.

Peter
  • 2,919
  • 1
  • 16
  • 35
  • Please give an example of how you call the compiled program and how the output looks: it could simply be that your terminal is introducing line wrapping. There is nothing in your final example which should have a "newline problem". – francescalus Nov 05 '18 at 06:19

2 Answers2

5

It is much better, in my opinion, to not enter the printed strings into the format, as you do in C, but rather put them into the output list.

I also recommend to trim the filename trim(arg) when printing it, so that you do not print around 90 useless trailing blanks.

program foo
    implicit none                                                        
    character(len=100) :: arg

    call getarg(1, arg)

    write(*, '(*(a))') "error: failed to read: '", trim(arg), "'"
end program foo

That way you do not need one outer layer of quotes that quote the format string itself.

Even inside any string you can repeat a quote to put it into the string, i.e. '''' (see Difference between double and single quotation marks in fortran?)

BTW, standard Fortran 2003 has subroutine GET_COMMAND_ARGUMENT instead of GETARG.

2

In case you wish to remain close to your original example, here is a summary of the three fixes. I also made use of an allocatable character variable, for information [and because I like the feature :-) ]. You can pick the fixes independently.

program foo
  ! always use implicit none at the beginning of a program
  implicit none
  ! use an allocatable character variable. The length can be specified later
  character(len=:), allocatable :: arg
  ! you need a variable to store the length of the argument
  integer :: arg_len

  ! obtain the length of the argument
  call get_command_argument(1, length=arg_len)
  ! allocate the character variable. the length is passed by the type definition of the
  ! allocate statement
  allocate(character(len=arg_len) :: arg)
  ! actually read the argument, finally!
  call get_command_argument(1, value=arg)

  ! the double quotes *inside* the string generate a single quote character
  ! the trim is not necessary here, as the character variable has the appropriate
  ! length. keep it if you stick to a fixed length character variable.
  write(*, fmt="('error: failed to read: ''', a, '''')") trim(arg)

end program foo
Pierre de Buyl
  • 7,074
  • 2
  • 16
  • 22