乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      異常處理

       遠(yuǎn)在南非 2010-08-18
      delphi中異常的截獲及其個(gè)性化處理

      黃悅、謝曉東

      【摘要】應(yīng)用程序中的異常幾乎是不可避免的,本文探討了delphi的異常處理機(jī)制和異常處理的幾種方法,并結(jié)合一些實(shí)例介紹如何根據(jù)應(yīng)用程序的需要開發(fā)自己的異常處理程序。


      一、 異常及異常處理機(jī)制


      異常可以理解為一種特殊的事件,當(dāng)這種特殊的事件發(fā)生時(shí),程序正常的執(zhí)行流程將被打斷。異常處理機(jī)制能夠確保在發(fā)生異常的情況下,應(yīng)用程序不會(huì)中止運(yùn) 行,并且能以一致的風(fēng)格進(jìn)行處理。許多剛剛涉及delphi的程序員感覺異常處理機(jī)制高深莫測(cè),是高級(jí)程序員的“專利”,總有盡可能繞開它的想法,因而不 得不小心翼翼地檢查每一次函數(shù)調(diào)用的返回值,或者通過額外的代碼捕獲可能的錯(cuò)誤,即使這樣,也只能保證程序代碼不出錯(cuò),而無法保證包括操作系統(tǒng)、設(shè)備驅(qū)動(dòng) 程序、數(shù)據(jù)庫驅(qū)動(dòng)程序、delphi自身的元件庫和運(yùn)行時(shí)間庫在內(nèi)的軟硬件設(shè)備不出錯(cuò)。問題就在于,通過檢查函數(shù)的返回值或設(shè)置錯(cuò)誤陷阱只能捕獲可預(yù)見的 錯(cuò)誤,如果出現(xiàn)沒有預(yù)見到的錯(cuò)誤,或者函數(shù)調(diào)用本身就已失敗,程序正常的流程就會(huì)被打亂。由此可見,異常幾乎是不可避免的。其實(shí),object pascal提供了多種異常處理方法,使異常的處理變得輕而易舉,可以將你從為你的應(yīng)用程序執(zhí)行的每個(gè)任務(wù)編寫單獨(dú)的錯(cuò)誤處理程序的繁瑣工作中解放出來。


      二、 處理異常的方法


      1. try...except 結(jié)構(gòu)

      try...except 結(jié)構(gòu)是這樣工作的:try后面到except之前的語句通常是希望正常執(zhí)行的代碼,在執(zhí)行過程中如果觸發(fā)了異常,程序就跳入except部分。在except部分做出的處理可以有以下三種類型:

      (a) 不需要確切知道異常的類型,只需要做籠統(tǒng)的處理時(shí),可以彈出一個(gè)警告信息框,或者釋放已分配的資源,或者退出程序。程序示例如下:

      例1 procedure tform1.button1click(sender :tobject)

      var

      num: integer;

      begin

      try

      num:=strtoint(edit1.text);

      edit2.text:=inttostr(num*num);

      except

      showmessage(edit1.text+'無法轉(zhuǎn)成整數(shù)!');

      end;

      end;

      該例中,點(diǎn)擊button1后,程序試圖將編輯框edit1中的內(nèi)容轉(zhuǎn)換為整型數(shù),整數(shù)平方之后再轉(zhuǎn)換成字符串類型數(shù)據(jù),在編輯框edit2中顯示。 如果edit1.text是7.89,傳遞給strtoint將產(chǎn)生econverterror異常,因?yàn)?.89不是一個(gè)有效整數(shù)。異常產(chǎn)生后,將顯示 一條警告信息,并退出該過程。

      (b) 利用異常處理句柄處理某個(gè)特定的異常

      例如,在例1中可以針對(duì)econverterror異常做出如下的處理:

      例2 procedure tform1.button1click(sender :tobject)

      var

      num: integer;

      begin

      try

      num:=strtoint(edit1.text);

      edit2.text:=inttostr(num*num);

      except

      on econverterror do showmessage(edit1.text+'無法轉(zhuǎn)成整數(shù)!');

      end;

      end;

      (c) 利用異常處理句柄處理多種異常

      通常,執(zhí)行的代碼不只產(chǎn)生一種異常,這就需要在except部分進(jìn)行更具體的測(cè)試,根據(jù)產(chǎn)生的異常類型分別做出處理?,F(xiàn)將例2稍加改動(dòng)如下:

      例3 procedure tform1.button1click(sender :tobject)

      var

      num: integer;

      begin

      try

      num:=strtoint(edit1.text);

      edit2.text:=inttostr(30 div num);

      except

      on econverterror do showmessage(edit1.text+'無法轉(zhuǎn)成整數(shù)!');

      on edivbyzero do

      begin

      showmessage('除數(shù)不能為零!');

      edit2.text:='0';

      end;

      end;

      end;

      在例3中,try部分的第一條語句可能產(chǎn)生econverterror 異常;當(dāng) num為零時(shí),try 部分的第二條語句還會(huì)產(chǎn)生被零除的異常(即產(chǎn)生edivbyzero 異常)。由于產(chǎn)生異常原因不同,需要分別進(jìn)行不同的處理。例3中的except 部分的代碼也可以寫成以下的形式,這兩種異常處理的結(jié)果是一樣的。

      except

      on e:exception do

      begin

      if e is econverterro then showmessage(edit1.text+'無法轉(zhuǎn)成整數(shù)!');

      if e is edivbyzero then

      begin

      showmessage('除數(shù)不能為零!');

      edit2.text:='0';

      end;

      end;

      2. try...finally 結(jié)構(gòu)

      try...finally 結(jié)構(gòu)最大的用處是在異常發(fā)生的情況下,確保釋放應(yīng)用程序已經(jīng)分配的資源,或者完成一些必須的操作,比如:剪貼板clipboard 在打開之后必須調(diào)用close 方法將剪貼板關(guān)閉;數(shù)據(jù)感知組件更新禁止之后必須調(diào)用enablecontrols方法才能使更新顯示有效等。try...finally 結(jié)構(gòu)之所以能做到這一點(diǎn),是因?yàn)椴还墚惓J欠癜l(fā)生,程序都要執(zhí)行finally 部分。請(qǐng)看下面的例子:

      例4 procedure tform1.button1click(sender :tobject)

      var

      icon : ticon;

      begin

      try

      icon:=ticon.create;

      icon.loadfromfile('spin.ico');

      imagelist1.replaceicon(0,icon);

      finally

      icon.free;

      end;

      end;

      在例4中,try 部分代碼是從磁盤獲取一個(gè)圖標(biāo),用來代替imagelist1 中的0號(hào)圖標(biāo)。如果圖標(biāo)文件spin.ico 不存在或者被損壞,將會(huì)產(chǎn)生efopenerror 異常,中斷 try 部分代碼的執(zhí)行,但是程序會(huì)執(zhí)行finally 部分的代碼,使得icon 占用的資源得以釋放。當(dāng)然,如果沒有發(fā)生任何異常,finally 部分也將被執(zhí)行??梢哉f,finally 部分是 try...finally 結(jié)構(gòu)的“必經(jīng)之路”。

        3. try...except 與try...finally 的嵌套結(jié)構(gòu)

      try...finally 結(jié)構(gòu)確實(shí)有它獨(dú)到的功能,但是try...finally結(jié)構(gòu)中沒有 try...except 結(jié)構(gòu)中的異常處理句柄,也就無法知道當(dāng)前確切的異常類型,并且不論異常是否發(fā)生,程序都執(zhí)行 finally 部分,這就決定了 try...finally 結(jié)構(gòu)無法對(duì)發(fā)生的異常進(jìn)行特別的處理。如果在應(yīng)用程序中,既需要完成一些必要的操作,又要對(duì)發(fā)生的異常進(jìn)行處理,那么最好使用這兩種結(jié)構(gòu)的嵌套。請(qǐng)看下 例:

      例5 procedure tform1.button1click(sender :tobject)

      var

      icon : ticon;

      begin

      try

      try

      icon:=ticon.create;

      icon.loadfromfile('spin.ico');

      imagelist1.replaceicon(0,icon);

      finally

      icon.free;

      end;

      except

      on efopenerror do showmessage('無法打開圖標(biāo)文件spin.ico');

      end;

      end;

      在例5中,無論異常發(fā)生與否,都將執(zhí)行finally 部分釋放圖標(biāo)占用的資源。一旦異常發(fā)生,則產(chǎn)生警告信息。上例是在 try...except 結(jié)構(gòu)的 try 部分嵌套 try...finally 結(jié)構(gòu),也可以在 try...finally 結(jié)構(gòu)的 try 部分嵌套 try...except 結(jié)構(gòu),前者是先執(zhí)行必須的操作,再進(jìn)行異常的處理,而后者是先進(jìn)行異常的處理,再執(zhí)行必須的操作。在多數(shù)情況下,兩者的區(qū)別并不大。除此之 外,try...except 結(jié)構(gòu)和try...finally 結(jié)構(gòu)還可以各自嵌套。在復(fù)雜的應(yīng)用程序中,except 部分或finally部分的異常處理代碼本身又有可能觸發(fā)異常,這就需要采用嵌套結(jié)構(gòu)編寫更深一層的異常處理代碼,這里就不再詳細(xì)舉例了。

      4. 定義自己的異常類

      我們的探討將進(jìn)入更深的一層——定義自己的異常類。雖然在簡(jiǎn)單的應(yīng)用程序中,程序員并無太大必要定義自己的異常類,但是它對(duì)編寫個(gè)性化的異常處理程序 仍然是有幫助的。例7中的過程是對(duì)數(shù)據(jù)集 table1 中的字段name進(jìn)行合法性檢查,如果name 沒有值或?yàn)榭兆址瑒t產(chǎn)生異常,這其中就定義了一個(gè) exception 的派生類emyexception。

      例6

      type emyexception=class(exception); {定義自己的異常類emyexception}

      procedure tform1.table1namevalidate(sender : tfield);

      begin

      if ( sender.isnull ) or ( sender.asstring='') then

      raise emyexception.create('必須填寫名稱');

      end;


      三、個(gè)性化的異常處理句柄


      delphi會(huì)自動(dòng)處理大部分的異常,但全英文信息提示會(huì)讓應(yīng)用程序的最終用戶感覺并不友好。那么如何編寫自己的異常處理代碼呢? 在forms單元中聲明的tapplication 類中的onexception 事件為編寫自己的異常處理代碼提供了可能。事實(shí)上,用于onexception 事件的事件句柄就是應(yīng)用程序默認(rèn)的異常處理句柄。請(qǐng)看下面的例子。

      在 project resource 中,首先創(chuàng)建一個(gè)新類 tmyclass, tmyclass 中有一個(gè)myexceptionhandler 方法,可以根據(jù)應(yīng)用程序的需要來編寫,這里體現(xiàn)了個(gè)性化的異常處理。由myexceptionhandler事件來響應(yīng)application 的 onexception事件,這樣在程序發(fā)生異常時(shí),首先調(diào)用的就是自己編寫的異常處理事件myexceptionhandler事件。工程文件如下:

      例7

      program exceptprj;

      uses

      forms, windows, sysutils, classes, dialogs, db, dbtables,

      example in 'example.pas' {form1};



      {創(chuàng)建一個(gè)tobject的派生類tmyclass}

      type

      tmyclass=class(tobject)

      public

      procedure myexceptionhandler(sender: tobject; einstance: exception);

      end;

      {編寫自己的異常處理句柄}

      procedure tmyclass.myexceptionhandler(sender: tobject; einstance: exception);

      var

      errorfile:textfile;

      filename,content:string;

      findflag:boolean;

      begin

      {截獲出現(xiàn)的新的異常,并存入文件errorinfo.txt.}

      filename:=applicationpath+'errorinfo.txt'; { applicationpath 是在主form中定義的全局變量,記錄應(yīng)用程序所在的目錄}

      {打開文件}

      assignfile(errorfile,filename);

      if not fileexists(filename) then

      rewrite(errorfile)

      else

      reset(errorfile);



      {檢查出現(xiàn)的異常是否曾經(jīng)記錄在文件errorinfo.txt中}

      findflag:=false;

      while not seekeof(errorfile) do

      begin

      readln(errorfile,content);

      if pos(einstance.classname+':'+einstance.message,content)<>0 then

      begin

      findflag:=true;

      break;

      end;

      end;

      {如果是一個(gè)未被記錄過的異常,則將它記錄在文件中}

      if not findflag then

      begin

      showmessage('出現(xiàn)新的錯(cuò)誤!');

      append(errorfile);

      writeln(errorfile,einstance.classname+':'+einstance.message);

      end;

      {關(guān)閉文件}

      closefile(errorfile);



      {對(duì)出現(xiàn)的異常顯示中文提示}

      if einstance is edivbyzero then

      application.messagebox('除數(shù)不能為零!','錯(cuò)誤',mb_ok+mb_iconstop)

      else if einstance is eaccessviolation then

      application.messagebox('訪問了無效的內(nèi)存區(qū)域!','錯(cuò)誤',mb_ok+mb_iconstop)

      else if (einstance is edatabaseerror) then

      application.messagebox('數(shù)據(jù)庫操作出現(xiàn)錯(cuò)誤!','錯(cuò)誤',mb_ok+mb_iconstop)

      else if (einstance is efopenerror) then

      application.messagebox('文件不能打開!','錯(cuò)誤',mb_ok+mb_iconstop)

      else if (einstance is econverterror) then

      application.messagebox('非法的類型轉(zhuǎn)換!','錯(cuò)誤',mb_ok+mb_iconstop)

      else

      messagedlg(einstance.classname+':'+einstance.message,mtinformation,[mbok],0)

      end;



      {$r *.res}



      var

      myobject: tmyclass; {聲明tmyclass類的一個(gè)變量}



      begin

      application.initialize;

      application.createform(tform1, form1);

      applicationpath:=extractfilepath(application.exename);



      myobject:=tmyclass.create; {創(chuàng)建tmyclass類的一個(gè)實(shí)例}

      application.onexception:=myobject.myexceptionhandler; {響應(yīng)onexception事件}



      application.run;

      end.

      例7中的myexceptionhandler 事件是我們?cè)陂_發(fā)鐵路車站行車工作細(xì)則管理系統(tǒng)時(shí)編制的,由于篇幅所限,在此僅將這一事件的整體框架呈現(xiàn)給大家,希望通過這個(gè)例子來說明開發(fā)異常處理句柄的方法。



      到此為止,我們對(duì)delphi異常處理的幾種方法由淺入深地進(jìn)行了歸納,并對(duì)應(yīng)于各種方法列舉了實(shí)例,希望對(duì)異常處理懷有“膽怯”心理的編程朋友有所幫助。當(dāng)然,在遇到具體問題的時(shí)候,還需要您選擇最適合的異常處理方法。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多