Console Input/Output

Programs that cannot read input data and write their results to some medium are of little use. We have used print * but there is much more to input/output.

Console Input/Output

Most operating systems have some type of console. Output written to the console appears as text on a terminal or equivalent. Geany opens a window for console output when a program is executed.

The console in Fortran can be represented with an asterisk *. In Unix this corresponds to the standard input stream for reading, and the standard output for writing. For standard error a file must be associated with it.

Input/output commands can be list directed, where the compiler handles the spacing and other aspects of the appearance of the output, or the programmer can explicitly format the output.

List-Directed Read/Write from/to the Console

Fortran read from the console. Values may be separated by commas or whitespace:

READ(*,*) var1, var2, var3

READ requires the unit identifier as the first option; here the * indicates console input. The second option must indicate how to format the output, with * telling the compiler to make its own choices. READ can take additional options to check for errors and perform other housekeeping tasks.

IOSTAT=ios 

Returns status into the integer variable ios. If the result is zero, the statement succeeded, otherwise it failed. Specific nonzero values are system-dependent.

IOMSG=msg 

For IOMSG the specific error message will vary by compiler, and no standard length is specified, but a declared length of 128 should be enough. Use the trim intrinsic to print it more legibly.

ERR=label   !Jump to label on error
END=label   !Jump to label on end of file 
EOR=label   !Jump to label on end-of-record (line) (nonadvancing READ only)

Fortran WRITE to the console:

WRITE(*,*) var1,var2,var3

As for READ, the first option to WRITE is the unit identifier and the second is a format descriptor. The asterisk as the format argument specifies a list-directed write in which the compiler formats the output based on its defaults.

WRITE has optional arguments for error checking similar to READ: IOSTAT, IOMSG, and ERR. It also has some optional arguments to control certain aspect of the output appearance, particularly those related to differences in conventional representation of numbers, for example:

DECIMAL=dec

where dec is a character variable or literal that evaluates to COMMA or POINT. This controls whether floating-point numbers are printed with a comma or decimal point.

The PRINT statement always writes to the console (standard output for Unix). The asterisk specifies list-directed IO.

PRINT *, var1,var2,var3

In Fortran the PRINT statement always writes an end-of-line marker after all variables have been output. The WRITE statement does as well, unless told otherwise. This is the opposite of the behavior of write in most other languages.

Example

program console_io
implicit none
real   ::  x,y

   write(*,*) "Please enter a number."
   read(*,*)  x
   write(*,*) "Please enter another number."
   read(*,*)  y

   print *, "The product of your numbers is ",x*y
   write(*,*,decimal='COMMA') "European style:",x*y

end program

Reading from the Command Line

Input values can be read from the command line. This is usually accomplished in an IDE through an option to Run.

We can read strings only. You must convert if necessary to a numerical type using internal read/write. See the discussion earlier.

The COMMAND_ARGUMENT_COUNT intrinsic returns the number of command-line options. For each one, we must call GET_COMMAND_ARGUMENT with its number and a character buffer variable.

   nargs=command_argument_count()
   if (nargs .ne. 1 ) then
      stop "No input specified"
   else
      call get_command_argument(1,nval)
      read(nval,'(i4)') n
      call get_command_argument(2,mval)
      read(mval,'(i4)') m
   endif

Example:

program console_io
implicit none
character(len=15) :: xvar, yvar
real              ::  x,y
integer           :: nargs

   nargs=command_argument_count()
   if (nargs .ne. 2) then
      stop "Too few arguments."
   else
      call get_command_argument(1,xvar)
      call get_command_argument(2,yvar)
   endif

   read(xvar,'(f15.8)') x
   read(yvar,'(f15.8)') y

   print *, "The product of your numbers is ",x*y
   write(*,*,decimal='COMMA') "European style:",x*y

end program

Exercises

  1. In an “infinite” while loop: Request an integer from the user with non-advancing input/output, e.g. “Please enter an integer:” If the integer is 1, print “zebra”. If it is 2, print “kangaroo”. If it is anything else except for zero, print “not found”. If it is 0, exit the loop.
Example Solution

program get_animal
implicit none

   integer          :: ans
   character(len=8) :: text

   do 
      write(*,*) "Please enter a digit 1 or 2, or 0 to exit:"
      read(*,*) ans

      if (ans==0) then
         exit
      else if (ans==1) then
         print *, "zebra"
      else if (ans==2) then
         print *, "kangaroo"
      else
         print *, "not found"
      endif
   enddo

end program

  1. Write a program that takes a string as the command-line argument. Print the string to standard output. Use trim or any other string operators or function s to make the output neat. If you read a string from the command line you do not have to do any conversion of the variable.
Example Solution

program read_arg
implicit none

   integer            :: nargs
   character(len=80)  :: infile

   nargs=command_argument_count()
   if (nargs .lt. 1) then
      stop "No file name specified"
   else
      call get_command_argument(1,infile)
   endif

   write(*,'(a,a)') "You entered a file name ",trim(infile) 

end program


Previous
Next