x9nd
05-23-2009, 04:53 PM
Bài 14 : Hàm - Lý thuyết
Giới thiệu
- Hàm là một đoạn chương trình thực hiện một tác vụ được định nghĩa cụ thể. Chúng thực chất là những đoạn chương trình nhỏ giúp giải quyết một vấn đề lớn.
1. Sử dụng các hàm
- Nói chung, các hàm được sử dụng trong C để thực thi một chuỗi các lệnh liên tiếp. Tuy nhiên, cách sử dụng các hàm thì không giống với các vòng lặp. Các vòng lặp có thể lặp lại một chuỗi các chỉ thị với các lần lặp tiếp nhau. Nhưng việc gọi một hàm sẽ sinh ra môt chuỗi các chỉ thị được thực thi tại ví trí bất kỳ trong chương trình. Các hàm có thể được gọi nhiều lần khi có yêu cầu. Giả sử một phần của mã lệnh chương trình dùng để tính tỉ lệ phần trăm cho một vài con số. Nếu sau đó, trong cùng chương trình, việc tính toán như vậy cần phải thực hiện trên những con số khác, thay vì phải viết lại các chỉ thị giống như trên, một hàm có thể được viết ra để tính tỉ lệ phần trăm của bất kỳ các con số. Sau đó chương trình có thể nhẩy đến hàm đó, để thực hiện việc tính toán (trong hàm) và trở về nới nó đã được gọi. Điều này sẽ được giải thích rõ ràng hơn khi thảo luận về cách hoạt động của các hàm.
- Một điểm quan trọng khác là các hàm thì dễ viết và dễ hiểu. Các hàm đơn giản có thể được viết để thực hiện cá tác vụ xác định. Việc gỡ rối chương trình cũng dễ dàng hơn khi cấu trúc chương trình dễ đọc, nhờ vào sự dơn giản hóa hình thức của nó. Mỗi hàm có thể được kiểm tra một cách độc lập với các dữ liệu đầu vào, với dữ liệu hợp lệ cũng như không hợp lệ. Cấc chương trình chứa các hàm cũng dễ bảo trì hơn, bởi vì những sửa đổi, nếu yêu cầu, có thể được giới hạn trong các hàm của chương trình. Một hàm không chỉ được gọi từ các vị trí bên trong chương trình, mà các hàm còn có thể đặt vào một thư viện và được sử dụng bởi nhiều chương trình khác, vì vậy tiết kiệm được thời gian viết chương trình.
2. Cấu trúc hàm
- Cú pháp tổng quát của một hàm trong C là:
Code:
type_specifier function_name (arguments)
{
body of the function
return statement
}
- type_specifier xác định kiểu dữ liệu của giá trị sẽ được trả về bởi hàm. Nếu không có kiểu được đưa ra, hàm cho rằng trả về một kết quả số nguyên. Các đối số được phân cách bởi dấu phẩy. Một cặp dấu ngoặc rỗng () vẫn phải xuất hiện sau trên hàm ngay cả khi nếu hàm không chứa bất kỳ đối số nào. Các tham số xuất hiện trong cặp dấu ngoặc () được gọi là tham số hình thức hoặc đối số hình thức. Phần thân của hàm có thể chứa một hoặc nhiều câu lệnh. Một hàm nên trả về một giá trị và vì vậy ít nhất một lệnh return phải có trong hàm.
3. Các đối số của một hàm
- Phương pháp 1
Code:
squarer (int x)
/* x được định nghĩa cùng với kiểu dữ liệu trong cặp dấu ngoặc ()*/
- Phương pháp 2
Code:
squarer (x)
int x;
/* x được đặt trong cặp dấu ngoặc (), và kiểu của nó đươc khai báo ngay sau tên hàm*/
Chú ý, trong trường hợp sau, x phải được định nghĩa ngay sau tên hàm, trước khối lệnh. Điều này thật tiện lợi khi có nhiều tham số có cùng kiểu dữ liệu được truyền. Trong trường hợp như vậy, chỉ phải chỉ rõ kiểu để một lần duy nhất tại điểm bắt đầu. Khi các đối số được khai báo trong cặp dấu ngoặc (), mỗi đối số phải được định nghĩa riêng lẻ, cho dũ chúng có cùng kiểu dữ liệu. Ví dụ, nếu x và y là hai đối số của một hàm abc(), thì abc(char x, char y) là một khai báo đúng và abc(char x, y) là sai.
4. Sự trả về từ hàm
- Lênh return có hai mục đích
+ Ngay lập tức trả điều khiển từ hàm về chương trình gọi.
+ Bất kỳ cái gì bên trong cặp dấu ngoặc () theo sau return được trả về như là một giá trị cho chương trình gọi.
- Ở đây một biểu thức hợp lệ được xem như một đối số trong câu lện return. Trong thực tế, lệnh return có thể được sử dụng theo một trong các cách sau đây:
Code:
return;
return(hằng);
return(biến);
return(biểu thức);
return(câu lệnh đánh giá); ví dụ return(a>b?a:b);
- Tuy nhiên, giới hạn của câu lện return là nó chỉ có thể trả về một giá trị duy nhất.
5. Kiểu của một hàm
- Type_specifier được sử dụng để xác định kiểu dữ liệu trả về của một hàm. Trong ví dụ trên, type-specifier không được viết bên cạnh hàm squarer(), vì squarer() trả về một giá trị kiểu int. Type-specifier là không bắt buộc nếu một giá trị kiểu số nguyên được trả về hoặc nếu không có giá trị nào được trả về. Tuy nhiên, tốt hơn nên chỉ ra kiểu dữ liệu trả về là int nếu một giá trị số nguyễn được trả về và tương tự dúng void nếu hàm không trả về giá trị nào.
6. Gọi hàm
- Có thể gọi một hàm từ chương trình chính bằng cách sử dụng tên của hàm, theo sau là cặp dấu ngoặc(). Cặp dấu ngoặc là cần thiết để nói với trình biên dịch là đây là một lời gọi hàm. Khi một tên hàm được sử dụng trong chương trình gọi, tên hàm có thể là một phần của một lệnh hoặc chính nó là một câu lệnh. Mà ta đã biết một câu lệnh luôn kết thúc với một dấu chấm phẩy (. Tuy nhiên, khi định nghĩa hàm, không được dùng dấu chấm phẩy ở cuối phần định nghĩa. Sự vắng mặt của dấu chấm phẩy nói với trình biên dịch đây là phần định nghĩa của hàm và không được gọi hàm.
- Một số điều cần nhớ:
+ Một dấu chấm phẩy được dùng ơ cuối câu lệnh khi một hàm được gọi, nhưng nó không được dùng sau một sự định nghĩa hàm.
+ Cặp dấu ngoặc () là bắt buộc theo sau tên hàm, cho dù có đối số hay không.
+ Hàm gọi đến một hàm khác được gọi là hàm gọi hay thủ tực gọi. Và hàm được gọi đến còn được gọi là hàm gọi hay thủ tục được gọi.
+ Các hàm không trả về một giá trị số nguyên cần phải xác định kiểu của giá trị được trả về.
+ Chỉ một giá trị có thể được trả về bởi một hàm.
+ Một chương trình có thể có một hoặc nhiều hàm.
7. Khai báo hàm
- Một hàm nên được khai báo trong hàm main() trước khi nó được định nghĩa hoặc sử dụng. Điều này phải được thực hiện trong trường hợp hàm được gọi trước khi nó được định nghĩa.
8. Các nguyên mẫu hàm
-Một nguyên mẫu hàm là một khai báo trong đó xác định rõ kiểu dữ liệu của các đối số và trị trả về. Thông thường, các hàm được khai báo bằng cách xác định kiểu của giá trị được trả về bới hàm, và tên hàm. Tuy nhiên, chuẩn ANSI C cho phép số lượng và kiểu dữ liệu của các đối số hàm được khai báo. Một hàm abc() có hai đối số kiểu int là x và y, và trả một giá trị kiểu char, có thể được khai báo như sau:
Code:
char abc()
hoặc
char abc(int x, int y);
- Cách định nghĩa sau được gọi là nguyên mẫu hàm. Khi các nguyên mẫu được sử dụng, C có thể tìm và thông báo bất kỳ kiểu dữ liệu không hợp lệ khi chuyển đổi giữa các đối số được dùng để gọi một hàm với sự định nghĩa kiểu của các tham số. Một số sẽ được thông báo ngay khi có sự khác nhau giữa số lượng các đối số được sử dụng để gọi hàm và số lượng các tham số khi định nghĩa hàm. Cú pháp tổng quát của một nguyên mẫu hàm:
Code:
type function_name(type parm_name, type parm_name2,...,type parm_nameN)
- Khi hàm được khai báo không có các thông tin nguyên mẫu, trình biên dịch cho rằng không có thông tin về các tham số được đưa ra. Một hàm không có đối số có thể gây ra lỗi khi khai báo không có thông tin nguyên mẫu. Để tránh điều này, khi một hàm không có tham số, nguyên mẫu của nó sử dụng void trong cặp dấu ngoặc(). Như đã nói ở trên, void cũng được sử dụng để khai báo tường mình một hàm không có giá trị trả về.
Giới thiệu
- Hàm là một đoạn chương trình thực hiện một tác vụ được định nghĩa cụ thể. Chúng thực chất là những đoạn chương trình nhỏ giúp giải quyết một vấn đề lớn.
1. Sử dụng các hàm
- Nói chung, các hàm được sử dụng trong C để thực thi một chuỗi các lệnh liên tiếp. Tuy nhiên, cách sử dụng các hàm thì không giống với các vòng lặp. Các vòng lặp có thể lặp lại một chuỗi các chỉ thị với các lần lặp tiếp nhau. Nhưng việc gọi một hàm sẽ sinh ra môt chuỗi các chỉ thị được thực thi tại ví trí bất kỳ trong chương trình. Các hàm có thể được gọi nhiều lần khi có yêu cầu. Giả sử một phần của mã lệnh chương trình dùng để tính tỉ lệ phần trăm cho một vài con số. Nếu sau đó, trong cùng chương trình, việc tính toán như vậy cần phải thực hiện trên những con số khác, thay vì phải viết lại các chỉ thị giống như trên, một hàm có thể được viết ra để tính tỉ lệ phần trăm của bất kỳ các con số. Sau đó chương trình có thể nhẩy đến hàm đó, để thực hiện việc tính toán (trong hàm) và trở về nới nó đã được gọi. Điều này sẽ được giải thích rõ ràng hơn khi thảo luận về cách hoạt động của các hàm.
- Một điểm quan trọng khác là các hàm thì dễ viết và dễ hiểu. Các hàm đơn giản có thể được viết để thực hiện cá tác vụ xác định. Việc gỡ rối chương trình cũng dễ dàng hơn khi cấu trúc chương trình dễ đọc, nhờ vào sự dơn giản hóa hình thức của nó. Mỗi hàm có thể được kiểm tra một cách độc lập với các dữ liệu đầu vào, với dữ liệu hợp lệ cũng như không hợp lệ. Cấc chương trình chứa các hàm cũng dễ bảo trì hơn, bởi vì những sửa đổi, nếu yêu cầu, có thể được giới hạn trong các hàm của chương trình. Một hàm không chỉ được gọi từ các vị trí bên trong chương trình, mà các hàm còn có thể đặt vào một thư viện và được sử dụng bởi nhiều chương trình khác, vì vậy tiết kiệm được thời gian viết chương trình.
2. Cấu trúc hàm
- Cú pháp tổng quát của một hàm trong C là:
Code:
type_specifier function_name (arguments)
{
body of the function
return statement
}
- type_specifier xác định kiểu dữ liệu của giá trị sẽ được trả về bởi hàm. Nếu không có kiểu được đưa ra, hàm cho rằng trả về một kết quả số nguyên. Các đối số được phân cách bởi dấu phẩy. Một cặp dấu ngoặc rỗng () vẫn phải xuất hiện sau trên hàm ngay cả khi nếu hàm không chứa bất kỳ đối số nào. Các tham số xuất hiện trong cặp dấu ngoặc () được gọi là tham số hình thức hoặc đối số hình thức. Phần thân của hàm có thể chứa một hoặc nhiều câu lệnh. Một hàm nên trả về một giá trị và vì vậy ít nhất một lệnh return phải có trong hàm.
3. Các đối số của một hàm
- Phương pháp 1
Code:
squarer (int x)
/* x được định nghĩa cùng với kiểu dữ liệu trong cặp dấu ngoặc ()*/
- Phương pháp 2
Code:
squarer (x)
int x;
/* x được đặt trong cặp dấu ngoặc (), và kiểu của nó đươc khai báo ngay sau tên hàm*/
Chú ý, trong trường hợp sau, x phải được định nghĩa ngay sau tên hàm, trước khối lệnh. Điều này thật tiện lợi khi có nhiều tham số có cùng kiểu dữ liệu được truyền. Trong trường hợp như vậy, chỉ phải chỉ rõ kiểu để một lần duy nhất tại điểm bắt đầu. Khi các đối số được khai báo trong cặp dấu ngoặc (), mỗi đối số phải được định nghĩa riêng lẻ, cho dũ chúng có cùng kiểu dữ liệu. Ví dụ, nếu x và y là hai đối số của một hàm abc(), thì abc(char x, char y) là một khai báo đúng và abc(char x, y) là sai.
4. Sự trả về từ hàm
- Lênh return có hai mục đích
+ Ngay lập tức trả điều khiển từ hàm về chương trình gọi.
+ Bất kỳ cái gì bên trong cặp dấu ngoặc () theo sau return được trả về như là một giá trị cho chương trình gọi.
- Ở đây một biểu thức hợp lệ được xem như một đối số trong câu lện return. Trong thực tế, lệnh return có thể được sử dụng theo một trong các cách sau đây:
Code:
return;
return(hằng);
return(biến);
return(biểu thức);
return(câu lệnh đánh giá); ví dụ return(a>b?a:b);
- Tuy nhiên, giới hạn của câu lện return là nó chỉ có thể trả về một giá trị duy nhất.
5. Kiểu của một hàm
- Type_specifier được sử dụng để xác định kiểu dữ liệu trả về của một hàm. Trong ví dụ trên, type-specifier không được viết bên cạnh hàm squarer(), vì squarer() trả về một giá trị kiểu int. Type-specifier là không bắt buộc nếu một giá trị kiểu số nguyên được trả về hoặc nếu không có giá trị nào được trả về. Tuy nhiên, tốt hơn nên chỉ ra kiểu dữ liệu trả về là int nếu một giá trị số nguyễn được trả về và tương tự dúng void nếu hàm không trả về giá trị nào.
6. Gọi hàm
- Có thể gọi một hàm từ chương trình chính bằng cách sử dụng tên của hàm, theo sau là cặp dấu ngoặc(). Cặp dấu ngoặc là cần thiết để nói với trình biên dịch là đây là một lời gọi hàm. Khi một tên hàm được sử dụng trong chương trình gọi, tên hàm có thể là một phần của một lệnh hoặc chính nó là một câu lệnh. Mà ta đã biết một câu lệnh luôn kết thúc với một dấu chấm phẩy (. Tuy nhiên, khi định nghĩa hàm, không được dùng dấu chấm phẩy ở cuối phần định nghĩa. Sự vắng mặt của dấu chấm phẩy nói với trình biên dịch đây là phần định nghĩa của hàm và không được gọi hàm.
- Một số điều cần nhớ:
+ Một dấu chấm phẩy được dùng ơ cuối câu lệnh khi một hàm được gọi, nhưng nó không được dùng sau một sự định nghĩa hàm.
+ Cặp dấu ngoặc () là bắt buộc theo sau tên hàm, cho dù có đối số hay không.
+ Hàm gọi đến một hàm khác được gọi là hàm gọi hay thủ tực gọi. Và hàm được gọi đến còn được gọi là hàm gọi hay thủ tục được gọi.
+ Các hàm không trả về một giá trị số nguyên cần phải xác định kiểu của giá trị được trả về.
+ Chỉ một giá trị có thể được trả về bởi một hàm.
+ Một chương trình có thể có một hoặc nhiều hàm.
7. Khai báo hàm
- Một hàm nên được khai báo trong hàm main() trước khi nó được định nghĩa hoặc sử dụng. Điều này phải được thực hiện trong trường hợp hàm được gọi trước khi nó được định nghĩa.
8. Các nguyên mẫu hàm
-Một nguyên mẫu hàm là một khai báo trong đó xác định rõ kiểu dữ liệu của các đối số và trị trả về. Thông thường, các hàm được khai báo bằng cách xác định kiểu của giá trị được trả về bới hàm, và tên hàm. Tuy nhiên, chuẩn ANSI C cho phép số lượng và kiểu dữ liệu của các đối số hàm được khai báo. Một hàm abc() có hai đối số kiểu int là x và y, và trả một giá trị kiểu char, có thể được khai báo như sau:
Code:
char abc()
hoặc
char abc(int x, int y);
- Cách định nghĩa sau được gọi là nguyên mẫu hàm. Khi các nguyên mẫu được sử dụng, C có thể tìm và thông báo bất kỳ kiểu dữ liệu không hợp lệ khi chuyển đổi giữa các đối số được dùng để gọi một hàm với sự định nghĩa kiểu của các tham số. Một số sẽ được thông báo ngay khi có sự khác nhau giữa số lượng các đối số được sử dụng để gọi hàm và số lượng các tham số khi định nghĩa hàm. Cú pháp tổng quát của một nguyên mẫu hàm:
Code:
type function_name(type parm_name, type parm_name2,...,type parm_nameN)
- Khi hàm được khai báo không có các thông tin nguyên mẫu, trình biên dịch cho rằng không có thông tin về các tham số được đưa ra. Một hàm không có đối số có thể gây ra lỗi khi khai báo không có thông tin nguyên mẫu. Để tránh điều này, khi một hàm không có tham số, nguyên mẫu của nó sử dụng void trong cặp dấu ngoặc(). Như đã nói ở trên, void cũng được sử dụng để khai báo tường mình một hàm không có giá trị trả về.