Chương trình con: thủ tục và hàm - 1


Chương trình con là một phần riêng biệt của chương trình có tên và giải quyết nhiệm vụ riêng của nó. Chương trình con nằm ở đầu chương trình chính và có thể được khởi chạy (được gọi) từ chương trình chính bằng cách chỉ định tên.

Việc sử dụng chương trình con cho phép bạn tránh trùng lặp mã nếu bạn cần viết cùng một mã ở các vị trí khác nhau của các chương trình . 
Các thư viện được nhập vào một chương trình (ví dụ: Hệ thống) bao gồm các quy trình đã được ai đó biên dịch. Các lập trình viên không cần phải suy nghĩ về những thuật toán nào được triển khai trong đó, họ chỉ cần áp dụng chúng, chỉ nghĩ về chính xác những gì họ đang làm. Đây là một tiết kiệm thời gian lớn. Không cần phải viết một thuật toán đã được viết bởi người khác.

Mỗi chương trình con chỉ nên thực hiện một tác vụ, tính toán một số thứ hoặc xuất một số dữ liệu hoặc làm một việc khác. 

Chương trình con hoặc phương thức có hai loại -  hàm (những hàm trả về kết quả của công việc) và thủ tục (những hàm không trả về).

Hãy bắt đầu với loại thứ hai. Hãy thử viết một ví dụ đơn giản.
Giả sử chúng ta cần hiển thị chuỗi "Error" trên màn hình mỗi khi mã xảy ra lỗi có thể do lỗi của người dùng (ví dụ: khi anh ta nhập dữ liệu không chính xác).
Điều này có thể được thực hiện bằng cách viết câu lệnh
Console.WriteLine("Lỗi"); Bây giờ, hãy tưởng tượng rằng dòng này cần được chèn vào nhiều vị trí trong chương trình. Tất nhiên, bạn chỉ có thể viết nó ở khắp mọi nơi. Nhưng giải pháp này có hai nhược điểm.
1) chuỗi này sẽ được lưu vào bộ nhớ nhiều lần;
2) nếu chúng ta muốn thay đổi đầu ra do lỗi, chúng ta sẽ phải thay đổi dòng này trong suốt chương trình, điều này khá bất tiện.

Đối với những trường hợp như vậy, các phương pháp và quy trình là cần thiết.
Một chương trình có thủ tục có thể trông như thế này:

sử dụng Hệ thống;
lớpChương trình {
    khoảng trống tĩnh PrintError() {
        Console.WriteLine("Lỗi");
   
    khoảng trống tĩnh Main() {
        PrintError();
   
}

 

Một thủ tục bắt đầu bằng từ void. Sau tên thủ tục  dấu ngoặc trống được viết.
Tất cả các câu lệnh được thực thi trong một thủ tục đều được thụt vào. 
Công cụ sửa đổi Tĩnh  có nghĩa là trường, phương thức hoặc thuộc tính đã cho sẽ không thuộc về từng đối tượng của lớp mà thuộc về tất cả chúng cùng nhau.
Các phương thức và thủ tục được viết trước phương thức chính Main().

Để chỉ một thủ tục, trong chương trình chính, bạn cần gọi nó bằng tên và đừng quên viết dấu ngoặc đơn.
Bạn có thể gọi một thủ tục trong một chương trình nhiều lần bất kỳ.

Bây giờ, hãy tưởng tượng rằng chúng ta cần hiển thị các thông báo khác nhau để phản hồi lỗi của người dùng, tùy thuộc vào việc chính xác anh ấy đã mắc sai lầm gì.
Trong trường hợp này, bạn có thể viết quy trình của riêng mình cho từng lỗi: 

 

vô hiệu printErrorZero() {     Console.WriteLine("Lỗi. Chia cho số 0!"); }

 

 

void printErrorInput() { Console.WriteLine("Lỗi nhập liệu!"); } Nếu có nhiều lỗi hơn có thể xảy ra thì sao? Vậy thì giải pháp này sẽ không phù hợp với chúng tôi.
Chúng ta cần học cách kiểm soát quy trình bằng cách cho nó biết thông báo lỗi nào sẽ hiển thị.
Để làm điều này, chúng ta cần các tham số mà chúng ta sẽ viết trong ngoặc đơn sau tên thủ tục
void printError(string s) { Console.WriteLine(s); } Trong quy trình này, s là một tham số - một biến đặc biệt cho phép kiểm soát quy trình.
Tham số là một biến có giá trị mà hoạt động của chương trình con phụ thuộc vào. Tên tham số được liệt kê cách nhau bằng dấu phẩy trong tiêu đề chương trình con. Loại tham số được viết trước tham số.

Bây giờ, khi gọi thủ tục, bạn cần chỉ định giá trị thực trong dấu ngoặc đơn sẽ được gán đến tham số (biến s) bên trong thủ tục của chúng ta printError("Lỗi! Chia cho số 0!"); Giá trị này được gọi là đối số.
Đối số là giá trị tham số được truyền cho chương trình con khi nó được gọi.
Đối số không chỉ có thể là giá trị hằng mà còn có thể là biến hoặc biểu thức số học.< /span>

Biến cục bộ và biến toàn cục
Thường cần phải sử dụng các biến bổ sung sẽ chỉ được sử dụng trong chương trình con. Các biến như vậy được gọi là cục bộ (hoặc cục bộ) và chỉ có thể được thao tác trong chương trình con mà chúng được tạo.
 
Phạm vi biến cục bộ là khối được khai báo trong dấu ngoặc nhọn.
Chương trình chính trong C# cũng là một chương trình con, vì vậy tất cả các biến được khai báo bên trong void Main() đều là biến cục bộ. Các chương trình con khác không "biết" gì về các biến cục bộ của các chương trình con khác.

Như vậy, có thể giới hạn phạm vi (scope) của một biến chỉ cho chương trình con ở những nơi thực sự cần thiết. Trong lập trình, kỹ thuật này được gọi là đóng gói  - ẩn biến không cho thay đổi từ bên ngoài.

Nếu cần khai báo một biến có thể nhìn thấy ở bất kỳ đâu trong chương trình (trong bất kỳ chương trình con nào), thì các biến đó được khai báo bên ngoài tất cả các chương trình con (xem chương trình 3 trong bảng bên dưới).
Các biến như vậy được gọi là toàn cầu.

Trong C#, khi chương trình bắt đầu, tất cả các biến toàn cục sẽ tự động được đặt thành 0 (các biến boolean nhận giá trị false).

Phân tích ba chương trình:

1) Trong chương trình này, biến i là cục bộ. Biến cục bộ được khai báo bên trong chương trình con. 2) Ở đây, ngay cả khi có một biến i trong chương trình chính (với giá trị 7), một biến cục bộ mới i với giá trị 5 sẽ được tạo. 
Khi chương trình này được thực hiện, giá trị 75 sẽ xuất hiện trên màn hình.
3) Chương trình này có biến toàn cục i. Giá trị của nó có thể được thay đổi bên trong chương trình con và bên trong chương trình chính.
Quy trình sẽ làm việc với biến toàn cục i và nó sẽ được gán một giá trị mới bằng 2. Giá trị 2 được hiển thị.
kiểm tra khoảng trống tĩnh () {   int tôi = 5; Console.Write("i"); } kiểm tra khoảng trống tĩnh () {   int tôi = 5;   Console.Write("i"); } khoảng trống tĩnh Main() { int tôi = 7;   Console.Write("i");   Bài kiểm tra(); } sử dụng Hệ thống; chương trình lớp học { int tôi; kiểm tra khoảng trống tĩnh () {   tôi = 2; } khoảng trống tĩnh Main() { Bài kiểm tra(); Console.Write("i"); } }
Nhiệm vụ
Viết thủ tục hoán đổi giá trị của hai biến.

Điểm đặc biệt của nhiệm vụ này là chúng ta cần những thay đổi được thực hiện trong quy trình để chương trình gọi được biết đến.

Hãy thử viết thủ tục như thế này: static void Swap (int a, int b) // với mô tả các tham số thủ tục như vậy, { // sẽ sao chép giá trị của các đối số (x và y) int c; // biến a và b là biến độc lập không liên quan đến x và y c = a; a = b; b=c; } khoảng trống tĩnh Main() { int x=1, y=2; Hoán đổi (x, y); // giá trị của biến x và y (đối số) được sao chép vào tham số a và b, x = 1, y = 2 } Nếu bạn chạy chương trình này, bạn có thể thấy rằng giá trị của các biến x và y không thay đổi. Để các tham số thay đổi giá trị của các đối số, bạn phải sử dụng dữ liệu truyền qua tham chiếu. Để làm điều này, trước tên của loại dữ liệu trong tiêu đề của chương trình con, bạn phải viết ref . void Swap ( ref int a, ref int b ) // lúc này biến a và b lấy địa chỉ của biến x và y trong bộ nhớ { int c; c = a; a = b; b=c; } khoảng trống tĩnh Main() {   int x=1, y=2;   Hoán đổi (tham khảo x, tham khảo y); Ứng dụng: nếu bạn truyền một đối số bằng tham chiếu, thì chỉ tên của biến (KHÔNG phải là số và KHÔNG phải là biểu thức số học) có thể đứng ở vị trí này khi gọi thủ tục.

Bạn không thể gọi một thủ tục như thế này: Hoán đổi(x, 4); Hoán đổi(5+x, y);