34

How can I read and write to the standard input, output and error streams stdin, stdout and stderr in Fortran? I've heard writing to stderr, for example, used to be write(5, fmt=...), with 5 the unit for stderr, and I know the way to write to stdout is to use write(*, fmt=...).

How do I read and write to the standard input and output units with the ifort compiler?

Compiler version:

Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 10.0 Build 20070426 Package ID: l_fc_p_10.0.023 Copyright (C) 1985-2007 Intel Corporation. All rights reserved

AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173

4 Answers4

43

If you have a Fortran 2003 compiler, the intrinsic module iso_fortran_env defines the variables input_unit, output_unit and error_unit which point to standard in, standard out and standard error respectively.

I tend to use something like

#ifdef f2003
use, intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
                                          stdout=>output_unit, &
                                          stderr=>error_unit
#else
#define stdin  5
#define stdout 6
#define stderr 0
#endif

in my input/output routines. Although this of course means preprocessing your source file (to do this with ifort, use the -fpp flag when compiling your source code or change the source file extension from .f to .F or from .f90 to .F90).

An alternative to this would be to write your own, non-intrinsic, iso_fortran_env module (if you don't have a Fortran 2003 compiler), as discussed here (this link has died since this answer was posted). In this example they use a module:

module iso_fortran_env

  ! Nonintrinsic version for Lahey/Fujitsu Fortran for Linux. 
  ! See Subclause 13.8.2 of the Fortran 2003 standard. 

  implicit NONE 
  public 

  integer, parameter :: Character_Storage_Size = 8 
  integer, parameter :: Error_Unit = 0 
  integer, parameter :: File_Storage_Size = 8 
  integer, parameter :: Input_Unit = 5 
  integer, parameter :: IOSTAT_END = -1 
  integer, parameter :: IOSTAT_EOR = -2 
  integer, parameter :: Numeric_Storage_Size = 32 
  integer, parameter :: Output_Unit = 6 

end module iso_fortran_env

As noted in other answers, 0, 5 and 6 are usually stderr, stdin and stdout (this is true for ifort on Linux) but this is not defined by the Fortran standard. Using the iso_fortran_env module is the correct way to portably write to these units.

Chris
  • 44,602
  • 16
  • 137
  • 156
  • Unfortunately I don't have a 2003 compatible compiler; I'm in fortran 90. – AncientSwordRage Dec 14 '11 at 18:56
  • 1
    @Pureferret So you can just use one of the alternative methods which I suggest. Also recent `ifort` versions support parts of the 2003 standard including `iso_fortran_env`. – Chris Dec 15 '11 at 09:05
  • I tried this and it didn't work, the compiler said everything in your first block was 'bad preprocessor syntax' (I think) I haven't tried your second block yet, but if @tpg2114's solution doesn't work, I'm not sure why/how your solution would work. – AncientSwordRage Dec 15 '11 at 23:01
  • As I said in my answer you need to preprocess the file (the `#`'s are [preprocessor directives](http://en.wikipedia.org/wiki/C_preprocessor)) and make sure that the #'s appear in the first column. With the intel compiler this mean using the `-fpp` flag when compiling your source files. The second example avoids having to do this, but you should check that the the values used match those of your compiler/machine. – Chris Dec 16 '11 at 09:13
  • Right. I had no idea what pre-processing was. It seems to work now. – AncientSwordRage Dec 16 '11 at 09:20
  • 3
    @Pureferret Glad to hear it works. Pre-processing can be very useful, although I don't see it used in Fortran codes that often. – Chris Dec 16 '11 at 09:37
  • 4
    You can also change the extension of your file. If it is .F or .F90 instead of .f or .f90, then the compiler will pre-process it for you without an special flags. – tpg2114 Dec 16 '11 at 11:10
  • I was trying this approach but isn't it `stdin=>input_unit` and so on ? Just for correction. – bela83 Apr 27 '15 at 13:27
  • 1
    @bela83 Thanks for pointing that out. I have corrected my answer. I'm amazed that no one else has mentioned this before. – Chris May 06 '15 at 07:08
  • 1
    @Chris your link "preprocessing" has died. As it seems to be a fairly important part of the answer, please consider finding a new source to link to. – River Aug 11 '15 at 18:26
  • @Chris nobody mentioned it because nobody is using Fortran 2003 yet...? – astrojuanlu Nov 26 '15 at 09:24
  • @Juanlu001 I hope that isn't the case - this is 2015! I hope we don't have to wait the best part of a decade before a standard starts to become used. I was certainly using some 2003 features back in 2008, hopefully I'm not the only person. – Chris Nov 26 '15 at 09:42
17

The Fortran standard doesn't specify which units numbers correspond to stdin/out/err. The usual convention, followed by e.g. gfortran, is that stderr=0, stdin=5, stdout=6.

If your compiler supports the F2003 ISO_FORTRAN_ENV intrinsic module, that module contains the constants INPUT_UNIT, OUTPUT_UNIT, and ERROR_UNIT allowing the programmer to portably retrieve the unit numbers for the preconnected units.

janneb
  • 36,249
  • 2
  • 81
  • 97
10

It's actually 0 for stderr. 5 is stdin, 6 is stdout.

For example:

PROGRAM TEST
  WRITE(0,*) "Error"
  WRITE(6,*) "Good"
END PROGRAM TEST

Gives:

./a.out 
Error
Good

while

./a.out 2> /dev/null
Good

I would store a PARAMETER that is STDERR = 0 to make it portable, so if you hit a platform that is different you can just change the parameter.

This example was compiled and run with ifort 12.1.1.256, 11.1.069, 11.1.072 and 11.1.073.

gauteh
  • 16,435
  • 4
  • 30
  • 34
tpg2114
  • 14,112
  • 6
  • 42
  • 57
  • 1
    I just tried it with 4 different versions of ifort and it works, and it also works with gfortran 4.6.0, 4.6.1 and 4.6.2. Can you post what errors it gives you? – tpg2114 Dec 15 '11 at 23:07
  • It doesn't give me any errors using `write(0,*)` but when I re-direct stderr to file, nothing happens. The version is: Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 10.0 Build 20070426 Package ID: l_fc_p_10.0.023 Copyright (C) 1985-2007 Intel Corporation. All rights reserved. – AncientSwordRage Dec 16 '11 at 09:05
  • 1
    This is compiler specific. There is no guarantee in the Fortran 9 standard that those numbers be 0,5 and 6. – Vladimir F Героям слава Oct 06 '17 at 21:17
3

The standard way to write to stdout in Fortran is to put an asterisk instead of the unit number, i.e.,

WRITE(*,fmt) something

or to simply use

PRINT fmt,something

Similarly, the standard way to read from stdin is

READ(*,fmt) something

There is no standard way to write to stderr unless you use ERROR_UNIT from the ISO_FORTRAN_ENV module, which requires Fortran 2003 or later.

Unit numbers 0, 5 and 6 will certainly work in the ifort compiler (and also in some other Fortran compilers), but keep in mind they are compiler-dependent.