Fortran by Hf7Av38

VIEWS: 49 PAGES: 91

									Fortran
        發展簡史

   1954:IBM 在 IBM 704 上發展
   1957:IBM發表,Fortran → Formula Translator
   1966:American Standards Association 制訂 Fortran 66
       鑑於各家編輯器無法相容,故統一標準
       American Standards Association:美國國家標準局(ANSI)的前身
   1978:ANSI 公布 Fortran 77 標準
       刪去部分內容,新增邏輯與輸出入方面的功能
   1992:國際標準組織 ISO 公布 Fortran 90 標準
       與 77 版本差異大
       加入物件導向、提供指標與加強陣列功能、自由格式寫作
   1997:國際標準組織 ISO 公布 Fortran 95 標準
       加強平行運算
   Fortran 200x
     書面格式

   Fixed Format是舊式的寫法,有較多的限制,
    Fixed Format副檔名用 *.F 或 *.FOR 。
   Free Format則是Fortran 90以後新增的作法,以副檔名
    做為區隔,Free Format使用 *.F90。
   Fixed Format(固定格式)
      字元位置意義:
    第 1 字元:如果是字母 C 或 c 或是星號 *,本行視為註解
    第 1-5 字元:空白,或是一組數字為本行程式的代號
    第 6 字元:放上 0 以外的字元,表示為接續上一行程式碼
    第 7-72 字元:程式碼寫作區域
    第 73 字元以後:不使用,編輯器會忽略,有些則發出錯誤訊息

    程式碼之間多餘的空格不具意義,僅作分隔與方便閱讀
    配合打孔卡片所發展,Fortran 90之後可採用Free Format
   例如:

1:C FIXED FORMAT
2:    PROGRAM FIXED
3:    READ (*,10) A,B
4: 10 FORMAT (F5.1,F5.1)
5:   SUM = A + B
6:   WRITE (*,20)
7: +SUM
8: 20 FORMAT (1X,F6.1)
9:    END
   Free Format(自由格式)
       Fortran 90 開始使用,附加檔名為 *.F90
       不再規定第幾字元有何特定用途
       驚嘆號「!」後都是註解
       每行可以寫作 132 字元
       如有行號放在每行最前面
       程式連接符號改為「&」,放在每行程式碼最前或最後,表連結
        前一行或是下一行
  例如:
1:! free format
2:   program free
3:   read (*,10) a,b
4:10 format (f5.1,f5.1)
5:   sum=a+b
6:   write (*,20) &
7:   sum
8:20 format (1x,f6.1)
9:   end
        輸出入指令

       WRITE
write(*,*) "Hello"
"*"星號意義:
        前者代表使用預設輸出裝置(一般即為螢幕)
        後者代表不特別設定輸出格式

嚴謹用法:
write(UNIT=*,FMT=*) "Hello" ! 使用預設輸出裝置,不設定特別格式
write(6,*) "Hello"   ! 使用螢幕輸出,不設定特別格式
write(UNIT=6,FMT=*) “Hello” ! 最嚴謹的寫法

輸出字串若包含有單或雙引號,請參考字串宣告
格式化請參見FORMAT
   PRINT

    print *, "Hello"
    print指令沒有指定輸出裝置的能力,只能針對螢幕輸出
   READ
read (*,*) a
讓使用者能透過鍵盤輸入變數內容
"*"星號意義:
         前者代表使用預設輸入裝置(一般為鍵盤)
         後者代表不指定輸入格式
嚴謹用法:
read(UNIT=*,FMT=*) "Hello" ! 使用預設輸入裝置,不指定輸入格式
read(5,*) "Hello"         ! 使用鍵盤輸入,不指定輸入格式
read(UNIT=5,FMT=*) "Hello" ! 最嚴謹的寫法
注意事項:
輸入字串無頇加上雙引號,但字串中若有空格或逗號,將被視為兩筆
      資料,比如:
         read (*,*) a, b
      若輸入 Happy Birthday,則a="Happy","b="Birthday"
         read (*,*) a
      若輸入 Happy Birthday,則a="Happy"
   FORMAT
      a = 12.3456
     write (*,*) a
     write (*,100) a
100 format(f5.2)
則前者輸出結果為「12.3456」,後者為「12.34」
f5.1代表使用5個字元長度顯示浮點數,其中小數佔1位

1. 簡化的用法1:將輸出格式寫在write指令中
    write (*,"(1x,f5.2)") a
     優點:
               減少程式行數及行號使用
               容易閱讀(不用另找行號、FORMAT)
     缺點:
               格式複雜時,程式碼混亂
               格式設定相同時,無法重複利用
2. 簡化的用法2:
不同格式控制指令,(1x,f5.2)可以移去逗號簡化成format (1xf5.2)
重複相同格式(a3,a3)不可以簡化成(a3a3),改用format (2a3)
若有不同格式時,如(1xf5.2 , 1xf5.2 , 1xf5.2)則改用format (3(1xf5.2))

3. 字串可以直接寫入格式內:
write (*,"(a4,I1)") "1+2=",1+2
write (*,"('1+2=',I1)") 1+2
輸出均為 1+2=3 。上例中單雙引號混用,但F77只用使用單引號:
write (*,'(''1+2='',I1)') 1+2
4. 使用字串變數做為格式條件,如:
   character(len=10) fmtstring
   fmtstring = "(f5.1)"
   write (*,fmtstring) 123.4
   好處在於,若執行階段輸出變數超過5個字元,可經由如:fmtstring(3:3)=“8”,
   使得格式成為(f8.1),以容納更大的數字

5. 常見錯誤:
  變數型態與格式型態不符:比如變數為整數123,卻給定字串型態A3
  早期應用在印表機輸出時,第一個字元被做為控制字元,所以早期程式設計師習
  慣上每一行最前面預留一個空白(1X),但多數編輯器已經取消這個設計

6. 通常設計師建議,不要將format集中排列,如此不利於搜尋。最好將format直接
   放在write之下、甚至用上述寫入write中。(但有些format被重複使用,所以非每
   行write都有format伴隨)
     變數型態
   基本概念
    以整數為例:
    integer a
    "a"為自己取的變數名稱,代表一個儲存整數的空間位置,稱為變數
    宣告後透過該名稱來給予或提供變數內容,如:
    1. program example
    2. integer a, b
    3. a = 3         ! 將a變數設定為3
    4. b = a ** 2      ! 將b變數設定為a**2,即3**2
    5. print *, "a=", a ! 寫出a的內容
    6. print *, "b=", b ! 寫出b的內容
    7. stop
    8. end example
執行結果
a=   3
b=   9
• 使用注意:
等號意義代表將左邊變數的內容,設定成右邊的數值或計算結果
• 名稱命名等原則及注意事項,請參考變數宣告
   整數型態 (INTEGERAL)
     integer a
     1. 使用注意:
     • 計算結果無條件捨去小數部分 ← 常見錯誤!
        如:a=3/2 → a=1 、a=1/2 → a=0
     • 宣告未指定長度時,通常表示為長整數
     2.長整數 - 使用4位元組(4 bytes, 32 bits)
        integer(kind=4) a ! F90新增作法
        integer(4) b !
        INTEGER*4        c ! F77傳統作法
        可儲存範圍:-2,147,483,648 ~ +2,147,483,647
3. 短整數 - 使用2位元組(2 bytes, 16 bits)
    integer(kind=2) a ! F90新增作法
    integer(2) b !
    INTEGER*2        c ! F77傳統作法
    可儲存範圍:-32,768 ~ +32,767
4. 部分編譯器支援 - 使用1位元組(1 bytes, 8 bits)
    integer(kind=1) a ! F90新增作法
    integer(1) b !
    INTEGER*1        c ! F77傳統作法
    可儲存範圍:-128 ~ +127
   浮點數型態 (REAL)
    real a
    未指定kind值時,通常宣告為單精準度(kind=4)
    1. 單精準度 - 使用4位元組(4 bytes, 32 bits)
        real(kind=4) a ! F90新增作法
        real(4)   b !
        REAL*4      c ! F77傳統作法
        可表示範圍(PC):±1.18*10-38 ~ ±3.40*1038
        單精準度有效位數為6-7位,注意可能有以下問題:
        a = 1000000. + 0.1 → a = 1000000. ← 常見錯誤,大數加小數!
2. 雙精準度 - 使用4位元組(8 bytes, 64 bits)
    real(kind=8) a ! F90新增作法
    real(8) b !
    REAL*8       c ! F77傳統作法
    可表示範圍(PC):±2.23*10-308 ~ ±1.79*10308
    雙精準度有效位數為15位
3. 使用注意:
    常數部分請加上".0",如3 → 3.0(只加"."亦可)
    real a
     • a= 1.5+3./2. → a= 3.0 (3.與2.被視為浮點數)
     • a= 1.5+3/2 → a= 2.5 (3/2視為整數,小數無條件捨去)← 常見錯誤!
    雙精準度(REAL*8),常數請加上"d0",如3 → 3.d0 ← 常見 忽略!
    或採用 a = 1.0_4 表示 kind = 4
       a = 1.0_8 表示 kind = 8
    可用科學記號表示法,如
     • 10,000,000,000 = 1E10 (1D10 代表雙精準度)
     • 0.0000000001 = 1E-10 (1D-10代表雙精準度)
   複數型態 (COMPLEX)
complex a
(複數由實部與虛部組成,a=x+yi,x 為實部、y 為虛部,皆為實數型態)
1. 使用注意:
     • 設定數值
         a = (x,y) ! a = x + yi ,若x=1.5,y=2.5,a=1.5 + 2.5i
         a = (1.5,2.5) ! a = 1.5 + 2.5i
         a = 1.5     ! a = 1.5 + 0i
2. 單精準度 - 使用兩個單精準浮點數
    complex(kind=4) a ! F90新增作法
    complex(4) b !
    COMPLEX*8         c ! F77傳統作法
3. 雙精準度 - 使用兩個雙精準浮點數
    complex(kind=8) a ! F90新增作法
    complex(8) b !
    COMPLEX*16         c ! F77傳統作法
   字元與字串 (CHARACTER)
    character a (此例僅能儲存一個字元)
    1. 長度超過一個字元時,需指定長度,如需十個字元長度時:
       character(len=10) a ! F90新增作法
       character(10) b !
       CHARACTER*10          c ! F77傳統作法
       CHARACTER*(10) d !
2. 使用注意:
    • 設定字串變數:
       a = "Hello"        ! F90使用單或雙引號來包裝字串
       b = 'Hello'       ! F77使用單引號來包裝字串
       c = "That's right" ! 使用雙引號中,有單引號不受影響
       d = „That‟„s right‟ ! 使用單引號,字串又包含單引號時,請連續使用
       兩個單引號
       e = “”“Hello”“” ! 使用雙引號,字串又包含雙引號時,請連續使用兩
       個雙引號,本例輸出為"Hello"
    • 設定部分字串:
       string(1:4) = "Good" ! 指定1-4字元
       string(5:5) = " "      ! 指定第5字元
       string(6:) = "morning" ! 指定第6個字元以後的字串
       使用 // 連接兩字串:string_a = string_b // string_c
       副程序中宣告為不定長度(依呼叫端長度決定)
     邏輯變數 (LOGICAL)
logical a
1. 使用注意:
    設定邏輯變數:
    a = .true. ! 設定為「真」
    a = .false. ! 設定為「假」
    使用 WRITE 輸出時,僅顯示 T 或 F
    但實務上邏輯變數很少用於輸出
2. 通常不指定使用空間大小,由編輯器自行決定,最少只需1個位元(1 bit)
    若指定使用4個位元組時(4 bytes, 32 bits)
    logical(kind=4) a ! F90新增作法
    LOGICAL*4        b ! F77傳統作法
    LOGICAL(4)       c ! F77傳統作法
    (也可使用2個位元組,將上例4換為2即可)
   自訂資料型態 (TYPE) - F90新增

    舉例來說,若程式中需記錄一個人的姓名、身高、體重、血型,則
    需要宣告四個變數,透過自訂型態,我們可以訂定一個「人員基本
    資料」的資料型態,其中將包含上述的各項資料型態,該資料型態
    變數使用起來就像是Visual Basic的物件。以下舉實例說明:
! 建立名稱為person的自訂資料型態
type :: person
  character(len=25) :: name ! 記錄姓名
  integer(kind=2) :: length ! 記錄身高
  integer(kind=2) :: weight ! 記錄體重
  character(len=2) :: blood ! 記錄血型
end type person
! 自訂資料型態結束,本例中person型態包括了四個元素

type(person) :: a ! 宣告一個person型態的變數
read(*,*) a%name ! 讀取變數a的姓名資料,變數與元素間以%隔開
write(*,*) a%name ! 列印變數a的姓名資料
a = person("Frank",172,75,"O") ! 直接設定所有資料
    KIND的應用 - F90新增
宣告INTEGER與REAL時,KIND值將影響可儲存範圍與有效位數,以PC來說:
integer(kind=1):-128 ~ +127
integer(kind=2):-32,768 ~ +32,767
integer(kind=4):-2,147,483,648 ~ +2,147,483,647
real(kind=4):±1.18*10-38 ~ ±3.40*1038   ,有效6-7位
real(kind=8):±2.23*10-308 ~ ±1.79*10308 ,有效15位
以下兩個函數可以判斷要記錄數值值域範圍所需的kind值。一般雖無頇使用,但
若程式有需要在不同電腦系統間移植,由於可儲存位數的差異,若能依實際需
要查詢該系統的kind值,可使程式維持正確性
• SELECTED_INT_KIND(n)
    傳回需要記錄 n 位整數時,所應宣告的kind值
    傳回 -1 時,表示無法提供該數值值域範圍
• SELECTED_REAL_KIND(n,e)
  傳回需要記錄 n 位有效位數、指數達到 e 位的浮點數所需kind值
  傳回 -1 表示無法滿足所要求有效位數
  傳回 -2 表示無法滿足所要求指數範圍
  傳回 -3 表示兩者都無法滿足
舉例:
  integer, parameter :: short_int = SELECTED_INT_KIND(3)
  integer, parameter :: long_real = SELECTED_REAL_KIND(9,30)
  integer(kind = short_int) :: a = 172
  real(kind = long_real) :: b = 1.23456789D25
  變數宣告

• 變數名稱命名原則注意:
  名稱可使用英文字母a-z、底線_、數字0-9(首字需為英文字母)
  變數名稱長度,F77規定至少支援1-6個字元,F90支援1-31個字元
  雖未規定,但建議不要與執行指令相同(比如PRINT)
  建議取有意義的英文單字,增加程式可讀性並減少出錯的機會
• 一般變數宣告請參閱:變數型態
• 注意內定型態的影響:
    變數不一定需經過宣告才能使用,未經過宣告之變數,依變數第一個字母
    決定型態
    未經宣告下,第一個字母 i,j,k,l,m,n 的變數將被視為整數型態,其他的則為
    浮點數;但可透過IMPLICIT來改變此預設狀態
    建議所有變數仍應宣告,以瞭解記憶體使用情況並能降低人為錯誤發生
    可配合IMPLICIT NONE指令限制所有變數需經宣告才能使用,以降低人為
    錯誤發生,比如變數 i 打成 j
• 可用parameter宣告變數為常數,以減少錯誤並增加執行速度
• equivalence則是在特殊情況下可減少記憶體的浪費以及增加速度
•宣告結構注意:
    • 宣告的位置要在可執行敘述之前,在數值計算或是輸出入指令後就不能
    再宣告
    • DATA也是宣告的一部份,也只能放在執行指令前
    • 通常program後接著implicit,然後宣告變數,最後是DATA
      IMPLICIT
未經宣告變數,編輯器會以其第一個字母決定型態,此稱為「內定型態」。
預設的狀況是,第一個字母 i,j,k,l,m,n 的變數將被視為整數型態,其他的則為
浮點數。
IMPLICIT可以用來改變與關閉內定型態。
1. 使用方式:
     implicit integer(A,B,C)   ! A,B,C開頭變數視為整數
     implicit integer(A-D,X,Y) ! A-D,X,Y開頭變數視為整數
     implicit real(L-P)    ! L-P開頭變數視為實數
     implicit none        ! 關閉此項服務,所有變數皆需經過宣告
2. 一個程式單元可以有一個以上 IMPLICIT 敘述,但是所有 IMPLICIT 敘述
    必頇在該程式單位所有其他宣告敘述之前才行。通常就是在program指令
    下一行。
3. 如果設定 IMPLICIT NONE,則所有使用者定義的名稱都必頇宣告其型態,
   未定義型態的名稱會產生編譯時期錯誤。也就是說,會強迫你宣告所使
   用到的每一個變數名稱。強烈建議初學者使用,因為助教實在太常遇到
   同學把變數名稱給拼錯或是型態錯誤(比如i,j,k,l,m,n開頭的變數預設為
   整數)。
4. 一個程式單元只能有一個 IMPLICIT NONE 敘述,也不能有其他的
    IMPLICIT 敘述。
   給定初值.DATA
變數宣告後,可利用等號來給定初值,如:
real pi
pi = 3.14159
但若要給初值的變數很多,程式便顯得雜亂,請參考:
• 利用 DATA/.../ 指令,依序給定變數初值
     real a, b
     complex c
     character(10) string
     data a, b, c, string /1.0, 2.0, (3.0,4.0), 'Hello'/
     則依順序,a=1.0 ,b=2.0 ,c=(3.0,4.0) ,string = 'Hello'
     使用在陣列變數中,更顯其方便:
     real a(4)
     data a /1.0 , 2.0 , 3.0 , 4.0/
• F90可以將宣告與初值寫在同一行程式碼中:
  real :: pi = 3.14159
  integer :: count = 0
  此時冒號不可省略


• 給定整數資料時,可以2、8、16進位方式
  若要給定28(十進位),可採用:
   a = B"11100" ! B 代表二進位 (Binary) - 0,1
   a = O"34"     ! O 代表八進位 (Octal) - 0,1,2,3,4,5,6,7
   a = Z"1C"     ! Z 代表十六進位 - 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E
     PARAMETER
PARAMETER (pi=3.14159)
可將變數pi視為常數使用,通常目的在簡化程式碼、減少錯誤、方便修改以及
增加可讀性
area = pi * radius**2 可讀性較 area = 3.14159 * radius**2 更好
若需將3.14159改為其他數字時,只需修改如:PARAMETER (pi=3.14)
1. 注意事項:
     • 數值只能設定一次
     • 在程式碼中不可去改變常數的內容
2. 將PARAMETER (pi=3.14159)改為一般變數pi=3.14159,程式仍可執行,但
    設定為常數後:
     • 若程式碼有修改該常數內容時,編譯階段會有錯誤訊息
     • 若變數內容在執行階段不會改變,改為常數將可增加執行速度
3. F90中,變數與常數宣告可以寫入同一行:
     real, parameter :: pi=3.14159 ! pi前的冒號不能省略
     冒號在告訴編輯器,宣告型態與設定已經完畢,冒號後開始給定變數名稱
    EQUIVALENCE(等位宣告)
integer a,b
equivalence (a,b)
則變數 a,b 將使用同一個記憶體空間,只是有兩個名稱
1. 用途之一:
     •   程式中的暫時變數,有時程式需要一些暫時使用的資料變數,通常設
         計師會宣告一個temp變數,但如此程式可讀性降低,但若每一個都各
         自宣告又浪費記憶體空間,此時可以利用equivalence,讓多個暫存變數
         使用同一記憶體空間。
     •   比如:
          integer temp_count, temp_record
          equivalence (temp_count, temp_record)
          需注意兩個暫存變數未被同時使用,否則產生錯誤
2. 用途之二:
  •    在陣列資料中,如某一位置經常被使用,則可以利用
       equivalence提昇效率。
  •    比如:
       equivalence (array(2,3,4), a)
      程式中需使用 array(2,3,4) 的地方改以 a 代替,除了精簡版面,
       系統在陣列的處理上需從陣列起始位置換算array(2,3,4)的記
       憶體位置,而 a 則可以直接獲得,可提昇效率
          流程控制與邏輯運算

   The Logical IF Statement
    IF (logical expression) statement
   The Arithmetic IF Statement
    IF (arithmetic expression) num1,num2,num3
    expression < 0 then goto num1
    expression = 0 then goto num2
    expression > 0 then goto num3
   The IF-ENDIF Statement
    IF (<logical expression>) THEN
          ...
          ... (statement group)
          ...
    ENDIF
    ...
   The ELSE Statement
    The IF-ENDIF Statement
          IF (<condition>) THEN
           ...
            ... (statement group 1)
            ...
          ENDIF
          IF (<opposite condition >) THEN
            ...
            ... (statement group 2)
            ...
          ENDIF
    The ELSE Statement
          IF (<condition>) THEN
            ...
            ... statement to be executed if <condition> is .TRUE.
            ...
          ELSE
            ...
            ... statement to be executed if <condition> is .FALSE.
            ...
          ENDIF
   The ELSE-IF Statement
    IF (<logical expression 1>) THEN
      ...
      ... (statement group 1)
      ...
    ELSEIF (<logical expression 2>) THEN
      ...
      ... (statement group 2)
      ...
    ELSEIF (<logical expression 3>) THEN
      ...
      ... (statement group 3)
      ...
    ELSEIF (<logical expression n>) THEN
      ...
      ... (statement group n)
      ...
    ELSE
      ...
      ... (all false statement group)
      ...
    ENDIF
   Nesting IF-ENDIF Structures
    IF (<logical expression-1>) THEN
     ...
     ...
     IF (<logical expression-2>) THEN
        ...
        ...
     ENDIF
     ...
     ...
    ENDIF
   Logical Expression
       LOGICAL Type
        The <condition>s are logical expressions, which can only have values .TRUE.
        and .FALSE.
       Logical expressions
            Relational expressions (comparisons)
            Logical variable
            .NOT. logical expressions (logical complement)
            Logical expressions .AND. Logical expressions (logical conjunction)
            Logical expressions .OR. Logical expressions (logical disjunction)
            Logical expressions .EQV. Logical expressions (logical equivalence)
            Logical expressions .NEQV. Logical expressions (logical differ)
       Relational expressions compare two numeric or character quantities, and have
        the following form: quantity <relation> quantity
   Relational operator (quantity <relation> quantity)

    F77使用縮寫     F90可用符號                  代表意義

      .EQ.           ==                  = equal to

      .NE.           /=                ≠ not equal to

      .LT.           <                  < less than

      .GT.           >                 > greater than

      .LE.           <=            ≦ less than or equal to

      .GE.           >=           ≧ greater than or equal to
       Logical operators

 A         B      .NOT. A   A .AND. B   A .OR. B   A .EQV. B   A .NEQV. B


True      True     False      True        True       True        False


True      False    False      False      True        False       True


False     True     True       False      True        False       True


False     False    True       False      False       True        False
   浮點數與字元的邏輯運算
       浮點數 Example:
         a = (3.**0.5)** 2
        b = 3.
        -> b - a 不會等於 0.0 ,(b-a .EQ. 0.0) is .FALSE.
         理論上 b - a 應等於 0.0 ,但受計算浮點數 a 時有效位數的影響,

          (3.**0.5)即產生誤差,再平方後只是接近 3. 的數字但並不等於 3. ,所
          以 (b-a .EQ. 0) 邏輯值為 .FALSE.
         將 a 值做螢幕輸出,得到 a = 0.0?可能是輸出格式的限制,所見為近

          似值(如已四捨五入)
         一般會採絕對或相對誤差來判斷,如

          if (abs(b-a) .LE. 0.000001) then ... 或
          if (abs(b-a)/b .LE. 0.000001) then ...
           註:abs函數可以傳回絕對值
         上例中,若改為 a = (4.**0.5)** 4 - 3. ,因 (4.**0.5) 得到 2. 沒有有效位

          數不足的問題,所以 b - a 值會等於 0.0
   字元的比較:
       字元可以比較大小,依其ASCII編碼順序
         'a' < 'b' ,∵ ascii(a)=97,ascii(b)=98
         'A' < 'a' ,∵ ascii(A)=65,ascii(a)=97
        ! ascii非內建函數,只是為了表達方便,請參考ichar
       字串比較時,則依字母順序一一比較下來
        'abcd' < 'axyz'
   SELECT CASE
F90新增,但幾乎所有F77編譯器都有支援
SELECT CASE (variable)
CASE (value-1)
 ...
 ... (statement group 1)
 ...
CASE (value-2)
 ...
 ... (statement group 2)
 ...
CASE (value-3)
 ...
 ... (statement group 3)
 ...
CASE DEFAULT
 ...
 ... (all false statement group)
 ...
END SELECT
   補充說明:
       case default 區段非必要
       CASE(value) 中,(value)可用(value1:value2),如 1:5 表示當 1≦變數
        ≦5 時執行該區段
       可取代IF-ELSE IF,但只接受整數、字元、邏輯變數,不能使用浮
        點數和複數
       CASE中的數值,必頇是常數
   GOTO
   在F77以前做為流程與迴圈控制,但由於容易造成程式結構混亂、降低可讀
   性、並產生錯誤,所以不建議使用。
Example 1: (IF-ELSE)
         if (a .GE. 60) then goto 100
         print *, "pass!"
         goto 200
   100 print *, "
   200 stop
Example 2: (LOOP)
        sum = 0
        count = 1
   100 if (count .GT. 10) then goto 200
        sum = sum + count
        count = count + 1
        goto 100
   200 print *, sum
        stop
   PAUSE.CONTINUE.STOP
       PAUSE
        程式執行至此,會暫停,並等待使用者按下 ENTER 鍵後繼續,在有大量資
        料作螢幕輸出時使用
       CONTINUE
         表示「繼續往下執行」,而就算沒有這行,也會繼續啊...
         在F77中,通常只是為了方便閱讀程式碼,比如與GOTO配合做迴圈使用時
       STOP
         結束程式執行,比如在 IF 中,當某條件成立或不成立,程式就必頇中斷
         使用此指令要小心,以免反致程式結構混亂,不該終止被終止
        迴圈

   The CONTINUE and GOTO statements
       由於 GOTO 的使用不當將造成程式結構混亂,且其閱讀性差,從
        Fortran 77 開始,已經不建議使用 GOTO ,而利用 DO 指令。
       利用GOTO強制程式回到特定指令行,形成迴圈:
               ... statement preceding loop ...
         <label> CONTINUE
               ... loop body ...
               GOTO <label>
           ... statement following loop ...
   loop body 需加入迴圈終止判斷,Conditional termination of loop execution
        IF {<exit condition>} GOTO <exit label>
        IF {<exit condition>} THEN
         ... statement to be executed just prior
         ... to leaving the loop at this point.
         GOTO <exit label>
         ENDIF
   Indexed Looping
                   <index-variable> = <initial-value>
                  * .... top of indexed loop ....
                  100 CONTINUE
                        IF (<index-variable> .GT. <final-value> GOTO 199
                          ...
                          ... loop statement
                          ...
                        <index-variable> = <initial-value> + <increment>
                        GOTO 100
                  * .... bottom of indexed loop ....
                  199 CONTINUE
    DO statements (Indexed Looping)
Fortran 77語法:
     DO <label> <index-var> = <initial-val>,<final-val>[,<increment>]
       ...
       ... loop statement
       ...
<label> CONTINUE

1. 第一次執行DO指令,<index-var> = <initial-val>

2. 每執行一次迴圈loop statement,<index-var>就會加上<increment>
  但迴圈中不可透過其他程式碼改變 <index-var> 數值,編譯時將發生錯誤
       DO 100 count = 1,10 ! 行號 100 表示迴圈程式碼結束位置
       i=i+1       ! 改變計數器的值,編譯時將產生錯誤訊息
   100 CONTINUE
3. 當 <index-var> ≦ <final-val>,繼續重複迴圈 ,
  迴圈結束後,<index-var> 一定大於 <final-val>

4. <initial-val>,<final-val>,<increment> 可以使用常數或變數
  但需注意的是,變數僅在進入迴圈時被讀取一次,迴圈中改變不影響迴圈
  執行狀況
    program test
    integer start , end , inc , i
    start = 1
    end = 10
    inc = 1
    do i = start, end, inc ! 用enddo做迴圈程式碼結束位置,F90標準,77多支援
        start = 3
        end = end - 1
        inc = -2
        print *, i , end ! 可觀察到變數內容的改變不影響 i 從 1 累加到 10
    enddo
    print *, i
    end
5. <increment> 可以是負數,EX:DO i = 10, 1, -1

6. <increment> 若未提供,預設為 1
EX: 如要計算 2+4+6+8+10+12 ,標準的:
        ans = 0           ! 給定初值,變數宣告後初值不一定會是 0
        DO 100 count = 2,12,2 ! 行號 100 表示迴圈程式碼結束位置
   100 ans = ans + count
   CONTINUE指令沒有實際的用途,利用其做為程式碼的包裝,方便閱讀:
         ans = 0           ! 給定初值,變數宣告後初值不一定會是 0
         DO 100 count = 2,12,2
         ans = ans + count
   100 CONTINUE               ! 迴圈結束後, count = 14
Fortran 90語法:(不需label,使用 enddo 做為結束,多數F77已支援)
     do <index-var> = <initial-val>,<final-val>[,<increment>]
       ...
       ... loop statement
       ...
     end do
     以上例而言
     ans = 0            ! 給定初值,變數宣告後初值不一定會是 0
     do count = 2,12,2
       ans = ans + count
     end do             ! 迴圈結束後, count = 14

Nested Loops: A loop body may itself contain a loop, and such nesting may be
arbitrarily deep.
     do i = 1, 5
       do j = 1, 3
          print *, a(i,j) ! 共執行 15 次 print 指令 (5*3)
       end do
     end do
   DO WHILE
do while (logical expression) ! 邏輯運算成立時,執行迴圈內容
  ...
  ...
end do

DO 迴圈用在可事先知道或控制迴圈執行次數,DO WHILE 迴圈則是不
能預知執行次數時,比如猜數字程式。
    CYCLE, EXIT
CYCLE、 EXIT 為 Fortran 90新增,但多數 77 的編譯器可用

CYCLE 指令可以略過程式區塊中,CYCLE 指令後面的所有所有程式碼,
直接跳下一次迴圈執行。
EX:對某些較小的資料量採取忽略的動作
do while (.true.)
  print *, 'Speed = ? (must > 99)'
  read *, speed
  if (speed .LT. 100) cycle ! 當speed小於100時,重新開始迴圈
  ...
end do

EXIT 可以直接結束迴圈執行。
EX:做數字總和,有一千筆資料,但若資料為0表示資料已結束,可利用 EXIT 提早結束
迴圈。
do i = 1, 1000
  sum = sum + a(i)
  if (a(i) .EQ. 0) exit ! 當條件成立,提前結束陣列
enddo
     迴圈命名
迴圈經過命名後,配合end do、cycle、exit的使用,可加強程式可讀性以減少出錯,
並能使結構更具彈性。
命名方法:<cycle_name> : do ...
配合使用:在 end do、cycle、exit 後面加上 <cycle_name>
EX:
outer: do i = 1, 10            ! 將第一層迴圈命名為 outer
    inner: do j = 1, 10        ! 將第二層迴圈命名為 inner
        ...
        if (i = 3) exit outer ! 當i=3,直接跳離外部迴圈,進行 i=4 迴圈
        if (j = 5) cycle inner ! 當j=5,忽略內部迴圈剩下的程式區塊
        ...
    enddo inner
enddo outer
     陣列

   一維陣列
宣告方式:<data type> <array name>(<size>)
data type可用integer、real、complex、logical也可用自訂型態type
產生 size 組記憶體位置,size 必頇是常數,EX:
   integer parameter :: count = 10
   real a(10), b(count)         ! a, b均為包含10個實數的陣列
各種宣告方式:
   integer a(10)          ! 最簡單的方法
   integer, dimension(10) :: a ! F90 另一種寫法
   INTEGER a                ! F77 的作法,先宣告型態,配合下行
   DIMENSION a(10)               ! 再宣告 a 的容量大小
叫用方法:<array name>(<sequence number>)
   integer a(10)
   read *, a(2) ! 從鍵盤輸入數值,置入 a 陣列中第二組記憶體位置
   print *, a(2) ! 將 a 陣列中第二組記憶體位置內容印出
    宣告指定索引值
宣告方式:<data type> <array name>(<low value>:<high value>)
 integer a(0:10)
 real b(-100:100)
基本的陣列宣告,如
 real a(10)
則 a(n) 代表陣列 a 中第 n 組記憶體位置內容,但經常為了可讀性問題,如數
列 a0,a1,a2,a3,...,a9 ,共十個元素,若宣告為 a(10),則
 a(1) = a0
 a(2) = a1
在使用上會造成混淆,所以在宣告陣列時可以利用 a(0:10) ,則
 a(0) = a0
 a(1) = a1
不會造成混淆,此時,a(0)代表陣列 a 中第 1 組記憶體位置內容,a(n)代表
陣列 a 中第 n+1 組記憶體位置內容。
即,宣告<data type> a(i:j),則 a(i+n) 代表第 n+1 個記憶體位置內容。
   二維陣列
    宣告方式:<data type> <array name>(<size, size>)
     integer a(3,4)
     real b(0:5,10)
    舉例:使用 C(10,4) 記錄班級十位同學,四個科目分數如下表:
       座號      國文      英文       數學       歷史
        1      80      85       75       80
        2      90      85       80       90
        3      75      80       90       85
        ...     ...

    資料可對應如下:
       座號     國文       英文       數學       歷史
        1     C(1,1)   C(1,2)   C(1,3)   C(1,4)
        2     C(2,1)   C(2,2)   C(2,3)   C(2,4)
        3     C(3,1)   C(3,2)   C(3,3)   C(3,4)
        ...     ...
    所以座號 2 同學的數學分數,就是 C(2,3)
    各種宣告方式:
     integer a(10,10)         ! 最簡單的方法
     integer, dimension(10,10) :: a ! F90 另一種寫法
     INTEGER a                  ! F77 的作法,先宣告型態,配合下行
     DIMENSION a(10,10)              ! 再宣告 a 的容量大小

   多維陣列
    宣告方式:<data type> <array name>(<size, size, ... , size>),最多到七
    維陣列

      integer a(3,4,5)
      read *, a(2,2,3)
      print *, a(2,2,3)
         記憶體配置
     DIMENSION A(5), B(0:4), C(3,4), E(12)

      A:         A(1)      A(2)       A(3)       A(4)     A(5)

         B:      B(0)      B(1)       B(2)       B(3)     B(4)

         C:      C(1,1)          C(1,2)      C(1,3)      C(1,4)
                 C(2,1)          C(2,2)      C(2,3)      C(2,4)
                 C(3,1)          C(3,2)      C(3,3)      C(3,4)

     ↓ equivalence C,E

C:       C(1,1) C(2,1) C(3,1) C(1,2) C(2,2) C(3,2) C(1,3) C(2,3) C(3,3) C(1,4) C(2,4) C(3,4)


E:        E(1)   E(2)     E(3)     E(4)   E(5)    E(6)    E(7)    E(8)   E(9)   E(10)   E(11)   E(12)
       Columnwise storage of data:
        addr(a(i,j)) = addr(a(1,1))+(j-i)*lda +(i-1)
        lda is the Leading Dimension of A
       效率注意,一起使用的資料,放在同一Column:

       資料不連續,效率差                 資料連續,效率好
       do i = 1, 5               do i = 1, 5
         sum = sum + a(1,i)        sum = sum + a(i,1)
       enddo                     enddo
      另外,多維陣列在處理記憶體位置較耗時,使用時頇注意。
   大小限制
    以 Compaq Visual Fortran 6.5 為例,整個程式使用記憶體大小以 256MB 為上限。
    參考錯誤訊息如下:
    -------------------------------------------------------------
    Linker Tools Warning LNK4084
    total image size size exceeds max (256MB); image may not run
    The application exceeds the limit of 256 megabytes.
    -------------------------------------------------------------
    設定初值.DATA.隱藏式迴圈
和一般變數相同,同樣可以利用DATA來給定初值
integer A(5)
data A/1,2,3,4,5/ ! A(1)=1,A(2)=2,A(3)=3,A(4)=4,A(5)=5
data A/5*3/       ! /5*3/表示有5個3,等於/3,3,3,3,3/
             ! A(1)=3,A(2)=3,A(3)=3,A(4)=3,A(5)=3
data (A(i),i=2,4) /2,3,4/ ! 使用「隱藏式迴圈」,只設定A(i), i=2,3,4
                   ! A(2)=2,A(3)=3,A(4)=4, A(1)及A(5)未設定
integer B(2,3)
data ( (B(i,j),i=1,2) , j=1,3 ) /1,2,3,4,5,6/
! 巢狀隱藏式迴圈,B(1,1)=1, B(2,1)=2, B(1,2)=3, B(2,2)=4, B(1,3)=5 ,B(2,3)=6
Fortran 90新增:(省去DATA)
integer :: a(5) = (/1,2,3,4,5/) ! 直接宣告並給初值,但必頇5個元素都給
                          ! A(1)=1,A(2)=2,A(3)=3,A(4)=4,A(5)=5
integer :: a(5) = (/1,(2,i=2,4),5/) ! 結合隱藏式迴圈
                          ! A(1)=1,A(2)=2,A(3)=2,A(4)=2,A(5)=5
integer :: a(5) = (/(i,i=1,5)/) ! A(i)=i, i=1~5
   ALLOCATABLE - Fortran 90新增
一般在宣告陣列時必頇指定大小,但有些問題在執行階段才知道需
要多大的陣列,這時經常的解決辦法就是宣告一個足夠大的陣列,
並告知使用者操作限制,如:
integer student(100), stu_count
print *,"輸入學生人數(MAX:100)"
read *, stu_count
do i = 1, stu_count
   print *, "請輸入第",i,"位同學成績"
   read *, student(i)
end do
...
Fortran 90則可以透過ALLOCATABLE來解決這個問題:
integer, allocatable :: student(:) ! 宣告一個可變大小的一維陣列
integer :: stu_count
print *,"輸入學生人數:"
read *, stu_count
allocate( student(stu_count) ) ! 配置stu_count個記憶體空間
do i = 1, stu_count
   print *, "請輸入第",i,"位同學成績"
   read *, student(i)
end do
...
  宣告注意:
   這裡需要 allocatable 和 allocate 兩個指令的配合,allocatable配合陣列
   宣告時使用,但陣列大小以「:」代替即可;當知道所需陣列大小
   時,再以 allocate 配置記憶體空間大小。
  配置是否成功:
   由於記憶體是有限的,不一定每次都會配置成功,如何得知是否配
   置成功?可寫成 allocate( student(stu_count), stat=error ) ,error是宣告
   好的整數變數,若成功,error傳為 0 ,其他數值表示失敗。
  解除配置空間:
   當該空間使用完畢,也可以透過 deallocate 指令來釋放配置空間:
如:deallocate( student )
完整的語法如下:
DEALLOCATE ( object [, object] ...[, STAT=sv] )
   object:
             Is a structure component or the name of a variable,     and
   must be a pointer or allocatable array.
   sv:
             Is a scalar integer variable in which the status of the
   deallocation is stored.
   多維陣列:
    integer, allocatable :: stu_2(:,:) ! 兩個冒號代表二維陣列
    integer, allocatable :: stu_3(:,:,:) ! 三個冒號代表三維陣列
    allocate( stu_2(3,3) )
    allocate( stu_2(4,4,4) )
   指定索引座標範圍:
    integer, allocatable :: stu_1(:)
    integer, allocatable :: stu_2(:,:) ! 兩個冒號代表二維陣列
    allocate( stu_1(-3:3) )
    allocate( stu_2(-3:3,0:5) )
   相關函數:
    allocated 可傳回陣列是否已經配置記憶體
   ALLOCATED

檢查一可變大小的矩陣是否已經配置記憶體,函數會傳回一個邏輯值。
如:
if ( .not. allocated(a) ) then
   allocate( a(5) )
end if
上例中,檢查陣列 a 是否已經配置,若無,則配置 5 個記憶體空間。
相關指令請參考:allocatable
   函式

函式是Subroutine(副程式)與Function(自訂函數)的統稱。
迴圈可以讓程式在相同的地方重複執行某一段程式碼,函式
則可以在不同的地方被重複使用,二者的應用範圍不同。
撰寫程式時,當某一段具備特定功能的程式碼被重複撰寫時,
可以將之包裝成函式,在使用時叫用該段函式(比如使用
CALL指令呼叫副程式),如此可使得程式撰寫更有效率,可
讀性也增加許多。
   Subroutine(副程式)
舉例如下:
! 使用者輸入兩個數字,傳入swap函式做交換後輸出
! 本例可用DO迴圈,但利用函式,在程式其他部分也可以呼叫函式功能
program Swap_2_Real
do while (.true)
  read *, value1, value2       ! 使用這從鍵盤輸入兩數字
  if (value1 .eq. value2) stop ! 若輸入兩數字相同,則停止程式
  call swap(value1, value2)      ! 呼叫 swap函式,做兩數交換
  print *, value1, value2      ! 將交換之兩數印出
end do
stop
end
 ! 交換兩數的函式 - swap
 subroutine swap(a, b)
 real a, b
 real temp
 temp = a     ! 將 a 值先做保留
 a=b       ! 將 b 的值置入 a 記憶體位置中
 b = temp     ! 將剛剛保留下的 a 值置入 b 記憶體位置中
 return     ! 返回呼叫程式
 end
語法:
Calling programs (main program, subroutines)
CALL <subr. name>[([<actual argument list>])]
--------------------------------------------------
Called programs (subroutines, intrinsic functions)
SUBROUTINE <subr. name>[([<dummy argument list>])]
END [SUBROUTINE [<subr. name>]] (Fortran 77只用END)
--------------------------------------------------
Note:Arguments are passed by reference: that is, their addresses are passed.
注意事項:
• 副程式的命名應有意義並且不隨意變更,因為副程式可能提供多個程式呼叫使用,
甚至由團隊中不同人員叫用;修正時,需修改原程式叫用部分並更新相關文件。
• 原始檔中,未規定主程式program與副程式subroutine先後順序;但編譯後執行,主
程式會被自動執行,副程式則是被動需被叫用才執行。
• 要返回主程式使用return指令,return可放在副程式中任意位置;使用stop會使主程
式也停止。
• 呼叫端可以是主程式,也可以是副程式。
• Fortran 90 進一步支援副程式自己呼叫自己,稱為遞迴。
•副程式除傳遞進入的變數外,可以獨立宣告屬於自己的變數,既使變數名稱與主
程式相同亦可。
• 副程式傳遞變數採用傳址呼叫(call by address / call by reference),即傳遞記憶體
位置,前例中,value1 和 a 指著相同的記憶體位置。
• 註:另一種稱「傳值呼叫」,在副程式中傳遞變數也會有獨立的記憶體位置,改
變內容不影響呼叫端的變數內容。
   Function(自訂函數)
舉例如下:
! 使用者輸入數字 x,計算 x2 - 2x + 1 值
program func_test
real x, y
 do while (.ture.)       ! 設定為無窮迴圈
   read *, x          ! 使用者輸入 x
   y = f(x)           ! 呼叫 f 函數計算 x2 - 2x + 1
   print *, y         ! y = f(x)、print *, y 兩行可合併為 print *,f(x)
 end do
end
------------------------------------------
real function f(x) ! 宣告函數 f 傳回的型態為real
real x
f = x**2 – 2*x + 1
return
end
語法:
Calling programs (main program, subroutines)
<function name>[([<actual argument list>])]
--------------------------------------------------
Called programs (functions)
[<type>] FUNCTION <func. name>[([<dummy argument list>])]
END [FUNCTION [<func. name>]] (Fortran 77只用END)
--------------------------------------------------
Passed by address: if an actual argument is a variable name, array name,
array element or a substring
Passed by value: if the actual argument is any other expression (including a
constant)
注意事項:
• 函數型態的宣告可以寫在函數的最開頭,如
  real function f(x)
或是放在變數宣告區塊,如
  function f(x)
  real f, x
• 呼叫端可將函數名稱做 EXTERNAL 宣告,表示該名稱不是變數,而
是函數名稱。當函數名稱做為變數傳遞時,不可省略。
• 叫用時不需使用 CALL 指令,直接寫出[名稱]即可,如
      print *, f(x)
      a = f(1.0) + f(2.0)
      b = f( f(1.0) )
• 傳遞變數若非運算式或常數,則採傳址呼叫,但在function中,一般
不會去改變該變數的內容,這是一個不成文的習慣。若要改變傳入變
數的內容,請改用subroutine。
   Statement Function

若函數只包含一個運算式,又只在同一個主程式或函式中被使用,可以
使用 statement function 的寫法,在 Function 中的例子變成:
program func_test
real x, f
f(x) = x**2 – 2*x + 1 ! 直接定義函數
do while (.ture)
read *, x        ! 使用者輸入 x
print *, f(x)     ! 呼叫 f 函數計算 x2 - 2x + 1,並輸出
end do
end
語法:
[<type>] <function name>
<function name>([<dummy argument list>])=<expression>
注意事項:
     • 上例中
       real x, f
       f(x) = x**2 – 2*x + 1
     叫用時不一定只能使用 f(x),可以是其他變數、常數或是運算式,
     如
       print *, f(a) , f(1.0) , f(a+2.0) , f(f(a))
    COMMON(全域變數)
不同的函式間,除了透過參數的傳遞來共享記憶體外,還可以經由「全域變數」
讓不同的函式中變數,使用相同的記憶體位置。請先看一個簡單的範例如下:
 program common_ex
 integer a, b
 common a, b
 a = 99
 b = 100
 call ShowCommon()
 end

 subroutine ShowCommon()
 integer num1, num2
 common num1, num2
 print *, num1, num2
 return
 end
   執行結果輸出所得為「99,100」
   其變數參照方式是以「位置對應」,上例中,主程式端宣告為全域變數第一
   個為 a ,第二個是 b ;而副程式 ShowCommon 中第一個是 num1 ,第二個
   是 num2 ;所以 num1 會指到同為第一個變數 a 的記憶體位置,num2 則會指
   到同為第二個變數 b 的記憶體位置。


• 利用位置對應的小技巧:(也讓你更清楚什麼是位置對應的關係)
主程式:common a,b
   integer a,b
副程式:common num
   integer num(2) ! 則num(1)對應到主程式的 a ,num(2)對應到主程式的 b
• 分組宣告:
   由於是按位置對應,在全域變數多時,宣告將成為困擾,假設共有十個全域
   變數,但副程式只需要最後兩個,仍要全部宣告:
   主程式program_main:common a,b,c,d,e,f,g,h,i,j
   副程式subroutine_1:common p,q,r,s,t       ! 只用前5個變數,故宣告5個
   即可
   副程式subroutine_2:common p,q,r,s,t,u,v,w,x,y ! 只用到最後兩個,但需全部
   宣告
   既使副程式subroutine_2只用到主程式中i,j兩變數,但由於全域變數是以宣告
   順序來對應,所以在副程式中,仍頇宣告十個全域變數,如此才能對應到我
   們要的第八和第九個變數i.j。
   要解決這個問題,讓程式碼更簡明,可以用以下的方法將全域變數「分組」
   主程式: common /group1/ a, b
      common /group2/ c, d
   副程式-1: common /group1/ num1. num2 ! 分別對應到主程式的 a, b
   副程式-2: common /group2/ num1. num2 ! 分別對應到主程式的 c, d
注意事項:
• 宣告成 COMMON 的變數,不能使用 DATA 來給定初值。
• 全域變數和傳遞參數一樣都可以讓不同的程序使用相同的變數內容,使用時機
有何不同呢?一般來說,若有許多不同的程序都會使用到相同的記憶體區塊,
便可以考慮宣告成全域變數。
• 全域變數不能宣告為常數。
• 全域變數宣告型態需一致,否則將造成讀取資料的錯誤:
(全域變數只是使用相同的記憶體區塊「起始位置」,至於區塊大小以及解碼
方式,按宣告型態而定)
    主程式:common a
        real a
        a = 1.0
    副程式:common num
        integer num ! 則num對應到主程式的 a
                  ! 但 a 為浮點數,num 為整數
        print *, num ! 輸出為 1065353216
上例來說,主程式 a = 1.0 ,浮點數表示法將記錄為
00111111100000000000000000000000,但 num 為整數,只讀取 2 位元組,且用
一般二進位補數表示法解讀,所得為 1065353216。
若num宣告為短整數(2位元組),又會有不同的結果。
   BLOCK DATA

上前一段 DATA 的範例中,若要使用 DATA 給定初值,需使用 BLOCK DATA
敘述。我們稍微修改範例如下:
 program common_ex
 integer a, b, c, d
 common a, b         ! 放在不具名的全域變數空間中
 common /group1/ c, d ! 放在分組名稱為 group1 的全域變數空間中
 print *, a, b, c, d
 end
  block data
  implicit none
  integer a, b
  common a, b
  data a, b /99, 100/
  integer c, d
  common /group1/ c, d
  data c, d /101, 102/
  end data block
執行結果為:「 99 100 101 102 」

注意事項:
• BLOCK DATA 類似副程式,但是不需要被別人呼叫。
• 在主程式執行前就會生效,意即主程式執行前,初值已寫入記憶體區塊中。
• 該段程式碼只放置與宣告有關的敘述,不可有設定初值以外的指令出現。
• 全域變數不能宣告為常數,故不能出現 PARAMETER 。
   傳址呼叫問題與技巧

• 字串傳遞問題:
副程式中需要宣告不定長度的字串(即字串長度由父程序中決定)
   function test(a,b,c)
   character*(*) a ! F77語法
   character(*) b ! F90語法
   character(len=*) c ! F90語法
   ...
   end function
 檔案處理

在檔案處理中,如果處理的檔案都是循序檔(sequential files),
即檔案中每一記錄 都是循序寫入的, 而且也必頇循序讀出。
表示要在循序檔中讀出一特定記錄, 之前所有記錄必頇先讀
出。另一種檔案稱為直接接達檔(direct-access files),檔案中每
一記錄可以直接讀寫, 通常是經由記錄號碼。直接接達檔中
所有記錄, 其長度必頇相同, 而且不能更動。循序檔中的記
錄長度可以變動。 檔案也可分成有格式和無格式兩種。目前
提及的檔案都是有格式的。有格式的檔案中記錄所含資訊是
用外顯字元的形式表示,而無格式的檔案中記錄則是用 二進
形式表示。因此無格式的檔案中記錄的確實形式, 隨機器而
有所不同。
   OPEN, CLOSE, 和 INQUIRE 敘述
       開檔
        在使用檔案輸入或輸出之前,檔案必頇先標明所用的單位規定式號碼。
        OPEN 敘述的一般形式為

               OPEN ( open-list )

        其中 open-list必頇包括

    單位規定式
     單位規定式的形式為, UNIT = integer-exp 或 integer-exp 其
     中 integer-exp 的數值是零或正整數, 指定檔案的單位號碼。
     READ 或 WRITE 敘述使用此單位號碼讀寫其連接的檔案。
     使用第二種形式時, integer-exp必頇是open-list的第一項。
FILE = 子句
FILE = 子句的形式為, FILE = char-exp 其中 char-exp (略去末尾的空白)是單位號
碼所連接的檔案名稱。
STATUS = 子句
STATUS = 子句的形式為, STATUS = char-exp 其中 char-exp (略去末尾的空白) 之
值是下列之一: OLD 舊檔, 必頇用 FILE = 子句規定檔名。 NEW 新檔, 必頇用
FILE = 子句規定檔名。 SCRATCH 草稿檔, 必頇不用檔名。 UNKNOWN 未知檔,
以上皆非。 若省略 STATUS = 子句, 則預設為未知檔。
IOSTAT = 子句
FILE = 子句的形式為, IOSTAT = int-var 其中 int-var 之值為零或正整數。 開檔順
利, 則為零。否則為正整數, 代表系統手冊中的錯誤信文之號碼。
ERR = 子句
ERR = 子句的形式為, ERR = n 其中 n 規定若在開檔發生錯誤時,所要執行檔案
的號碼。
ACCESS = 子句
ACCESS = 子句的形式為, ACCESS = char-exp 其中 char-exp (略去末尾的空
白) 之值是下列之一: SEQUENTIAL 規定檔案是循序 DIRECT 規定檔案是直接
若省略此子句, 則預設為循序檔。
FORM = 子句
FORM = 子句的形式為, FORM = char-exp 其中 char-exp (略去末尾的空白)
之值是下列之一: FORMATTED 規定檔案是有格式的 UNFORMATTED 規定檔
案是無格式的 若省略此子句, 則循序檔預設為有格式的, 而直接檔預設為無
格式的。
RECL = 子句
RECL = 子句的形式為, RECL = int-exp 其中 int-exp 之值為正。 此子句只在
直接接達檔使用,規定其記錄長度。 在有格式檔, 指的是 該檔每一記錄的字
元數,在無格式檔, 則視處理器(processor)而定。
BLANK = 子句
BLANK = 子句的形式為, BLANK = char-exp 其中 char-exp (略去末尾的空白)
之值是下列之一: ZERO 規定數值欄中的空白是當做 0。 NULL 規定略過數值
欄中的空白。 若數值欄中全是空白, 則不論 ZERO 或 NULL, 都當做 0。
    關檔
CLOSE 敘述用以切斷檔案和單位號碼的連接。 CLOSE 敘述的一般形式為
CLOSE ( close-list ) 其中 close-list
必頇包括單位規定式
  也可包括選自下列的其他規定式:
IOSTAT =子句,指示檔案是否順利關閉。
ERR =子句,規定若在關檔發生錯誤時,所要執行檔案的號碼。
STATUS =子句,規定檔案要保留或刪除。

STATUS = 子句的形式為, STATUS = char-exp 其中 char-exp (略去末尾的空白) 之
   值是下列之一: KEEP 規定關檔後保留該檔。 DELETE 規定關檔後刪除該檔。
   SCRATCH 檔不可用 KEEP。 若省略 STATUS = 子句, 則刪除草稿檔, 保留其
   他類型的檔案。 檔案用CLOSE 敘述關閉後, 可以再用OPEN敘述打開,可用
   同一單位號碼, 也可用不同的 號碼。 所有未關閉的檔案,在程式終止執行時
   (由於發生錯誤而導致的不正常終止除外),都自動關閉。

								
To top