版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、19第5章 使用復合賦值和循環(huán)語句第5章 使用復合賦值和循環(huán)語句本章旨在教會你:l 使用復合賦值操作符更新變量值l 使用while、for和do循環(huán)語句l 單步執(zhí)行do語句,觀察變量值的變化第4章講述了如何使用if和switch語句選擇性地運行語句。本章要介紹如何使用各種循環(huán)語句重復運行一個或多個語句。寫循環(huán)語句時通常要控制重復次數(shù)。為此可以使用一個變量,每次重復都更新它的值,并在變量抵達特定值時停止重復。因此,還要介紹如何在這些情況下使用特殊的賦值操作符來更新變量值。5.1 使用復合賦值操作符前面講過如何使用算術操作符創(chuàng)建新值。例如以下語句使用操作符+創(chuàng)建比變量answer大42的值,新值在
2、控制臺顯示:Console.WriteLine(answer + 42);前文還講過如何使用賦值語句更改變量值。以下語句使用賦值操作符=將answer的值變成42:answer = 42;要在變量的值上加42,可在同一個語句中使用賦值和加法操作。例如,以下語句在answer上加42,新值再賦給answer。換言之,在運行該語句之后,answer的值比之前大42:answer = answer + 42; 雖然這是有效的語句,但有經(jīng)驗的程序員不會這樣寫。在變量上加一個值是常見操作,所以C#專門提供了+=操作符來簡化它。要在answer上加42,有經(jīng)驗的程序員會像下面這樣寫:answer += 4
3、2;類似,可將任何算術操作符與賦值操作符合并見下表。這些操作符稱為復合賦值操作符。不要這樣寫要這樣寫variable = variable * number;variable *= number;variable = variable / number;variable /= number;variable = variable % number;variable %= number;variable = variable + number;variable += number;variable = variable - number;variable -= number;提示復合賦值操作符和
4、簡單賦值操作符具有一樣的優(yōu)先級和右結(jié)合性。操作符+=可用于字符串;作用是將一個字符串附加到另一個字符串末尾。例如,以下代碼在控制臺上顯示Hello John:string name = John;string greeting = Hello ;greeting += name;Console.WriteLine(greeting);但其他任何復合賦值操作符都不能用于字符串。注意變量遞增或遞減1不要使用復合賦值操作符,而是使用操作符+和-。例如,不要像下面這樣寫:count += 1;而是像下面這樣寫:count+;5.2 使用while語句使用while語句,可在條件為true的前提下重復運
5、行一個語句。while語句的語法如下:while ( booleanExpression ) statement先求值booleanExpression(布爾表達式,注意必須放在圓括號中),如果為true,就運行語句(statement)。再次求值booleanExpression,仍為true就再次運行語句。再次求值booleanExpression這個過程一直繼續(xù),直至結(jié)果為false,此時while語句退出,從while構(gòu)造之后的第一個語句繼續(xù)。while語句在語法上與if語句有許多相似的地方(事實上,除了關鍵字不同,語法完全相同),具體如下。l 表達式必須是布爾表達式。l 布爾表達式必
6、須放在圓括號中。l 首次求值布爾表達式為false,語句不運行。l 要在while的控制下執(zhí)行兩個或更多語句,必須用大括號將語句分組成代碼塊。以下while語句向控制臺寫入值09。一旦變量i的值變成10,while語句中止,不再運行代碼塊。int i = 0;while (i 10) Console.WriteLine(i); i+;所有while語句都應在某個時候終止。新手常見錯誤是忘記添加語句最終造成布爾表達式求值為false來終止循環(huán)。在上例中,這個語句就是i+;。注意while循環(huán)的變量i控制循環(huán)次數(shù)。這是常見的設計模式,具有這個作用的變量有時也稱為哨兵變量。還可創(chuàng)建嵌套循環(huán),這種情況
7、下一般延續(xù)該命名模式來使用j,k甚至l等作為哨兵變量名。提示和if語句一樣,建議總是為while語句使用代碼塊,即使其中只有一個語句。這樣以后添加代碼更省心。如果不這樣做,只有while后的第一個語句才會與之關聯(lián),造成難以發(fā)現(xiàn)的bug。例如以下代碼: int i = 0; while (i 10) Console.WriteLine(i); i+;代碼將無限循環(huán),無限顯示零,因為只有Console.WriteLine語句才和while關聯(lián),i+;語句雖然縮進但編譯器不把它視為循環(huán)主體的一部分。以下練習寫一個while循環(huán),每次從源文件讀取一行內(nèi)容,將其寫入文本框。 編寫while語句1.在Vi
8、sual Studio 2013中打開WhileStatement項目,它位于“文檔”文件夾下的Microsoft PressVisual CSharp Step by StepChapter 5Windows XWhileStatement子文件夾中。2.在“調(diào)試”菜單中選擇“啟動調(diào)試”。Visual Studio 2013生成并運行應用程序。應用程序本身是一個簡單的文本文件查看器,用于打開文件并查看內(nèi)容。3.單擊Open File。如果使用Windows 8.1,將打開文件選取器并顯示“文檔”文件夾的內(nèi)容(如果使用Windows 8.1 Updatre1以后的版本,則顯示OneDrive的
9、“文檔”文件夾中的內(nèi)容),如下圖所示(在你的計算機上,文件和文件夾列表可能有所不同)。如果使用Windows 7,將顯示“打開”對話框,如下圖所示。無論什么操作系統(tǒng),都可利用該功能切換至一個文件夾并選擇要顯示的文件。4.切換到這臺電腦“文檔”文件夾下的Microsoft PressVisual CSharp Step by StepChapter 5Windows XWhileStatementWhileStatement子文件夾。5.選擇MainWindow.xaml.cs文件,單擊“打開”按鈕。文件名MainWindow.xaml.cs在小文本框顯示,但文件內(nèi)容沒有在大文本框中顯示。這是由
10、于尚未實現(xiàn)代碼來讀取并顯示源文件內(nèi)容。下面的步驟將添加這個功能。6.返回Visual Studio 2013并停止調(diào)試。7.在“代碼和文本編輯器”窗口中打開MainWindow.xaml.cs文件,找到openFileClick方法。在“打開”對話框中選擇文件并單擊“打開”按鈕后將調(diào)用該方法。應用程序的不同版本以不同方式實現(xiàn)該方法。目前不需要理解方法的細節(jié),只需知道方法提示用戶指定文件(通過FileOpenPicker或OpenFileDialog窗口)并打開指定文件以進行讀取。(在Windows 7版本中,方法只是顯示OpenFileDialog窗口。當用戶選擇文件并單擊“打開”按鈕后,將調(diào)
11、用openFileDialogFileOk方法來打開文件以進行讀取。)openFileClick方法(Windows 8.1)或openFileDialogFileOk方法(Windows 7或Windows 8)的最后兩個語句很重要。Windows 8.1版本如下:TextReader reader = new StreamReader(inputStream.AsStreamForRead();displayData(reader);第一個語句聲明TextReader變量reader。TextReader是.NET Framework提供的類,用于從文件等來源讀取字符流。它在System.
12、IO命名空間中。該語句使用戶指定文件中的數(shù)據(jù)可供TextReader對象使用,然后利用該對象從文件讀取數(shù)據(jù)。最后一個語句調(diào)用displayData方法,將reader作為參數(shù)傳遞。方法使用reader對象讀取數(shù)據(jù)并在屏幕上顯示,稍后將實現(xiàn)該方法。Windows 7版本對應的語句如下:TextReader reader = src.OpenText();displayData(reader);src變量是FileInfo對象,填充了用戶所選文件的信息。FileInfo類也是.NET Framework提供的類,它的OpenText方法用于打開文件以進行讀取。第一個語句打開所選文件,使reader
13、變量能接收文件內(nèi)容。和Windows 8.1版本一樣,最后一個語句調(diào)用displayData方法并將reader作為參數(shù)傳遞。8.找到displayData方法。它的兩個版本是相同的:private void displayData(TextReader reader) / TODO: add while loop here主體只有一行代碼,馬上就要添加代碼來獲取并顯示數(shù)據(jù)。9.將TODO注釋替換成以下語句:source.Text = ;source變量是窗體上最大的那個文本框。把它的Text屬性設為空字符串(),就可以清除當前顯示的任何文本。10.在剛才輸入的語句之后,輸入以下語句:stri
14、ng line = reader.ReadLine(); 上述語句聲明string變量line,調(diào)用reader.ReadLine方法把文件中的第一行文本讀入變量。方法要么返回讀取的一行文本;要么返回特殊值null來表明沒有更多的行可供讀取。如果一行文本都沒有返回,表明是空文件。11.在剛才輸入的代碼之后繼續(xù)輸入以下代碼:while (line != null) source.Text += line + n; line = reader.ReadLine();以上while循環(huán)依次讀取文件每一行,直至沒有更多行。while循環(huán)判斷l(xiāng)ine變量值。不為null就顯示讀取的行,具體做法是將該行附
15、加到source文本框的Text屬性,并在行末添加換行符(n)。TextReader對象的ReadLine方法讀取每一行會自動刪除換行符,所以要重新添加。然后,在下次循環(huán)之前,while循環(huán)讀取下一行文本。如果沒有更多文本,ReadLine返回null值,造成while循環(huán)終止。12.如果使用Windows 8.1,在while循環(huán)的結(jié)束大括號()之后添加以下語句:reader.Dispose();如果使用Windows 7或Windows 8,在之后添加以下語句:reader.Close();這將釋放與文件關聯(lián)的資源并關閉文件。這是一個好習慣。除了釋放訪問文件所需的內(nèi)存和其他資源,還使其他應
16、用程序能使用該文件。13.在“調(diào)試”菜單中選擇“啟動調(diào)試”。14.窗體出現(xiàn)之后單擊Open File。15.在文件選取器或“打開”對話框中,切換到“文檔”文件夾下的Microsoft PressVisual CSharp Step by StepChapter 5Windows XWhileStatementWhileStatement子文件夾,選擇MainWindow.xaml.cs文件,單擊“打開”按鈕。注意不要打開非文本文件。例如,打開可執(zhí)行程序或圖形文件會顯示二進制信息的文本形式。如果文件很大,應用程序可能掛起,需要強制終止。 這次所選文件的內(nèi)容在文本框中完整顯示,可看到剛才輸入的代碼
17、。下圖展示的是Windows 8.1版本的運行情況。Windows 7版本與此相似。16.在文本框中滾動文本,找到displayData方法。驗證方法包含剛才添加的代碼。17.返回Visual Studio 2013并停止調(diào)試。5.3 編寫for語句C#的大多數(shù)while循環(huán)語句都具有以下常規(guī)結(jié)構(gòu):initializationwhile (Boolean expression) statement update control variablefor語句提供了這種結(jié)構(gòu)的更正式版本,它將initialization(初始化)、Boolean expression(布爾表達式)與update co
18、ntrol variable(更新控制變量)合并到一起。用過for語句之后就能體會到它的好處,它能防止遺漏初始化和更新控制變量的代碼,減少寫出無限循環(huán)代碼的概率。以下是for語句的語法:for (initialization; Boolean expression; update control variable) statement其中,statement(語句)是for循環(huán)主體,要么是一個語句,要么是用花括號封閉的代碼塊。前面展示過while循環(huán)的一個例子,它顯示09的整數(shù)。下面要用for循環(huán)改寫它:for (int i = 0; i 10; i+) Console.WriteLine(i
19、);初始化(int i = 0)只在循環(huán)開始時發(fā)生一次。如果布爾表達式(i 10)的求值結(jié)果為true,就運行語句(Console.WriteLine(i);)。隨后,控制變量進行更新(i+),布爾表達式重新求值,如果仍為true,語句再次執(zhí)行,控制變量更新,布爾表達式重新求值如此反復。注意三點:初始化只發(fā)生一次;初始化后先執(zhí)行循環(huán)主體語句,再更新控制變量;更新控制變量后再重新求值布爾表達式。提示和while語句一樣,建議總是為for循環(huán)主體使用代碼塊,即使其中只有一個語句。這樣一來,以后添加代碼就更省心。for語句的三個部分都可以省略。如果省略布爾表達式,布爾表達式就默認為true。以下fo
20、r語句將一直運行:for (int i = 0; ;i+) Console.WriteLine(根本停不下來!); 省略初始化和更新部分會得到一個看起來很奇怪的for循環(huán),如下所示:int i = 0;for (; i 10; ) Console.WriteLine(i); i+;注意for語句的初始化、布爾表達式和更新控制變量這三個部分必須用分號分隔,即使某個部分的實際內(nèi)容并不存在。如有必要,可在for循環(huán)中提供多個初始化語句和多個更新語句(布爾表達式只能有一個)。為此,請用逗號分隔不同的初始化和更新語句,如下例所示:for (int i = 0, j = 10; i = j; i+, j-
21、) .最后用for循環(huán)重寫上個練習的while循環(huán):for (string line = reader.ReadLine(); line != null; line = reader.ReadLine() source.Text += line + n;理解for語句作用域前面說過,可在for語句的“初始化”部分聲明新變量。變量作用域限制于for語句主體。for語句結(jié)束,變量消失。該規(guī)則造成兩個重要結(jié)果。首先,不能在for語句結(jié)束后使用變量,因為它已不在作用域中。下面是一個例子:for (int i = 0; i 10; i+) .Console.WriteLine(i); / 編譯錯誤其次,
22、可在兩個或更多for語句中使用相同變量名,因為每個變量都在不同作用域中。下面是一個例子:for (int i = 0; i 10; i+) .for (int i = 0; i 20; i += 2) / okay .5.4 編寫do語句while和for語句都在循環(huán)開始時測試布爾表達式。這意味著假如首次測試布爾表達式為false,循環(huán)主體一次都不運行。do語句則不同,它的布爾表達式在每次循環(huán)之后求值,所以主體至少執(zhí)行一次。do語句的語法如下(不要忘記最后的分號):do statementwhile (booleanExpression);多個語句構(gòu)成的循環(huán)主體必須是放在中的代碼塊。以下語句向
23、控制臺輸出09,這次使用do語句:int i = 0;do Console.WriteLine(i); i+;while (i 10); break語句和continue語句第4章用break語句跳出switch語句。還可用它跳出循環(huán)。執(zhí)行break后,系統(tǒng)立即終止循環(huán),并從循環(huán)之后的第一個語句繼續(xù)執(zhí)行。在這種情況下,循環(huán)的“更新”和“繼續(xù)”條件都不會重新判斷。相反,continue語句造成當前循環(huán)結(jié)束,立即開始下一次循環(huán)(在對布爾表達式重新求值之后)。下面是在控制臺上輸出09的例子的另一個版本,這次使用break語句和continue語句:int i = 0;while (true) Con
24、sole.WriteLine(continue + i); i+; if (i 10) continue; else break;這段代碼看起來讓人難受。在許多編程守則中,都建議謹慎使用continue語句,或者根本不要用,因為它很容易造成難以理解的代碼。continue語句的行為還讓人捉摸不透。例如,在for語句中執(zhí)行continue語句,會在運行for語句的“更新(控制變量)”部分之后,才開始下一次循環(huán)。下例要寫do語句將正的十進制數(shù)轉(zhuǎn)換成八進制的字符串形式。程序基于以下算法:將十進制數(shù)存儲到變量dec中do以下事情: dec除以8,將余數(shù)存儲起來 將dec設為上一步得到的商while d
25、ec不等于0 按相反順序合并每一次得到的余例如,要將十進制數(shù)999轉(zhuǎn)換成八進制,可執(zhí)行以下步驟。1.999除以8,商124余7。2.124除以8,商15,余4。3.15除以8,商1余7。4.1除以8,商0,余1。5.按相反順序合并每一步得到的余,結(jié)果是1747。這就是999轉(zhuǎn)換成八進制的結(jié)果。 寫do語句1.在Visual Studio 2013中打開DoStatement項目,它位于“文檔”文件夾下的Microsoft PressVisual CSharp Step by StepChapter 5Windows XDoStatement子文件夾中。2.在設計視圖中MainWindow.xa
26、ml窗體。窗體左側(cè)是number文本框。用戶在此輸入十進制數(shù)。單擊Show Steps按鈕后,會生成該數(shù)字的八進制形式。右側(cè)steps文本框顯示每個計算步驟的結(jié)果。3.在“代碼和文本編輯器”窗口中顯示MainWindow.xaml.cs的代碼。找到showStepsClick方法。該方法在單擊Show Steps按鈕后運行,目前為空。4.將以下加粗顯示的代碼添加到showStepsClick方法中:private void showStepsClick(object sender, RoutedEventArgs e) int amount = int.Parse(number.Text);
27、steps.Text = ; string current = ;第一個語句使用int類型的Parse方法將number文本框的Text屬性中存儲的字符串值轉(zhuǎn)換成int值。第二個語句將右側(cè)文本框steps的Text屬性設為空字符串,清除顯示的文本。第三個語句聲明string變量current,初始化為空字符串。該字符串存儲每一次do循環(huán)時生成的八進制數(shù)位。5.將以下加粗顯示的do語句添加到showStepsClick方法中:private void showStepsClick(object sender, RoutedEventArgs e) int amount = int.Parse(n
28、umber.Text); steps.Text = ; string current = ; do int nextDigit = amount % 8; amount /= 8; int digitCode = 0 + nextDigit; char digit = Convert.ToChar(digitCode); current = digit + current; steps.Text += current + n; while (amount != 0);該算法反復計算amount變量除以8所得的余數(shù)。每次得到的余數(shù)都是正在構(gòu)造的新字符串的下一個數(shù)位。最終,amount變量將減小至
29、0,循環(huán)結(jié)束。注意循環(huán)主體至少執(zhí)行一次。這個“至少執(zhí)行一次”的行為正是我們所需要的,因為即使是數(shù)字0,也有一個八進制的數(shù)位。進一步研究代碼,do循環(huán)的第一個語句如下:int nextDigit = amount % 8;該語句聲明int變量nextDigit初始化為amount變量除以8之余。該值范圍是07。第二個語句如下:amount /= 8;這是復合賦值語句,相當于amount = amount / 8;。如果amount的值是999,那么在執(zhí)行這個語句之后,amount的值就是124。下一個語句是:int digitCode = 0 + nextDigit;這個語句要稍微解釋一下!根據(jù)
30、Windows操作系統(tǒng)使用的字符集,每個字符都有唯一代碼。在Windows操作系統(tǒng)常用的字符集中,字符0的代碼是整數(shù)值48。字符1的代碼是49,字符2的代碼是50,以此類推,直到字符9,它的代碼是57。C#允許將字符當作整數(shù)處理,允許對它們執(zhí)行算術運算。但這樣做會將字符碼作為值使用。所以,表達式0 + nextDigit的結(jié)果是4855之間的值(記住,nextDigit的值在07之間),對應于等價的八進制數(shù)位的代碼。do語句的第四個語句如下:char digit = Convert.ToChar(digitCode);該語句聲明char變量digit,把它初始化為Convert.ToChar(
31、digitCode)方法調(diào)用的結(jié)果。Convert.ToChar方法獲取字符碼(一個整數(shù)),返回與之對應的字符。所以,假如digitCode的值是54,Convert.ToChar(digitCode)返回字符6??傊?,do循環(huán)的前4個語句計算與用戶輸入的數(shù)字對應的最低有效八進制數(shù)位(最右邊的數(shù)位)。下個任務是將這個數(shù)位添加到要輸出的字符串的前面,如下所示:current = digit + current;do循環(huán)的下一個語句如下:steps.Text += current + n;該語句將迄今為止得到的八進制數(shù)位添加到steps文本框中,還為每次輸出都附加換行符,使每次輸出在文本框中都單獨
32、占一行。最后,do循環(huán)末尾用while子句對循環(huán)條件進行求值:while (amount != 0)如果amount的值目前不為0,就開始下一次循環(huán)。最后一個練習使用Visual Studio 2013調(diào)試器來單步執(zhí)行上述do語句,幫助理解其工作原理。 單步執(zhí)行do語句1.在打開了MainWindow.xaml.cs文件的“代碼和文本編輯器”窗口中,將光標移到showStepsClick方法的第一個語句:int amount = int.Parse(number.Text);2.右擊第一個語句,從彈出的快捷菜單中選擇“運行到光標處”命令。3.窗體出現(xiàn)后,在左側(cè)文本框中鍵入999,單擊Show
33、Steps按鈕。程序暫停運行,Visual Studio 2013進入調(diào)試模式?!按a和文本編輯器”窗口左側(cè)將出現(xiàn)一個黃色箭頭,標記出當前要執(zhí)行的語句。4.如果“調(diào)試”工具欄不可見,請顯示它(選擇“視圖”|“工具欄”|“調(diào)試”)。5.單擊“調(diào)試”工具欄的下箭頭,指向“添加或移除按鈕”,選擇“窗口”,如下圖所示。這樣會在“調(diào)試”工具欄上顯示“斷點”按鈕。6.單擊“斷點”按鈕右側(cè)的下箭頭,選擇“局部變量”,如下圖所示。隨后將顯示下圖所示的“局部變量”窗口,其中列出了當前方法的局部變量的名稱、值和類型,其中包括局部變量amount。注意amount變量的值目前是0。7.在“調(diào)試”工具欄上單擊“逐語句
34、”按鈕(或者按功能鍵F11)。調(diào)試器將運行當前語句:int amount = int.Parse(number.Text);在“局部變量”窗口中,amount的值變成999,黃色箭頭指向下一個語句。8.再次單擊“逐語句”按鈕。調(diào)試器運行以下語句:steps.Text = ;該語句不影響“局部變量”窗口的顯示,因為steps是窗體控件,不是局部變量。黃箭頭指向下一個語句。9.再次單擊“逐語句”按鈕。調(diào)試器將運行以下語句:string current = ;黃箭頭指向do循環(huán)的起始大括號。do循環(huán)主體有三個局部變量,即nextDigit,digitCode和digit。注意,這些局部變量在“局部變
35、量”窗口中顯示,而且值均為0。10.單擊“逐語句”按鈕。黃箭頭指向do循環(huán)主體的第一個語句。11.單擊“逐語句”按鈕。調(diào)試器運行以下語句:int nextDigit = amount % 8;在“局部變量”窗口中,nextDigit的值變成7,這是999除以8之余。12.單擊“逐語句”按鈕。調(diào)試器運行以下語句:amount /= 8;在“局部變量”窗口中,amount的值變成124。13.單擊“逐語句”按鈕。調(diào)試器運行以下語句:int digitCode = 0 + nextDigit;在“局部變量”窗口中,digitCode變量的值變成55。這是7的字符碼(48 + 7)。14.單擊“逐語句
36、”按鈕。調(diào)試器運行以下語句:char digit = Convert.ToChar(digitCode);在“局部變量”窗口中,digit的值變?yōu)??!熬植孔兞俊贝翱谕瑫r顯示char值的數(shù)值形式(本例是55)和字符形式(本例是7)。注意,在“局部變量”窗口中,current變量的值仍是。15.單擊“逐語句”按鈕。調(diào)試器運行以下語句:current = current + digit;在“局部變量”窗口中,current的值變成7。 16. 單擊“逐語句”按鈕。調(diào)試器運行以下語句:steps.Text += current + n;該語句在steps文本框中顯示文本7,后跟換行符,確保以后的輸出
37、從文本框的下一行開始(窗體隱藏在Visual Studio后面,所以看不到)。黃箭頭移至do循環(huán)末尾的結(jié)束大括號。17.單擊“逐語句”按鈕。黃箭頭指向while語句,準備求值while條件,判斷是結(jié)束還是繼續(xù)do循環(huán)。18.單擊“逐語句”按鈕。調(diào)試器運行以下語句:while (amount != 0);amount的值是124,表達式124 != 0求值結(jié)果是true,所以進行下一次循環(huán)。黃箭頭跳回do循環(huán)的起始大括號。19.單擊“逐語句”按鈕。黃箭頭再次指向do循環(huán)的第一個語句。20.連續(xù)單擊“逐語句”按鈕,重復三次do循環(huán),觀察變量值在“局部變量”窗口中的變化。21.第4次循環(huán)結(jié)束時,am
38、ount的值變成0,current的值變成1747。黃箭頭指向do循環(huán)的while條件:while (amount != 0);amount目前為0,所以表達式amount != 0求值結(jié)果為false,do循環(huán)應該終止。22.單擊“逐語句”按鈕。調(diào)試器運行以下語句:while (amount != 0);如同預期的那樣,do循環(huán)終止,黃箭頭移至showStepsClick方法的結(jié)束大括號。23.單擊工具欄上的“繼續(xù)”按鈕,或者從“調(diào)試”菜單選擇“繼續(xù)”。窗體隨后將出現(xiàn),顯示為創(chuàng)建999的八進制形式所經(jīng)歷的4個步驟:7,47,747和1747(參見下圖)。24.返回Visual Studio
39、2013并停止調(diào)試。小 結(jié)本章講述了如何使用復合賦值操作符更新數(shù)值變量;講述了如何使用while,for和do語句在布爾條件為true的前提下重復執(zhí)行代碼。l 如果希望繼續(xù)學習下一章,請繼續(xù)運行Visual Studio 2013,然后閱讀第6章。l 如果希望現(xiàn)在就退出Visual Studio 2013,請選擇“文件”|“退出”。如果看到“保存”對話框,請單擊“是”按鈕保存項目。第5章快速參考目標操作在變量(variable)上加一個值(amount)使用復合加法操作符。示例如下:variable += amount;從變量(variable)中減一個值(amount)使用復合減法操作符。示
40、例如下:variable -= amount;條件為true時運行一個或多個語句使用while語句。示例如下:int i = 0;while (i 10) Console.WriteLine(i); i+;還可使用for語句。示例如下:for (int i = 0; i 10; i+) Console.WriteLine(i);一次或反復多次執(zhí)行語句使用do語句。示例如下:int i = 0;do Console.WriteLine(i); i+;while (i 10);41第6章 管理錯誤和異常第6章 管理錯誤和異常本章旨在教會你:l 使用try,catch和finally語句處理異常l
41、使用checked和unchecked關鍵字控制整數(shù)溢出l 使用throw關鍵字從方法中拋出異常l 使用finally塊寫總是運行的代碼(即使在發(fā)生異常之后)之前學習了執(zhí)行常規(guī)任務所需的核心C#語句,這些常規(guī)任務包括編寫方法,聲明變量,用操作符創(chuàng)建值,用if和switch語句選擇運行代碼,以及用while、for和do語句重復運行代碼。但一直沒有提到程序可能出錯的問題。事實上,很難保證代碼總是像希望的那樣工作。有許多原因造成出錯,其中許多不是程序員能控制的。任何應用程序都必須能檢測錯誤,并以得體的方式處理:要么進行糾正;如果糾正不了,也要用最清楚的方式報告出錯原因。作為第部分的最后一章,本章要
42、講述C#如何通過拋出異常來通知發(fā)生了錯誤,如何使用try,catch和finally語句捕捉和處理這些異常所代表的錯誤。通過本章的學習,將進一步掌握C#語言,為順利學習第部分的內(nèi)容打下堅實的基礎。6.1 處 理 錯 誤生活并非總是一帆風順。輪胎可能扎破,電池可能耗盡,螺絲起子并非總在老地方,應用程序的用戶可能采取了出乎預料的操作。在計算機世界里,磁盤可能出故障,編寫不當?shù)某绦蚩赡苡绊憴C器上運行的其他應用程序(比如由于程序bug造成耗盡所有內(nèi)存),無線網(wǎng)絡可能在最不恰當?shù)臅r刻斷開連接,甚至一些自然現(xiàn)象(比如附近的一次閃電)也會造成電源或網(wǎng)絡故障。錯誤可能在程序運行的任何階段發(fā)生,其中許多都不是程
43、序本身的問題。那么,如何檢測并嘗試修復呢?人們多年來為此研發(fā)了大量機制。早期系統(tǒng)(如UNIX)采用的典型方案要求在每次方法出錯時都由操作系統(tǒng)設置一個特殊全局變量。每次調(diào)用方法后都檢查全局變量,判斷方法是否成功。和大多數(shù)面向?qū)ο缶幊陶Z言一樣,C#沒有使用這種痛苦的、折磨人的方式處理錯誤。相反,它使用的是異常。為了寫可靠的C#應用程序,必須很好地掌握異常。6.2 嘗試執(zhí)行代碼和捕捉異常錯誤任何時候都可能發(fā)生,使用傳統(tǒng)技術為每個語句手動添加錯誤檢測代碼,不僅勞神費力,還很容易出錯。另外,如果每個語句都需要錯誤處理邏輯來管理每個階段都可能發(fā)生的每個錯誤,會很容易迷失方向,失去對程序主要流程的把握。幸好
44、,在C#中利用異常和異常處理程序 譯注:本書按照約定俗成的譯法,將exception handler翻譯成“異常處理程序”,但請把它理解成“用于異常處理的構(gòu)造”。同樣的道理也適用于“catch處理程序”,它其實是指“catch構(gòu)造”。,可以很容易地區(qū)分實現(xiàn)程序主邏輯的代碼與處理錯誤的代碼。為了寫支持異常處理的應用程序,要做下面兩件事。1.代碼放到try塊中(try是C#關鍵字)。代碼運行時,會嘗試執(zhí)行try塊內(nèi)的所有語句。如果沒有任何語句產(chǎn)生異常,這些語句將一個接一個運行,直到全部完成。但一旦出現(xiàn)異常,就跳出try塊,進入一個catch處理程序中執(zhí)行。2.緊接著try塊寫一個或多個catch處
45、理程序(catch也是C#關鍵字)來處理可能發(fā)生的錯誤。每個catch處理程序都捕捉并處理特定類型的異常,可在try塊后面寫多個catch處理程序。try塊中的任何語句造成錯誤,“運行時”都會生成并拋出異常。然后,“運行時”檢查try塊之后的catch處理程序,將控制權移交給匹配的處理程序。下例在try塊中嘗試將文本框中的內(nèi)容轉(zhuǎn)換成整數(shù)值,調(diào)用方法計算值,將結(jié)果寫入另一個文本框。為了將字符串轉(zhuǎn)換成整數(shù),要求字符串包含一組有效的數(shù)位,而不能是一組隨意的字符。如果字符串包含無效字符,int.Parse方法拋出FormatException異常,并將控制權移交給對應的catch處理程序。catch處
46、理程序結(jié)束后,程序從整個try/catch塊之后的第一個語句繼續(xù)。注意,如果沒有和異常對應的處理程序,就說異常未處理(稍后會討論這種情況)。try int leftHandSide = int.Parse(lhsOperand.Text); int rightHandSide = int.Parse(rhsOperand.Text); int answer = doCalculation(leftHandSide, rightHandSide); result.Text = answer.ToString();catch (FormatException fEx) / 處理異常.catch處理
47、程序采用與方法參數(shù)相似的語法指定要捕捉的異常。在前例中,一旦拋出FormatException異常,fEx變量就會被填充一個對象,其中包含了異常細節(jié)。FormatException類型提供大量屬性供檢查造成異常的確切原因。其中不少屬性是所有異常通用的。例如,Message屬性包含錯誤的文本描述。處理異常時可利用這些信息,例如可以把細節(jié)記錄到日志文件,或者向用戶顯示有意義的消息,并要求重新輸入。6.2.1 未處理的異常如果try塊拋出異常,但沒有對應的catch處理程序,那么會發(fā)生什么?在前例中,lhsOperand文本框可能確實包含一個整數(shù),但該整數(shù)超出了C#允許的整數(shù)范圍(例如2147483
48、648)。在這種情況下,int.Parse語句會拋出OverflowException異常,而catch處理程序目前只能捕捉FormatException異常。如果try塊是某個方法的一部分,那個方法將立即退出,并返回它的調(diào)用方法。如果它的調(diào)用方法有try塊,“運行時”會嘗試定位try塊之后的一個匹配catch處理程序并執(zhí)行。如果調(diào)用方法沒有try塊,或者沒有找到匹配的catch處理程序,調(diào)用方法退出,返回它的更上一級的調(diào)用方法以此類推。如果最后找到了匹配的catch處理程序,就運行它,然后從捕捉(到異常的)方法的catch處理程序之后的第一個語句繼續(xù)執(zhí)行。重要提示 捕捉了異常之后,將從“捕捉
49、方法”中的catch處理程序之后的第一個語句繼續(xù),這個catch處理程序是實際捕捉到異常的catch塊??刂撇粫氐皆斐僧惓5姆椒āS蓛?nèi)向外遍歷了所有調(diào)用方法之后,如果還是找不到匹配的catch處理程序,整個程序終止,報告發(fā)生了未處理的異常??梢院苋菀椎貦z查應用程序生成的異常。以“調(diào)試”模式運行應用程序(選擇“調(diào)試”|“啟動調(diào)試”)并發(fā)生異常,會出現(xiàn)如下圖所示的對話框。應用程序暫停,便于判斷造成異常的原因。應用程序在拋出異常并導致調(diào)試器介入的語句停止。此時可檢查變量值,可更改變量的值,還可使用“調(diào)試”工具欄和各種調(diào)試窗口,從拋出異常的位置單步調(diào)試代碼。6.2.2 使用多個catch處理程序通過
50、前面的討論,我們知道不同的錯誤可能拋出不同類型的異常。為了解決這個問題,可以提供多個catch處理程序。所有catch處理程序依次列出,就像下面這樣:try int leftHandSide = int.Parse(lhsOperand.Text); int rightHandSide = int.Parse(rhsOperand.Text); int answer = doCalculation(leftHandSide, rightHandSide); result.Text = answer.ToString();catch (FormatException fEx) /.catch (
51、OverflowException oEx) /.如果try塊中的代碼拋出FormatException異常,和FormatException 對應的catch塊開始運行。如果拋出OverflowException異常,和OverflowException對應的catch塊開始運行。注意如果FormatException catch塊的代碼拋出OverflowException異常,不會造成相鄰的那個OverflowException catch塊的運行。相反,異常會傳給調(diào)用當前代碼的方法。換言之,該異常會“傳播”至調(diào)用棧的上一級。本節(jié)前面有相關的描述。6.2.3 捕捉多個異常C#和Micro
52、soft .NET Framework的異常捕捉機制相當完善。.NET Framework定義了許多異常類型,包括程序可能拋出的大多數(shù)異常!一般不可能為每個可能的異常都寫對應的catch處理程序某些異??赡茉诔绦驎r都沒有想到。那么,如何保證所有可能的異常都被捕捉并處理呢?這個問題的關鍵在于各個異常之間的關系。異常用繼承層次結(jié)構(gòu)進行組織。這個繼承層次結(jié)構(gòu)由多個“家族”構(gòu)成(第12章將詳細討論繼承)。FormatException和OverflowException異常都屬于SystemException家族。該家族還包含其他許多異常。SystemException本身又是Exception家族的
53、成員,而Exception是所有異常的“老祖宗”。捕捉Exception相當于捕捉可能發(fā)生的所有異常。注意Exception包含眾多異常,其中許多異常是專門供.NET Framework的各種組件使用的。雖然一些異常較難理解,但至少應該知道如何捕捉它們。下面的代碼將展示如何捕捉所有可能的異常:try int leftHandSide = int.Parse(lhsOperand.Text); int rightHandSide = int.Parse(rhsOperand.Text); int answer = doCalculation(leftHandSide, rightHandSide
54、); result.Text = answer.ToString();catch (Exception ex) / 這是常規(guī)catch處理程序,能捕捉所有異常 /.提示如果真的決定捕捉Exception,可以從catch處理程序中省略它的名稱,因為默認捕捉的就是Exception: catch / 但并不總是推薦這樣做。傳入catch處理程序的異常對象可能包含異常的重要信息。使用這個沒有參數(shù)的catch構(gòu)造進行訪問,可能無法利用這些信息。最后還有一個問題:異常與try塊之后的多個catch處理程序匹配會發(fā)生什么?假如一個處理程序捕捉FormatException,另一個捕捉Exception,最終運行哪一個(還是兩個都運行)? 異常發(fā)生后將運行由“運行時”發(fā)現(xiàn)的第一個匹配
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度綠色建筑鋼筋綁扎與回收利用合同4篇
- 江蘇省無錫市錫山區(qū)2019-2020學年八年級下學期期中物理試題【含答案、解析】
- 2025版房屋抵押貸款風險評估與咨詢服務合同4篇
- 股權代持合同簽訂與解除的法律要點2025年合同2篇
- 江西省贛州市瑞金市2024-2025學年八年級上學期期末考試道德與法治試題(含答案)
- 廣東省茂名市電白區(qū)2024-2025學年八年級上學期期末地理試卷(含答案)
- 固體飲料行業(yè)的融資模式與投資機會分析報告考核試卷
- 2025版企業(yè)知識產(chǎn)權保護委托合同范本指南3篇
- 東南歐eMAG知識百科 2025
- 2001年江蘇南通中考滿分作文《我發(fā)現(xiàn)女孩也可做“太陽”》
- 《健康體檢知識》課件
- 部編版語文五年級下冊 第一單元 專項訓練課外閱讀(含答案)
- 蘇少版七年級美術下冊 全冊
- 名表買賣合同協(xié)議書
- JTG-T-F20-2015公路路面基層施工技術細則
- 2024年遼寧石化職業(yè)技術學院單招職業(yè)適應性測試題庫附答案
- 中西方校服文化差異研究
- 《子宮肉瘤》課件
- 《準媽媽衣食住行》課件
- 給男友的道歉信10000字(十二篇)
- 客人在酒店受傷免責承諾書范本
評論
0/150
提交評論