READ(,)和WRITE(,)中,两个的意义:
第一个
:该处的数据域指明从哪个输入/输出单元(I/O单元)读入/输出数据;
第二个:该处的数据域指明读入数据的格式。
*Fortran控制字符

控制字符 作用
1 跳到新页
空格 单行间距
0 双行间距
+ 没有行距(在前一行上打印)

我在Windows平台IVF+VS中写的以下代码,与书中描写的结果并不一致,这些控制字符没有起到作用,而是直接被输出出来了。

  1. PROGRAM main
  2. IMPLICIT NONE
  3. WRITE(*,100)
  4. 100 FORMAT('1','This heading is at the top of a new page.')
  5. WRITE(*,200)
  6. 200 FORMAT('0','Control Character Action ')
  7. WRITE(*,300)
  8. 300 FORMAT(' ','================= ======')
  9. END PROGRAM

实际运行结果如下:

1This heading is at the top of a new page. 0Control Character Action ================= ====== 请按任意键继续. . .

而不是行间距的变化,这些描述行间距的控制字符被直接输出出来了。

格式描述符

格式描述符的四个基本类别:

  1. 描述文本行垂直位置的格式描述符;
  2. 描述行中数据水平位置的格式描述符;
  3. 描述特定数值的输出格式的格式描述符;
  4. 控制格式中一部分的重复的格式描述符。

格式描述符使用的符号

符号 含义
c 列号
d 实数输入或输出的小数位右边的位数
m 要显示的最小位数
n 要跳过的空格数
r 重复计数,一个或一组描述符的使用次数
w 域宽,输入或输出占用的字符数

整数输出-I描述符

格式:r_I_wr_I_w.m
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. INTEGER::index = -12, junk = 4, number = -12345
  4. WRITE(*,110) index, index+12, junk, number
  5. WRITE(*,120) index, index+12, junk, number
  6. WRITE(*,130) index, index+12, junk, number
  7. 110 FORMAT(' ', 2I5, I6, I10)
  8. 120 FORMAT(' ', 2I5.0, I6, I10.8)
  9. 130 FORMAT(' ', 2I5.3, I6, I5)
  10. END PROGRAM

结果如下:
image.png
整数数值在给定的显示域宽内右对齐打印。
注:输出结果中的,是因为本身整数过大,而给的输出域宽太窄,不足以放入打印区域,那么就用表示。
特殊的零长度描述符,I0,可以使整数输出到足够容纳其信息的可变域宽中。

实数输出-F描述符

格式:r_F_w.d
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. REAL::a = -12.3, b = .123, c = 123.456
  4. WRITE(*,110) a, b, c
  5. WRITE(*,120) a, b, c
  6. 110 FORMAT(2F6.3, F8.3)
  7. 120 FORMAT(3F10.2)
  8. END PROGRAM

结果如下:
image.png
实数数值在给定的显示域宽内右对齐打印。
如果有必要,数值在显示前会自己四舍五入。
如果要求显示的小数点后位数多余实际,会自己添加额外的0。
给定的域宽太窄,会显示星号。

实数输出-E描述符

格式:r_E_w.d
E描述符使数据规范到0.1到1.0之间的数乘10的幂。
使用E格式,要特别注意区域大小,一般来说,E格式描述符域宽应满足以下表达式:
w≥d+7
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. REAL::a = 1.2346E6, b = 0.001, c = -77.7E10, d = -77.7E10
  4. WRITE(*,110) a, b, c, d
  5. 110 FORMAT(2E14.4, E13.6, E11.6)
  6. END PROGRAM

结果:
image.png
当格式描述不满足w≥d+7时,会显示星号。

真正的科学记数法-ES描述符

格式:r_ES_w.d
ES格式描述符域宽应满足以下表达式:
w≥d+7
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. REAL::a = 1.2346E6, b = 0.001, c = -77.7E10
  4. WRITE(*,110) a, b, c
  5. 110 FORMAT(2ES14.4, ES12.6)
  6. END PROGRAM

结果:
image.png

逻辑输出-L描述符

格式:r_L_w
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. LOGICAL::output = .TRUE., debug = .FALSE.
  4. WRITE(*,110) output, debug
  5. 110 FORMAT(2L5)
  6. END PROGRAM

结果:
image.png

字符输出-A描述符

格式:r_A或_r_A_w

r_A:在宽度与要显示的字符数相同的区域内显示字符数据 _r_A_w:在一个固定宽度w的区域内显示字符数据

例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. CHARACTER(len=17)::string = 'This is a string.'
  4. WRITE(*,10) string
  5. WRITE(*,11) string
  6. WRITE(*,12) string
  7. 10 FORMAT(A)
  8. 11 FORMAT(A20)
  9. 12 FORMAT(A6)
  10. END PROGRAM

结果:
image.png

水平定位-X和T描述符

X描述符:格式nX
n为插入的空格数,用于在输出行上的两个数值之间添加一个或多个空格
T描述符:格式Tc
c为要转到的列号,用来输出缓冲区中直接跳到一个特定列
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. CHARACTER(len=10)::first_name='James'
  4. CHARACTER::initial='R'
  5. CHARACTER(len=16)::last_name='Johnson'
  6. CHARACTER(len=9)::class='COSC 2301'
  7. INTEGER::grade=92
  8. WRITE(*,100)first_name,initial,last_name,grade,class
  9. 100 FORMAT(A10,1X,A1,1X,A10,4X,I3,T51,A9)
  10. END PROGRAM

结果:
image.png
详见Page147

改变输出行-斜线(/)描述符

斜线(/)描述符可以在一个WRITE语句中将输出行打印在多行上。
要跳过几行就加几个斜线(/),例如,一条(/)会在第二行继续打印;两条(/)会在第三行(跳过一行)继续打印……
例:

  1. PROGRAM main
  2. IMPLICIT NONE
  3. INTEGER::index=10
  4. REAL::time=300.,depth=330.,amplitude=850.65,phase=30.
  5. WRITE(*,100)index, time, depth, amplitude, phase
  6. 100 FORMAT(T20,'Results for Test Number ',I3,///,&
  7. 'Time = ',F7.0,/,&
  8. 'Depth = ',F7.1,'meters',/,&
  9. 'Amplitude = ',F8.2,/,&
  10. 'Phase = ',F7.1)
  11. END PROGRAM

结果:
image.png

例题

  1. PROGRAM table
  2. IMPLICIT NONE
  3. INTEGER::i
  4. INTEGER::square
  5. INTEGER::cube
  6. REAL::square_root
  7. WRITE(*,100)
  8. 100 FORMAT(T3,'Table of Square Roots, Squares, and Cubes'/)
  9. WRITE(*,110)
  10. 110 Format(T4,'Number',T13,'Square Root',T29,'Square',T39,'Cube')
  11. WRITE(*,120)
  12. 120 FORMAT(T4,'======',T13,'===========',T29,'======',T39,'===='/)
  13. DO i = 1,10
  14. square_root = SQRT(REAL(i))
  15. square = i**2
  16. cube = i**3
  17. WRITE(*,130)i,square_root,square,cube
  18. 130 FORMAT(1X,T4,I4,T13,F10.6,T27,I6,T37,I6)
  19. END DO
  20. END PROGRAM

结果:
image.png

文件及文件处理介绍

OPEN语句

格式:OPEN (open_list)
open_list为一组子句,最重要的6项:

  1. UNIT=指明与文件关联的i/o单元号,格式:UNIT=int_expr,int_expr为非负整数;
  2. FILE=指定要打开的文件名,格式:FILE=char_expr,char_expr是包含要打开文件名的字符值;
  3. STATUS=指定要打开文件的状态,格式:STATUS=char_expr,char_expr为:”OLD”,”NEW”(打开新文件,如若存在,IOSTAT的变量会返回错误值),”REPLACE”(无论是否有同名文件,都打开一个新文件,若文件已存在,则删除,再建立新文件),”SCRATCH”(临时文件,保存程序运行中间结果,当文件被关闭或程序运行结束,该文件会被删除),”UNKNOW”;
  4. ACTION=指定文件是否以只读、只写或读写方式打开,格式:ACTION=char_expr,char_expr为:”READ”,”WRITE”,”READWRITE”,若未指定,则以读写方式打开;
  5. IOSTAT=指定一个整数变量名,打开状态返回到这个变量中,格式:IOSTAT=int_var,其中int_var为整数变量。如果打开成功,返回给这个整数变量的值为0,若不成功,返回正整数值。
  6. IOMSG=指定一个字符变量名,如果发生错误,将包含错误信息,格式:IOMSG=chart_var。如果OPEN执行成功,字符变量内容不变,如果不成功,错误信息返回到该字符串。

CLOSE语句

格式:CLOSE (close_list)
close_list必须包含一个指定i/o单元号子句,也可指定其他选项(第14章)。
无CLOSE语句,程序运行结束也会自动关闭。
非临时文件关闭后,可再次OPEN打开,可以使用新的i/o单元号,也可使用之前的。
文件关闭后,i/o单元会被释放,可以在新的OPEN语句中再次使用该i/o单元号。

READ语句的IOSTAT=和IOMSG=子句

当使用磁盘文件,可以给READ语句增加IOSTAT=和IOMSG=子句。
IOSTAT=子句格式:IOSTAT=int_var

若READ成功执行,给整型变量int_var返回0; 若由于文件或格式错误,返回与系统错误信息对应的整数; 若由于已经到达输入数据文件尾部而导致语句执行失败,返回一个负数。

READ语句包含IOMSG=子句,在返回的i/o状态为非零值时,IOMSG=子句返回的字符串将以语句的形式解释发生的错误。
例:

  1. PROGRAM read_file
  2. IMPLICIT NONE
  3. CHARACTER(LEN=20)::filename !要打开的文件名
  4. CHARACTER(LEN=80)::msg !错误信息
  5. INTEGER::nvals=0 !读入数值的个数
  6. INTEGER::status !I/O状态
  7. REAL::value !读入的实数值
  8. WRITE(*,*) 'Please enter input file name:'
  9. READ(*,*) filename
  10. WRITE(*,100) filename
  11. 100 FORMAT('The input file name is ', A)
  12. OPEN(UNIT=3,FILE=filename,STATUS='OLD',ACTION='READ',&
  13. IOSTAT=status,IOMSG=msg)
  14. openif:IF(status == 0) THEN
  15. readloop:DO
  16. READ(3,*,IOSTAT=status) value
  17. IF(status /= 0) EXIT
  18. nvals = nvals + 1
  19. WRITE(*,101) nvals, value
  20. 101 FORMAT('Line ',I6,':Value = ',F10.4)
  21. END DO readloop
  22. readif:IF(status > 0) THEN
  23. WRITE(*,102) nvals+1
  24. 102 FORMAT('An error occurred reading line ',I6)
  25. ELSE
  26. WRITE(*,103) nvals
  27. 103 FORMAT('End of file reached. There are ',I6,&
  28. ' values in the file.')
  29. END IF readif
  30. ELSE openif
  31. WRITE(*,104) status
  32. 104 FORMAT('Error opening file: IOSTAT = ',I6)
  33. WRITE(*,105) TRIM(msg)
  34. 105 FORMAT(A)
  35. END IF openif
  36. CLOSE(UNIT=3)
  37. END PROGRAM read_file

文件定位

BACKSPACE语句:BACKSPACE(UNIT=unit),每次调用它都可以回退一条记录;
REWIND语句:REWIND(UNIT=unit),可以从文件头重新开始文件。
两条语句也可使用IOSTAT=和IOMSG=子句,以检测回退或倒回操作期间是否发生错误。
例:

  1. PROGRAM least_squares_fit
  2. IMPLICIT NONE
  3. INTEGER,PARAMETER::LU = 18
  4. CHARACTER(LEN=24)::filename
  5. INTEGER::ierror
  6. CHARACTER(LEN=80)::msg
  7. INTEGER::n = 0
  8. REAL::k
  9. REAL::sum_x = 0.
  10. REAL::sum_x2 = 0.
  11. REAL::sum_xy = 0.
  12. REAL::sum_y = 0.
  13. REAL::x
  14. REAL::x_bar
  15. REAL::y
  16. REAL::y_bar
  17. REAL::b
  18. WRITE(*,100)
  19. 100 FORMAT('该程序功能为根据输入的数据拟合出最佳平方逼近的直线。',/,&
  20. '直线形式为:y = k*x + b',/,'请输入包含(x,y)数据的文件名:')
  21. READ(*,'(A)') filename
  22. OPEN(UNIT=LU,FILE=filename,STATUS='OLD',IOSTAT=ierror,IOMSG=msg)
  23. errorcheck:IF(ierror > 0) THEN
  24. WRITE(*,1010) filename
  25. 1010 FORMAT('错误:文件:',A,'不存在!')
  26. WRITE(*,'(A)') TRIM(msg)
  27. ELSE
  28. DO
  29. READ(LU,*,IOSTAT=ierror) x,y
  30. IF(ierror /= 0) EXIT
  31. n = n + 1
  32. sum_x = sum_x + x
  33. sum_y = sum_y + y
  34. sum_x2 = sum_x2 + x**2
  35. sum_xy = sum_xy + x*y
  36. END DO
  37. x_bar = sum_x / REAL(n)
  38. y_bar = sum_y / REAL(n)
  39. k = (sum_xy - sum_x*y_bar) / (sum_x2 - sum_x*x_bar)
  40. b = y_bar - k*x_bar
  41. WRITE(*,1020) k,b,n
  42. 1020 FORMAT('斜率(k) = ',F12.3,/,&
  43. '截距(b) = ',F12.3,/,&
  44. '输入的(x,y)对数为',I12,'对')
  45. CLOSE(UNIT=LU)
  46. END IF errorcheck
  47. END PROGRAM least_squares_fit