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
- 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
- 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.