掃瞄器的高效實現

2021-12-29 22:29:59 字數 3390 閱讀 4160

編譯器進行詞法分析時,不可避免地需要對原始檔進行掃瞄,實現該功能的模組稱為掃瞄器。掃瞄器讀取原始檔,按序返回檔案內的字元,直到檔案結束。  

掃瞄器的功能

實現檔案的讀一般使用庫函式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等高危埠暴露在網際網路上,大大提高了被入侵的風險。...

掃瞄器詳解

一 掃瞄器的定義 掃瞄器是一種獲取影象的裝置,並將資訊轉為電腦可以顯示 編輯 儲存和輸出的數字格式。即可以完成以下工作 在檔案中插隊圖和 將文字識別,免去打字 將傳真檔案掃到庫中存檔 在多 中加入影象 在報刊中加入有效表達主題。二 掃瞄器的工作原理 將光線照到待掃瞄的稿件上,光線反向回平後再由乙個稱...