Tìm Và Sửa Lỗi Chương Trình Sau Class Baitap3_4

catch{

Console.WriteLine(“Exception caught and handled.”);

}

Console.WriteLine(“Exit Func1...”);

}

public void Func2()

{

Console.WriteLine(“Enter Func2...”); throw new System.Exception(); Console.WriteLine(“Exit Func2...”);

}

}

Có thể bạn quan tâm!

Xem toàn bộ 285 trang tài liệu này.

}

Lúc này ngoại lệ không được xử lý bên trong hàm Func2(), mà nó được xử lý bên trong hàm Func1(). Khi hàm Func2() được gọi, nó in câu lệnh thông báo vào hàm rồi phát sinh một ngoại lệ. Việc thực hiện chương trình bị ngưng, CLR tìm kiếm phần xử lý ngoại lệ, nhưng trong hàm này không có và CLR vào stack lấy hàm gọi trong trường hợp này là Func1(). Câu lệnh catch sẽ được gọi và việc thực thi tiếp tục thực hiện bình thường sau câu lệnh catch.

Chúng ta đã dùng khối catch tổng quát, tức là với bất cứ ngoại lệ nào cũng được. Tuy nhiên chúng ta có thể tạo ra khối catch xác định để xử lý chỉ một vài các ngoại lệ chứ không phải toàn bộ ngoại lệ, dựa trên kiểu của ngoại lệ phát sinh. Ví dụ sau minh họa cách xác định loại ngoại lệ mà chúng ta xử lý.

Ví dụ: Xác định ngoại lệ để bắt

namespace Programming_CSharp

{

using System; public class Test

{

public static void Main()

{

Test t = new Test(); t.TestFunc();

}

// ta thử chia hai phần xử lý ngoại lệ riêng public void TestFunc()

{

try{

double a = 5; double b = 0;

Console.WriteLine(“{0} / {1} = {2}”, a, b, DoDivide(a,b));

}

catch (System.DivideByZeroException){ Console.WriteLine(“DivideByZeroException caught!”);

}

catch (System.ArithmeticException){ Console.WriteLine(“ArithmeticException caught!”);

}

catch{

Console.WriteLine(“Unknown exception caught”);

}


Trong ví dụ này, phương thức DoDivide() sẽ không cho phép chúng ta chia cho zero bởi một số khác và cũng không cho phép chia số zero. Nó sẽ phát sinh một đối tượng của Divide- ByzeroException nếu chúng ta thực hiện chia với zero. Trong toán học việc lấy zero chia cho một số khác là được phép, nhưng trong ví dụ minh họa của chúng ta không cho phép thực hiện việc này, nếu thực hiện sẽ phát sinh ra một ngoại lệ ArithmeticException.

Khi một ngoại lệ được phát sinh, CLR sẽ kiểm tra mỗi khối xử lý ngoại lệ theo thứ tự và sẽ lấy khối đầu tiên thích hợp. Khi thực hiện với a=5 và b=7 thì kết quả như sau:

5 / 7 = 0.7142857142857143

Như vậy, không có ngoại lệ được phát sinh. Tuy nhiên, khi chúng ta thay đổi giá trị của a là 0, thì kết quả là: ArithmeticException caught!

Ngoại lệ được phát sinh và CLR sẽ kiểm tra ngoại lệ đầu tiên: DivideByZero Exception. Vì không phù hợp, nên sẽ tiếp tục đi tìm và khối xử lý Arithmetic Exception được chọn.

Giả sử chúng ta thay đổi giá trị của b là 0. Khi thực hiện sẽ dẫn đến ngoại lệ DivideByZeroException.

Phải xét kỹ thứ tự của câu lệnh catch, bởi vì DivideByZero-Exception được dẫn xuất từ ArithmeticException. Nếu chúng ta đảo thứ tự của câu lệnh catch, thì ngoại lệ DivideByZeroException sẽ được phù hợp với khối xử lý ngoại lệ Arith- meticException. Và việc xử lý ngoại lệ sẽ không bao giờ được giao cho khối xử lý DivideByZeroException. Thật vậy, nếu thứ tự này được đảo, nó sẽ không cho phép bất

cứ ngoại lệ nào được xử lý bởi khối xử lý ngoại lệ DivideByZeroException. Trình biên dịch sẽ nhận ra rằng DivideByZero

Exception không thực hiện bất cứ khi nào và nó sẽ thông báo một lỗi biên dịch.

Có thể phân phối câu lệnh try/catch, bằng cách bắt giữ những ngoại lệ xác định trong một hàm và nhiều ngoại lệ tổng quát trong nhiều hàm. Mục đích của thực hiện này là đưa ra các thiết kế đúng. Giả sử chúng ta có phương thức A, phương thức này gọi một phương thức khác tên là phương thức B, đến lượt mình phương thức B gọi phương thức C. Và phương thức C tiếp tục gọi phương thức D, cuối cùng phương thức D gọi phương thức E. Phương thức E ở mức độ sâu nhất trong chương trình của chúng ta, phương thức A, B ở mức độ cao hơn. Nếu chúng ta đoán trước phương thức E có thể phát sinh ra ngoại lệ, chúng ta có thể tạo ra khối try/catch để bắt giữ những ngoại lệ này ở chỗ gần nơi phát sinh ra ngoại lệ nhất. Chúng ta cũng có thể tạo ra nhiều khối xử lý ngoại lệ chung ở trong đoạn chương trình ở mức cao trong trường hợp những ngoại lệ không đoán trước được.

2.8.3. Câu lệnh finally

Trong một số tình huống, việc phát sinh ngoại lệ và unwind stack có thể tạo ra một số vấn đề. Ví dụ như khi chúng ta mở một tập tin, xác nhận một tài nguyên, chúng ta đóng một tập tin hay là giải phóng bộ nhớ đệm mà chương trình đã chiếm giữ trước đó. Trong ngôn ngữ C#, vấn đề này ít xảy ra hơn do cơ chế thu dọn tự động của C# ngăn ngừa những ngoại lệ phát sinh từ việc thiếu bộ nhớ.

Tuy nhiên, có một số hành động mà chúng ta cần phải quan tâm là bất cứ khi nào một ngoại lệ được phát sinh ra, như việc đóng một tập tin, chúng ta có hai chiến lược để lựa chọn thực hiện. Một hướng tiếp cận là đưa hành động nguy hiểm vào trong khối try và sau đó thực hiện việc đóng tập tin trong cả hai khối catch và try. Tuy nhiên, điều này gây ra đoạn chương trình không được đẹp do sử dụng trùng lắp lệnh. Ngôn ngữ C# cung cấp một sự thay thế tốt hơn trong khối finally.

Đoạn chương trình bên trong khối catch được đảm bảo thực thi mà không quan tâm đến việc khi nào thì một ngoại lệ được phát sinh. Phương thức TestFunc() trong ví dụ sau minh họa việc mở một tập tin như là hành động đầu tiên của nó, sau đó phương thức thực hiện một vài các phép toán toán học và sau đó là tập tin được đóng. Có thể trong quá trình mở tập tin cho đến khi đóng tập tin chương trình phát sinh ra một ngoại lệ. Nếu xuất hiện ngoại lệ, khi đó tập tin vẫn còn mở nhưng cuối của phương thức này tập tin sẽ được đóng. Do chức năng đóng tập tin được di chuyển vào trong khối finally, ở đây nó sẽ được thực thi mà không cần quan tâm đến việc có phát sinh hay không một ngoại lệ trong chương trình.

Ví dụ: Sử dụng khối finally

namespace Programming_CSharp

{

using System; public class Test

{

public static void Main()

{

Test t = new Test(); t.TestFunc();

}

public void TestFunc(){ try {

Console.WriteLine(“Open file here”); double a = 5; double b = 0;

Console.WriteLine(“{0} /{1} = {2}”, a, b, DoDivide(a,b)); Console.WriteLine(“This line may or not print”);

}

catch (System.DivideByZeroException){ Console.WriteLine(“DivideByZeroException caught!”);

}

catch{

Console.WriteLine(“Unknown exception caught”);

}

finally{

Console.WriteLine(“Close file here.”);

}

}

public double DoDivide(double a, double b){ if ( b == 0){

throw new System.DivideByZeroException();

}

if ( a == 0){

throw new System.ArithmeticException();

}

return a/b;

}

}}

Trong ví dụ này một khối catch được loại bỏ và thêm vào khối finally. Bất cứ khi một ngoại lệ được phát sinh ra hay không thì khối lệnh trong finally cũng được thực thi. Do vậy nên trong cả hai trường hợp ta cũng thấy xuất hiện thông điệp “Close file here”.

2.9. Bài tập

1. Cho biết chương trình sau thực hiện điều gì?

using System; class variables

{

public static void Main(){

int radius = 4; const double PI = 3.14159; double circum, area; area = PI * radius* radius;

circum = 2 * PI * radius;

Console.WriteLine(“Ban kinh = {0}, PI = {1}”, radius, PI); Console.WriteLine(“Dien tich {0}”, area); Console.WriteLine(“Chu vi {0}”, circum);

}

}

2. Cho biết chương trình sau thực hiện điều gì?

class AClass

{

static void Main(){ int x, y;

for( x = 0; x < 10; x++, System.Console.Write(“n”));

for( y = 0 ; y < 10; y++, System.Console.WriteLine(“{0}”,y));

}

}

3. Cho biết chương trình sau thực hiện điều gì?

class BaiTap3_1

{

public static void Main(){ int x = 0;

for(x = 1; x < 10; x++)

{

System.Console.Write(“{0:03}”, x);

}

}

}

4. Tìm và sửa lỗi chương trình sau

class Test

{

pubic static void Main(){ Console.WriteLine(“Xin chao”); Consoile.WriteLine(“Tam biet”);

}

}

5. Tìm và sửa lỗi chương trình sau

class Test

{

pubic void Main(){ Console.WriteLine(„Xin chao‟); Consoile.WriteLine(„Tam biet‟);

}

}

6. Tìm và sửa lỗi chương trình sau

class BaiTap3_2

{

public static void Main(){

for(int i=0; i < 10 ; i++) System.Console.WriteLine(“so :{1}”, i);

}

}

7. Tìm và sửa lỗi chương trình sau

using System; class BaiTap3_3

{

public static void Main()

{

double myDouble; decimal myDecimal; myDouble = 3.14;

myDecimal = 3.14;

Console.WriteLine(“My Double: {0}”, myDouble); Console.WriteLine(“My Decimal: {0}”, myDecimal);

}

}

8. Tìm và sửa lỗi chương trình sau class BaiTap3_4

{

static void Main()

{

int value;

if (value > 100);

System.Console.WriteLine(“Number is greater than 100”);

}

}

9. Viết chương trình hiển thị trên màn hình như sau

10 Viết chương trình giải phương trình bậc nhất cho phép người dùng nhập 1

10. Viết chương trình giải phương trình bậc nhất, cho phép người dùng nhập vào giá trị a, b.

11. Viết chương trình giải phương trình bậc hai, cho phép người dùng nhập vào giá trị a, b, c.

12. Viết chương trình tính chu vi và diện tích của các hình sau: đường tròn, hình chữ nhật, hình thang, tam giác.

13. Viết chương trình nhập vào số nguyên dương n. In ra màn hình kết quả của tổng sau: S=1+3+5+7+…+n

14. Viết chương trình nhập vào m số nguyên sau đó hiển thị các số đó ra màn hình Hướng dẫn:

using System;

using System.Collections.Generic; using System.Text;

namespace ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

int m,i;

int[] a= new int[100];

Console.Write("Nhap so luong phan tu mang:"); m =Convert.ToInt32(Console.ReadLine());

//hoac m = int.Parse(Console.ReadLine()); for (i = 1; i <= m; i++)

{

Console.Write("Nhap phan tu thu " + i + ":"); a[i]=Convert.ToInt32(Console.ReadLine());

}

Console.WriteLine("Cac gia tri vua nhap:"); for (i = 1; i <= m; i++)

{

Console.WriteLine(a[i]);

}

Console.ReadLine();

}

}

}

15. Viết chương trình nhập vào m số nguyên sau đó hiển thị các số đó ra màn hình theo thứ tự tăng dần.

16. Xây dựng lớp sinh viên gồm các thuộc tính: họ tên, địa chỉ, số điện thoại. Nhập thông tin của n sinh viên sau đó hiển thị các thông tin này ra màn hình

Hướng dẫn:

using System;

using System.Collections.Generic; using System.Text;

namespace ConsoleApplication3

{

class sv

{

public string ht, dc; public int dt;

}

.....

⇦ Trang trước - Trang tiếp theo ⇨

Ngày đăng: 16/07/2022