編譯器進行詞法分析時,不可避免地需要對原始檔進行掃瞄,實現該功能的模組稱為掃瞄器。掃瞄器讀取原始檔,按序返回檔案內的字元,直到檔案結束。
掃瞄器的功能
實現檔案的讀一般使用庫函式fscanf或者fread,那麼按照怎樣的讀取方式才能讓掃瞄器的效能更佳呢?
(1)使用fscanf逐字掃瞄,並返回。
char scan(file*file)
return ch; }
這是最簡單的實現方式,缺點是每次讀取字元時都需要訪問檔案進行io。
我們先看看它的效率,首先在主函式內呼叫掃瞄器。
//主函式
int main()
主函式內使用掃瞄器掃瞄測試檔案1000000次,然後使用time命令檢視**的執行時間(測試檔案可以是任意檔案,這裡不給出檔案內容了,區別只是執行的時間不同而已)。
$ time main
我們測試了五次,並取了平均值(單位:ms)。 次數
1 23 4
5平均值
real
370366
374368
377371
user
112140
132144
140133.6
sys256
228240
224232
236可以計算**的cpu平均執行時間為133.6+236=369.6ms。
(2)使用fscanf和緩衝區結合的方式,每次讀取字元時首先嘗試從緩衝區內取,緩衝區為空時使用fscanf重新載入緩衝區。
#define buflen 80
int linelen=0;
int readpos=-1;
char line[buflen];
char scan(file*file)
linelen=pos;//記錄緩衝區長度
readpos=-1;//恢復讀取位置
}readpos++;//移動讀取點
return line[readpos]; //獲取新的字元 }
按照前邊的方式測試**的執行時間。 次數
1 23 4
5平均值
real
374380
371371
374374
user
140124
148136
108131.2
sys232
252220
232264
240計算**的cpu平均執行時間為131.2+240=371.2ms。雖然這種方法只是在緩衝區為空時重新載入緩衝區,避免了每次讀取符號進行檔案io的問題,但是卻比第一種方式的效能還差。主要是因為載入緩衝區時使用fscanf是按照位元組進行載入的,如果使用fread可能會不同。
(3)和方法二類似,只是載入緩衝區時使用fread。fread的引數size表示載入資料塊的大小,count表示載入資料塊的個數,這裡每次載入buflen個1位元組資料塊。
#define buflen 80
int linelen=0;
int readpos=-1;
char line[buflen];
char scan(file*file)
linelen=pos;//記錄緩衝區長度
readpos=-1;//恢復讀取位置
}readpos++;//移動讀取點
return line[readpos]; //獲取新的字元 }
測試**的執行時間。 次數
1 23 4
5平均值
real
339332
334341
332335.6
user 96
92116
108 84
99.2
sys244
236216
228244
233.6
計算**的cpu平均執行時間為99.2+233.6=332.8ms,可見使用fread讀取檔案比使用fscanf的效率要高。該方法是每次載入buflen個1位元組資料塊,如果每次載入1個buflen位元組資料塊是不是更高效呢?
(4)和方法三類似,只是這裡每次載入buflen個1位元組資料塊。
#define buflen 80
int linelen=0;
int readpos=-1;
char line[buflen];
static int offset=0;//記錄檔案指標的偏移,每次開啟檔案需要初始化為0
char scan(file*file)
else
linelen=pos;//記錄緩衝區長度
readpos=-1;//恢復讀取位置
}readpos++;//移動讀取點
return line[readpos]; //獲取新的字元 }
測試**的執行時間。 次數
1 23 4
5平均值
real
2241
2223
2259
2223
2221
2233.4
user
620540
616600
648604.8
sys1616
1680
1640
1620
1568
1624.8
計算**的cpu平均執行時間為604.8+1624.8=2229.6ms,這有點出乎意料。分析原因,可能是因為檔案較小時,當讀取到最後一塊緩衝區時,撤回檔案指標比較消耗時間。因此,使用方法三實現的掃瞄器效能更穩定,且**更簡潔。
(5)如果使用fread不是讀入1個buflen位元組資料,而是讀取buflen/2個2位元組資料,那麼最後一次將讀入最後乙個位元組。
#define buflen 80
int linelen=0;
int readpos=-1;
char line[buflen];
char scan(file*file)
else
linelen=pos;//記錄緩衝區長度
readpos=-1;//恢復讀取位置
}readpos++;//移動讀取點
return line[readpos]; //獲取新的字元 }
測試**的執行時間。 次數
1 23 4
5平均值
real
663657
646665
659658
user
208224
204212
184206.4
sys452
428440
456472
449.6
計算**的cpu平均執行時間為206.4+449.6=656ms。雖然該方法不需要撤回檔案指標,但是效能仍不如方法三。
掃瞄器的高效實現
掃瞄器的高效實現 編譯器進行詞法分析時,不可避免地需要對原始檔進行掃瞄,實現該功能的模組稱為掃瞄器。掃瞄器讀取原始檔,按序返回檔案內的字元,直到檔案結束。掃瞄器的功能 實現檔案的讀一般使用庫函式fscanf或者fread,那麼按照怎樣的讀取方式才能讓掃瞄器的效能更佳呢?1 使用fscanf逐字掃瞄,...
python實現高效的埠掃瞄器基礎
一 點睛 如今網際網路安全形勢日趨嚴峻,給系統管理員帶來很大的挑戰,網路的開放性以及黑客的攻擊是造成網路不安全的主因。稍有疏忽將給黑客帶來可乘之機,給企業帶來無法彌補的損失。比如由於系統管理員誤操作,導致核心業務伺服器的22 21 3389 3306等高危埠暴露在網際網路上,大大提高了被入侵的風險。...
掃瞄器詳解
一 掃瞄器的定義 掃瞄器是一種獲取影象的裝置,並將資訊轉為電腦可以顯示 編輯 儲存和輸出的數字格式。即可以完成以下工作 在檔案中插隊圖和 將文字識別,免去打字 將傳真檔案掃到庫中存檔 在多 中加入影象 在報刊中加入有效表達主題。二 掃瞄器的工作原理 將光線照到待掃瞄的稿件上,光線反向回平後再由乙個稱...