穿孔卡片
我在讀一些關於早期編程語言歷史的文章時,經常看到"穿孔卡片(punched card)"這個名詞。但對現代計算機習以為常的我, 並不知道它是什么,它是怎么工作的以及為什么要用它。
#穿孔卡片是什么
形式上,穿孔卡片就是一張紙卡片。這個紙卡片被分為N行M列的格子。IBM的12行80列的穿孔卡片曾是主流。每個格子都可以選擇打孔或不打孔。可以把它想象成一個大小12*80的二維布爾數組。 許多早期的數字計算機使用穿孔卡片作為計算機程序和數據輸入的主要媒介(一個程序可能得用很多張卡片,因為一張卡片通常值表示一行代碼)。

圖中黑色的是洞。從上往下分別叫為第12行,第11行,第10行(或者第0行),第1,2,...,9行。
#穿孔卡片怎么工作
穿孔卡片的每一列用來表示一個字符(比如數字,字母),這樣一來80列就能表示80個字符(也有說法是IBM 701會把最后8列作為其它用途,比如記錄卡片序號。這樣一來一張卡片就是表示 72個字符)。
編碼規則
- 某列要表示數字0到9,則在該列相應的第n行打一個孔,其它行不打孔
- 在第12行打一個孔,第1到第9行打孔分別表示字母A,B,...,I
- 在第11行打一個孔,第1到第9行打孔分別表示字母J,K,...,R
- 在第10行打一個孔,第2到第9行打孔分別表示字母S,T,...,Z
如下圖,每一列頂上的字符就是這一列所代表的含義

#鍵盤打孔器
但那個年代的編程並不就是手動在這些卡片上打孔,有個叫鍵盤打孔器(keypunch)的設備可以專門用來打孔,鍵盤上輸入1, 就在當前列的第1行打一個孔,然后到下一列。 負責用鍵盤打孔器打孔的操作員通常是女性。所以編程整體流程上是:
- 在紙上寫段程序
- 給人照着用鍵盤打孔器打孔
- 拿卡片作為輸入給計算機運行
#為什么用穿孔卡片
在計算機屏幕和鍵盤已經存在的年代(1950),為什么程序員會在打孔卡上不是在終端上編寫他們的程序?
分時和多用戶系統是在二十世紀50年代后期發明的,但他們在整個60年代也並不常見。大多數計算機都是以批處理模式運行,一次運行一個程序。 假如有一個交互式編輯程序讓你坐在電傳打字機和計算機前寫代碼,由於批處理的存在,編輯程序將完全壟斷計算機。而同時很多人還在等着運行他們的程序。 同時,你編輯代碼時,也會被收錢。這樣看來,先寫好代碼再轉錄到穿孔卡片最后交給計算機運行顯然是一種更划算的方案。
#穿孔卡片與Fortran
在Fortran 90之前,大多數Fortran編譯器都要求Fortran代碼以固定列格式編寫,這正是因為代碼輸入需要使用穿孔卡片。
- 第一列為*或C或!表示這一行是注釋
- 第1到5列表示語句(statement)的標簽,比如
GO TO語句就可以用這個標簽,實現跳轉 - 連續行必須在第6列有一個非空白字符
- 語句必須從第7列開始
- 行的字符個數被限制在72個,因為正如之前提到過,在一張80列的穿孔卡片中,最后8列保留為其它用途了,比如記錄卡片序號。(一張卡片一行代碼,有個序號弄亂了還可以方便排序回來)
下面是一段計算三角形面積的Fortran II代碼示例
C AREA OF A TRIANGLE - HERON'S FORMULA C INPUT - CARD READER UNIT 5, INTEGER INPUT C OUTPUT - C INTEGER VARIABLES START WITH I,J,K,L,M OR N READ(5,501) IA,IB,IC 501 FORMAT(3I5) IF(IA.EQ.0 .OR. IB.EQ.0 .OR. IC.EQ.0) STOP 1 S = (IA + IB + IC) / 2.0 AREA = SQRT( S * (S - IA) * (S - IB) * (S - IC) ) WRITE(6,601) IA,IB,IC,AREA 601 FORMAT(4H A= ,I5,5H B= ,I5,5H C= ,I5,8H AREA= ,F10.2, $13H SQUARE UNITS) STOP END
上面的每一行代碼會分別記錄在一張穿孔卡片。 前4行以C開頭,表示注釋。第6行是輸入三個整數IA,IB,IC(I表示整數),第7行的501是標簽,后面的601也是標簽。 READ, WRITE這些輸入輸出語句用了FORMAT語句的標簽做參數,具體用法是什么,暫時就不考究了。
