Lập trình C: Hàm (Function)


Đăng ký nhận thông báo về những video mới nhất

Giới thiệu

Hầu hết các chương trình viết bằng ngôn ngữ C (cũng như viết bằng những ngôn ngữ khác như C++Java, C#, Python) thường được phân nhỏ thành các hàm (function) trong đó có một hàm chính là main() và chương trình luôn luôn bắt đầu từ hàm main(). Hàm (Function) là phần kiến thức rất quan trọng trong C, nắm tốt kiến thức về hàm bạn sẽ có được thuận lợi khi tìm hiểu các ngôn ngữ lập trình khác.

Khái niệm

Hàm là đoạn chương trình thực hiện trọn vẹn một công việc nhất định (cụ thể). Hàm giúp chia cắt việc lớn thành nhiều việc nhỏ hơn, điều này tương đương với việc chia bài toán lớn thành các bài toán nhỏ hơn để giải, như vậy thì việc giải bài toán sẽ trở nên dễ dàng hơn. Ngoài ra, hàm còn giúp cho chương trình trở nên sáng sủa, dễ sửa, nhất là đối với các chương trình lớn.

Định nghĩa một hàm

Để định nghĩa hay tạo một hàm, ta có thể sử dụng cú pháp như sau:

Kiểu_dữ_liệu Tên_hàm(Khai_báo Các_đối_số) {
  Khai_báo_các_biến_của_hàm;  //Nếu cần
  Khối_lệnh;
  return Giá_trị; //Nếu Kiểu_dữ_liệu là void thì không cần câu lệnh này
}

, trong đó:

Kiểu_dữ_liệu: Là một trong 5 kiểu dữ liệu cơ bản hoặc một trong các kiểu dữ liệu dẫn xuất hay nâng cao. Nếu Kiểu_dữ_liệu là kiểu int thì không cần khai báo Kiểu_dữ_liệu vì int là kiểu dữ liệu mặc định của ngôn ngữ C.

+ Tên_hàm buộc phải có và việc đặt tên phải tuân theo quy tắc đặt tên. Ví dụ muốn sử dụng tên hàm là "Tinh binh phuong" thì không được vì có dấu cách trong đó, ta có thể thay bằng "Tinh_binh_phuong" hoặc "tinhBinhPhuong".

+ Các_đối_số: Không bắt buộc, nghĩa là Các_đối_số có thể có hoặc không có tuỳ thuộc vào mục đích dùng hàm đó để làm gì.

+ Cặp () bao ngoài Các_đối_số và sau Tên_hàm là bắt buộc phải có, ngay cả không có Các_đối_số.

+ Cặp {} là bắt buộc phải có đối với mọi định nghĩa hàm.

+ return Giá_trị: Lệnh này dùng để trả về giá trị cho hàm, nếu Kiểu_dữ_liệu của hàm không phải là void thì lệnh này buộc phải có. Giá_trị có thể là một hằng, giá trị của biến, giá trị của biểu thức hoặc giá trị trả về từ một lời gọi hàm khác.

Một số chú ý đối với hàm:

- Có thể thể gọi một hàm từ hàm khác nhưng bạn không được định nghĩa hàm bên trong hàm (kể cả trong hàm main()).

- Kiểu dữ liệu của Giá_trị nên cùng kiểu (nhưng không được lớn hơn) với kiểu dữ liệu của hàm.

- Bạn có thể định nghĩa hàm nằm trên hoặc nằm dưới hàm main(). Trong trường hợp bạn muốn định nghĩa hàm nằm dưới hàm main() thì bạn cần phải khai báo hàm.

- Mỗi hàm chỉ có thể trả về được duy nhất một giá trị. Trong trường hợp bạn muốn trả về nhiều hơn một giá trị thì bạn có thể sử dụng phương pháp tham chiếu.

- Nơi mà hàm trả về giá trị chính là nơi mà nó được gọi.

Sau đây là một ví dụ áp dụng hàm, đó là viết chương trình tính giai thừa: S = n! (=1*2*3*4*…*n). Chương trình được viết như sau:

#include<stdio.h>

float Giaithua(int n) { //đnh nghĩa hàm Giaithua() có kiu tr v là float có mt đi s kiu int
  int i; //biến cc b ca hàm
  float KQ=1.0; //đây cũng là biến cc b  for (i=1; i<=n; i++)  //n  đây là đi s  ca hàm Giaithua()
    KQ = KQ*i;
  return KQ ; //hàm tr v giá tr lưu trong biến KQ cho nơi gi
}

int main() { //mi chương trình C luôn bt đu t hàm main()
  int n; //khai báo biến nguyên n
  printf("Nhap n = "); //in ra màn hình chui
  scanf("%d",&n); //nhp giá tr cho n
  printf("\nGiai thua cua %d la %f", n, Giaithua(n)); //gi đến hàm Giaithua() trong đó truyn giá tr ca n (thuc hàm main()) cho đi s n ca hàm Giaithua()

  return 0;
}

Dưới đây là một kết quả thực hiện chương trình trên:

Giai thừa 

Khai báo hàm

Việc khai báo một hàm đơn giản hơn so với định nghĩa một hàm. Mục đích của việc khai báo hàm là để cho việc kiểm soát code chương trình của bạn được dễ dàng hơn. Mặt khác, nếu bạn muốn định nghĩa một hàm nằm dưới hàm main() thì bạn bắt buộc phải khai báo hàm. Cú pháp của việc khai báo hàm như sau:

Kiểu_dữ_liệu Tên_hàm(Khai_báo Các_đối_số);

Lưu ý là bạn có thể khai báo hàm nằm bên trong hàm khác, nhưng bạn cần phải khai báo trước khi có lời gọi hàm đến hàm đó. Trong trường hợp khai báo hàm trong hàm main() thì lệnh khai báo phải nằm trên lời gọi hàm clrscr().

Ví dụ trên đây có thể được viết lại như sau:

#include<stdio.h>

float Giai_thua(int n); //Khai báo nhm mc đích đt hàm Giai_thua()  sau hàm main()

int main(){

  int n;

  printf("Nhap n = ");
  scanf("%d",&n);
  printf("\nGiai thua cua %d la %g", n, Giai_thua(n));

  return 0;
}

float Giai_thua(int n) {
  int i;
  float GT=1.0;
  for(i=1; i<=n ; i++)
    GT = GT * i;
  return GT;
}

Lời gọi hàm

Các hàm thường giao tiếp hay gọi đến nhau bằng lời gọi hàm (call function). Việc giao tiếp hay gọi đến nhau của các hàm thông qua cách truyền tham số.

Các tham số được truyền theo một trong hai cách sau đây:

Truyền đối số bằng tham trị (hay giá trị)

Ý nghĩa: Đây là lời gọi hàm mà trong đó đối số thực sự không thay đổi giá trị sau khi hàm được gọi thực hiện xong công việc. Truyền bằng tham trị là lời gọi mặc định của các chương trình C.

Truyền đối số bằng tham chiếu (hay tham biến)

* Bản chất của truyền bằng tham chiếu là truyền địa chỉ của biến.

* Ý nghĩa: cách gọi hàm bằng truyền tham chiếu có thể làm thay đổi giá trị của đối số thực sự. Việc truyền tham chiếu được thực hiện thông qua biện pháp con trỏ. Cú pháp như sau:

Kiểu_dữ_liệu  Tên_hàm(Kiểu _dữ_liệu *Tên_con_trỏ_1, Kiểu_dữ_liệu *Tên_con_trỏ_2,…) {
    Khối_lệnh;
}
void main() {
    Kiểu_dữ_liệu Biến_1;
    Kiểu_dữ_liệu Biến_2;
    …
    Tên_hàm(&Biến_1,&Biến_2,…);
    …
}

Ví dụ dưới đây sẽ viết một hàm có nhiệm vụ hoán đổi giá trị của hai số x và y cho nhau với x và y nhập vào từ bàn phím.

Nếu không dùng phương pháp tham chiếu thì chương trình sẽ không thực hiện được mục đích, tức là hai số x và y vẫn giữ nguyên giá trị sau lời gọi hàm. Chương trình được viết như sau:

#include <stdio.h>

void hoanVi(float x, float y) {
  int z;
  z=x;  //cách khác: x=x+y;
  x=y;  //y=x-y; //y= (x+y)-y = x
  y=z;  //x=x-y; //x= (x+y)-x = y
}

int main() {
  float x, y;
  printf("Nhap 2 so x, y: ");
  scanf("%f%f",&x,&y);
  hoanVi(x, y);
  printf("\nSau khi tien hanh hoan vi, ta duoc: x=%g va y=%g", x, y);

  return 0;
}

Nếu dùng phương pháp tham chiếu thì chương trình sẽ thực hiện được mục đích, x và y sẽ hoán đổi giá trị cho nhau. Chương trình được viết như sau:

#include<stdio.h>

void DoiGT(float *x, float *y) {
  int z;
  z=*x; //cách khác:   *x=*x+*y;
  *x=*y; //*y=*x-*y; //*y= (*x+*y)-*y = *x
  *y=z; //*x=*x-*y;  //*x= (*x+*y)-*x = *y
}

int main() {
  float x, y;
  printf("\nNhap 2 so x, y: ");
  scanf("%f%f", &x, &y);
  DoiGT(&x,&y);
  printf("\nSau khi tien hanh hoan vi, ta duoc: x=%g va y=%g", x, y);

  return 0;
}

Một kết quả demo thể hiện như hình sau:

Lời gọi hàm - Hoán vị

Còn đây là ví dụ viết chương trình nhập vào 3 giá trị kiểu thực (float hoặc double), sau đó tìm giá trị lớn nhất trong 3 giá trị đó. Yêu cầu:

· Phải viết chương trình dưới dạng các hàm.

· Không được sử dụng các biến tổng thể (biến toàn cục).

Theo yêu cầu trên thì ta phải có 3 biến để lưu 3 giá trị muốn so sánh và các biến này phải là các biến địa phương khai báo trong các hàm. Vì hàm main() là hàm chính của chương trình nên ta sẽ khai báo các biến trong hàm main(), và vì chương trình được viết dưới dạng các hàm nên ta khai báo thêm các con trỏ ứng với các biến đó. Sau đây là đoạn code thể hiện:

#include<stdio.h>

void nhap(float *a, float *b, float *c) { //hàm nhp các s a, b và c
  printf("\nNhap a: ");
  scanf("%f", a);
  printf("\nNhap b: ");
  scanf("%f", b);
  printf("\nNhap c: ");
  scanf("%f", c);
}

  float sosanh(float a, float b, float c) { //hàm tìm giá tr ln nht
  float max; //biến lưu li giá tr ln nht
  max = a; //gi s a là s ln nht
  if(max < b) //nếu b ln hơn max
  max = b; //thì gán b cho max
  if(max < c) //nếu c ln hơn max
  max = c; //thì gán c cho max
  return max; //tr li giá tr ln nht lưu trong biến max
}

int main() {
  float a, b, c; //khai báo 3 biến a, b, c
  float max; //khai báo biến lưu tr giá tr ln nht
  nhap(&a,&b,&c);  //Gi hàm nhap() truyn đi số ở dng tham chiếu
  max=sosanh(a,b,c); //Gi và gán giá tr tr v ca hàm sosanh() cho biến max
  printf("\nSo lon nhat trong 3 so nhap vao la: %g", max);

  return 0;
}

Chú ý: Mọi hàm nhập giá trị cho các biến địa phương (cục bộ) đều được truyền theo phương pháp tham chiếu theo mẫu chương trình như trên.


Bài viết này được đóng góp bởi LongDT. Nếu bạn thích V1Study và muốn đóng góp, bạn gửi bài viết về địa chỉ [email protected] hoặc gửi vào Zalo 0986.589.410. Bài viết của bạn sẽ xuất hiện sau khi được duyệt và bạn có thể trợ giúp những người học khác.
« Prev
Next »
Copied !!!