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 mã, trong trường hợp bạn cần viết cùng một mã ở những vị trí khác nhau trong chương trình. 
Các thư viện được nhập vào một chương trình (ví dụ: thư viện toán học toán học) bao gồm các chương trình con đã được biên dịch sẵn bởi một người nào đó. Các lập trình viên không cần phải suy nghĩ về những thuật toán mà họ thực hiện, mà 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 quy trình chỉ nên làm một việc:  hoặc chỉ tính toán điều gì đó hoặc xuất ra một số dữ liệu hoặc làm điều gì đó khác. 

Có hai loại chương trình con - thủ tụchàm

Chương trình con thực hiện một số hành động, chẳng hạn như in kết quả ra màn hình theo một dạng nhất định (ví dụ đơn giản, câu lệnh writeln() là một chương trình con chuẩn in ra thông tin màn hình)

Các chương trình con hàm trả về kết quả (số, chuỗi ký tự, v.v.) mà chúng ta có thể sử dụng trong chương trình chính.

Hãy thử viết một thủ tục đơ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 tuyên bố writeln('Lỗi'); Và bây giờ hãy tưởng tượng rằng một dòng như vậy cần được chèn vào nhiều chỗ 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 trong 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 thủ tục là cần thiết.
Một chương trình với một thủ tục có thể trông như thế này: ... sử dụng không gian tên std; thủ tục printError(); //mô tả thủ tục bắt đầu writeln('Lỗi'); // thân thủ tục - các lệnh mà thủ tục sẽ thực hiện kết thúc; // chương trình chính bắt đầu; ... lỗi in(); // bắt đầu thủ tục để thực thi. Chúng tôi chỉ chỉ định tên của thủ tục mà chúng tôi muốn thực hiện. ... lỗi in(); ... kết thúc. Thủ tục bắt đầu bằng từ thủ tục. Sau tên của thủ tục, các dấu ngoặc đơn được viết, cho biết các biến và loại của chúng phụ thuộc vào việc thực hiện thủ tục. Ví dụ:

var a, b, answer: integer;
thủ tục Sum(a, b: số nguyên);
bắt đầu
    trả lời := a + b;
kết thúc;

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ác thủ tục được viết trước chương trình chính

Để thực hiện một thủ tục, trong chương trình chính, bạn cần gọi thủ tục đó bằng tên và nhớ 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â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 loại lỗi mà anh ta mắc phải.
Trong trường hợp này, bạn có thể viết quy trình của riêng mình cho mỗi lỗi:   thủ tục printErrorZero(); bắt đầu writeln('Lỗi. Chia hết cho 0!'); kết thúc; thủ tục printErrorInput(); bắt đầu writeln('Lỗi nhập liệu!'); kết thúc; Điều gì xảy ra nếu có nhiều lỗi hơn có thể xảy ra? 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 thủ tục printError(s: string); bắt đầu writeln(s); kết thúc; Trong thủ tục này, s là một tham số - một biến đặc biệt cho phép bạn kiểm soát thủ tục.
Tham số là một biến xác định cách hoạt động của chương trình con. Tên tham số được liệt kê cách nhau bằng dấu chấm phẩy trong tiêu đề chương trình con. Sau tham số, một dấu hai chấm được theo sau bởi loại của nó.

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

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 một biến khỏi bị 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ục.

Phân tích ba chương trình: được hiển thị trên màn hì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ạy chương trình này, màn hình sẽ hiển thị giá trị 75
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
Thủ tục sẽ làm việc với biến toàn cục i và nó sẽ được gán giá trị mới bằng 2. Giá trị 2
kiểm tra thủ tục();
var i: số nguyên;
bắt đầu
    tôi := 5;
    writeln(i);
kết thúc;
var i: số nguyên;

kiểm tra thủ tục();
var i: số nguyên;
bắt đầu
    tôi := 5;
    writeln(i);
kết thúc;

bắt đầu
    tôi := 7;
    ghi(i);
    kiểm tra();
kết thúc.
var i: số nguyên;

kiểm tra thủ tục();
bắt đầu
    tôi := 2;
kết thúc;

bắt đầu
    kiểm tra();
    writeln(i);
kết thúc.
Bài toán:viết thủ tục hoán đổi giá trị của hai biến.
Điểm đặc biệt của tác 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:

var x, y: số nguyên; thủ tục Hoán đổi (a, b: số nguyên); // với mô tả như vậy về các tham số thủ tục, var c: số nguyên; begin // sẽ sao chép giá trị của các đối số (x và y) // biến a và b là biến độc lập không liên quan đến x và y c := a; một := b; b := c; kết thúc; bắt đầu 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 writeln('x = ', x, ', y = ', y); // x=1, y=2 kết thúc. 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 xy không thay đổi. Để các tham số thay đổi giá trị của đối số, bạn phải sử dụng truyền dữ liệu theo tham chiếu. Để làm điều này, sau tên của loại dữ liệu trong tiêu đề của chương trình con, bạn phải đặt từ var  thủ tục Hoán đổi(var a, b: số nguyên);   // bây giờ biến a và b lấy địa chỉ của biến x và y trong bộ nhớ var c: số nguyên;  bắt đầu c := a; một := b; b := c; kết thúc; Cách sử dụng: Nếu bạn truyền đối số bằng tham chiếu, thì chỉ có tên biến (KHÔNG phải số và KHÔNG phải biểu thức số học) có thể ở vị trí này khi gọi thủ tục!< br />
KHÔNG gọi thủ tục như thế này: Hoán đổi(x, 4); Hoán đổi(5+x, y);