Nhập Môn Lập Trình C - Phần 3

BinhHT
NHẬP MÔN LẬP TRÌNH C

8013

CHƯƠNG 3: HÀM TRONG NGÔN NGỮ LẬP TRÌNH C

I. HÀM TRONG NGÔN NGỮ LẬP TRÌNH C

I.1 Giới thiệu về hàm


Hàm trong C nói riêng và các ngôn ngữ lập trình khác nói chung là một đoạn chương trình bao gồm một hoặc nhiều xử lý nhằm giải quyết một công việc nào đó và được xây dựng với mục đích tái sử dụng. Ví dụ như chương trình cần nhập 3 số a, b, c. Nếu bạn không sử dụng hàm thì đoạn code sẽ như sau.


C:
#include <stdio.h>

int main()
{
    int a, b, c;
    printf("Nhap so a\n");
    scanf("%d",&a);

    printf("Nhap so b\n");
    scanf("%d",&b);

    printf("Nhap so c\n");
    scanf("%d",&c);

    return 0;
}

Nhìn đoạn code trên, bạn thấy chương trình sẽ trở nên dài và không tối ưu, vì vậy để khắc phục việc cứ phải mỗi lần làm một công việc nào đó nhiều lần thì người ta đã tạo ra hàm để khắc phục những việc như thế. Sau đây là đoạn code sử dụng hàm.

C:
#include <stdio.h>

void inputNumber(int &x)
{
    printf("Nhap so\n")
    scanf("%d",x);
}

int main()
{
    int a, b, c;
    inputNumber(a);
    inputNumber(b);
    inputNumber(c);
    printf("Cac so da nhap = %d %d %d",a,b,c);
    return 0;
}

Ở đoạn code trên, mình đã tạo một hàm tên là inputNumber. Cú pháp khai báo hàm như sau : Kiểu_dữ_liệu Tên_Hàm(Tham_Số_1, Tham_Số_2, Tham_Số_3,......). Kiểu dữ liệu ở đây có thể là các kiểu dữ liệu chúng ta đã học như kiểu int, float, double, long... Kiểu dữ liệu của hàm có 2 loại, 1 là kiểu dữ liệu trả về giá trị2 là kiểu dữ liệu không trả về giá trị. Ở hàm inputNumber bên trên, từ khóa void được dùng để nói rằng hàm này không có kiểu trả về. Nếu một hàm được khai báo là các kiểu dữ liệu như int, float, long, double... Thì cuối hàm ta phải có từ khóa return để trả về giá trị. Hàm có thể có hoặc không có tham số, như hàm inputNumber bên trên thì ta khai báo một tham số là x. Tương ứng với các biến a, b, c mà ta đã gọi hàm trong hàm main(). Kiểu dữ liệu không trả về thường được dùng để thực hiện một số công việc như in ra một kết quả, hoán vị hai số, tìm kiếm một phần tử nào đó... Còn kiểu dữ liệu trả về thường được dùng để thực hiện một số công việc như tính tổng các số, thêm một giá trị vào trong một mảng... Sau đây là code demo cho hai loại hàm.
C:
#include <stdio.h>

int tinhTongHaiSo(int &a, int &b)
{
    int sum = 0;
    sum = a + b;
    return sum;
}

void inRaMotDongChu()
{
    printf("Hello World, Let's learn Programming!.");
}

int main()
{
    int a, b;
    printf("Nhap so a \n");
    scanf("%d",&a);
    printf("Nhap so b \n");
    scanf("%d,&b");
    printf("Tong hai so %d va %d la %d",a,b,tinhTongHaiSo(a,b));
    inRaMotDongChu();
    return 0;
}

Ở đoạn code trên mình đã tạo hai hàm là tinhTongHaiSo inMotDongChu. Ở hàm tính tổng hai số thì mình cho hàm đó thực hiện việc tính tổng và do mình khai báo kiểu dữ liệu của hàm là int nên phải có câu lệnh return để trả về giá trị, lưu ý là nếu ta khai báo kiểu dữ liệu nào thì giá trị trả về phải phù hợp với kiểu dữ liệu đó. Ở đây do mình khai báo kiểu dữ liệu của hàm là kiểu int nên giá trị trả về của mình cũng phải là kiểu int, tương tự như khi khai báo các kiểu double, float, long... Nếu kiểu trả về không giống với kiểu dữ liệu đã khai báo thì chương trình sẽ báo lỗi.

Hàm được đặt tên phải là động từ, dùng để diễn tả công việc mà hàm đó thực hiện, tên hàm không được trùng với các từ khóa đặc biệt trong C, không chứa khoảng trắng. Cú pháp để khai báo hàm như sau
Kiểu_dữ_liệu Tên_Hàm(Tham số 1, Tham số 2...)
{
// TODO
}

Ở trong hàm main, nếu muốn gọi hàm thì ta chỉ việc ghi ra tên hàm là hàm đó sẽ được gọi.

I.2 Tham số và đối số.

Khi làm việc với hàm thì ta phải biết hai khái niệm là tham số và đối số, tham số là những giá trị được khai báo ở ngay sau tên hàm. Ví dụ như:
int tinhTong(int a, int b). Ở đây, hai biến ab được gọi là tham số của hàm. Còn khi ta gọi hàm trong hàm main thì biến hay giá trị được truyền vào trong hàm ta gọi là đối số. Ví dụ như :

C:
#include <stdio.h>

int tinhTong(int a, int b)
{
// TODO...
}

int main()
{
    int a, b;
    //...
    tinhTong(a,b);
    //...
    return 0;
}

Hàm tinhTong được gọi trong hàm main, lúc này hai biến ab trong hàm main được truyền vào trong hàm tinhTong ta gọi là đối số (tinhTong(a,b).

II. THAM SỐ CỦA HÀM


Tham số của hàm cũng còn được gọi là tham số hình thức, biến hình thức hay đối số. Đây là danh sách những biến được đặt trong dấu ngoặc khi viết hàm: chẳng hạn như các biến a b khi viết hàm int tinhTong(int a, int b). Khi gọi hàm thì các tham số này có thể được thay thế bằng biến thực sự. Chẳng hạn như ở đoạn code đầu tiên, mình đã thay thế biến x bằng các biến a, b c. Đôi khi trong một số chương trình ta cũng thấy có trường hợp đối số và biến thực sự có tên trùng nhau.
Việc gửi các biến đến hàm khi gọi hàm cũng được gọi là truyền tham số hay trao đổi tham số. Chúng ta cần phân biệt hai trường hợp: tham số giá trịtham số dạng tham chiếu.

II.1 Tham số giá trị

Tham số giá trị
được hiểu là ta truyền bản sao của các biến, giá trị của các biến được truyền vào trong hàm trước và sau khi thực hiện hàm có giá trị không đổi.

C:
#include <stdio.h>

void hoanVi(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
    printf("Sau khi hoan vi a = %d, b = %d",a,b);
}

int main()
{
    int a, int b;
    printf("Nhap so a\n");
    scanf("%d",&a);
    printf("Nhap so b\n");
    scanf("%d",&b);
    printf("Truoc khi hoan vi a = %d, b = %d",a,b);
    hoanVi(a,b);
    printf("Sau khi hoan vi a = %d, b = %d",a,b);
    return 0;
}

Ở đoạn code trên, hàm hoanVi có nhiệm vụ đổi chỗ hai số ab. Nhìn kĩ thì các bạn sẽ thấy mình khai báo hàm như sau. void hoanVi(int a, int b), đây là kiểu khai báo tham số giá trị hay còn gọi là tham trị. Ví dụ như mình nhập a = 10b = 5. Thì khi ta truyền hai số a b này vào trong hàm thì hàm sẽ thực hiện hoán vị hai số. Minh chứng cho việc hàm này có thực hiện hoán vị là câu lệnh printf("Sau khi hoán vị .... ) bên trong thân hàm sẽ in ra hai số ab đã bị hoán vị. Nhưng khi câu lệnh printf("Sau khi hoan vi...) trong hàm main thì lại in ra hai số ab không bị hoán vị mặc dù trong hàm main đã gọi hàm hoanVi. Nguyên do là do nếu ta truyền kiểu tham số giá trị thì hàm sẽ thực hiện nhiệm vụ nào đó và nhiệm vụ đó chỉ có tác dụng bên trong thân hàm, và khi nó thoát khỏi hàm thì việc thực hiện bên trong thân hàm sẽ không còn tác dụng. Do đó mà với dạng truyền tham số thì hai biến ab trước và sau khi hoán vị không khác nhau.

II.2 Tham số dạng tham chiếu.

Trong trường hợp cần tính toán và thay đổi giá trị của biến gửi đến hàm thì phải dùng tham số dạng tham chiếu (còn gọi là truyền địa chỉ hay tham biến). Tức là biến được gửi đến hàm, khi thực hiện các chỉ thị bên trong hàm sẽ có những chỉ thị tính toán tác động lên biến đó sao cho khi kết thúc hàm thì giá trị của biến đó cũng bị thay đổi. Trường hợp này biến gửi đến sẽ được gắn kết trực tiếp với tham số hình thức, vào lúc hàm đang chạy thì tham số hình thức và biến gửi đến xem như đồng nhất với nhau.

Ngôn ngữ C++ qui ước dùng dấu & đặt phía trước các tham số dạng tham chiếu. Cơ chế này chỉ dành riêng cho C++, không thể dùng cho các chương trình ngôn ngữ C. Với các chương trình C thì chúng ta sẽ cài đặt đối số tham chiếu dựa vào biến con trỏ (phần này sẽ nói sau).

C:
#include <stdio.h>

void hoanVi(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}


int main()
{
    int a = 10, b = 20;
    printf("Truoc khi hoan vi, a = %d, b = %d\n",a,b);
    hoanVi(&a,&b);
    printf("Sau khi hoan vi a = %d, b = %d\n",a,b);
    return 0;
}

Ở đoạn code trên hàm hoanVi cũng có chức hoán vị hai số, nhưng khác với kiểu truyền tham trị thì kết quả trước và sau khi hoán vị không bị thay đổi thì ở cách truyền tham chiếu này thì kết quả của hai biến ab trước và sau khi hoán vị đã thay đổi. Để truyền tham chiếu thì ở phần đối số trong hàm main, các bạn thêm dấu & trước các biến ( dấu & là chỉ địa chỉ của các biến ), và ở phần tham số của hàm thì các biến để dấu * ( dấu * là khai báo con trỏ, con trỏ chỉ lưu địa chỉ của biến nên ở phần đối số ta phải khai báo địa chỉ của các biến truyền vào hàm.

Mình đã trình bày sơ lược và một số điểm quan trọng khi làm việc với hàm trong ngôn ngữ C. Còn 1 phần nữa là về mảng và cũng là phần cuối cùng và cũng là kết thúc series Nhập Môn Lập Trình C của mình. Nếu các bạn có yêu cầu hay thắc mắc gì thì hãy nhắn tin riêng cho mình. Cám ơn cám bạn đã đọc.
 
Sửa lần cuối:
Trả lời

1234560987

Rìu Vàng
Mình nghĩ là ở đầu hoặc cuối bài viết nên đưa link dẫn tới những phần khác cho mọi người tiện tìm kiếm thì hay hơn
 

love2learnonline

Rìu Sắt
Mình nghĩ là ở đầu hoặc cuối bài viết nên đưa link dẫn tới những phần khác cho mọi người tiện tìm kiếm thì hay hơn
EM NÓ ĐÂY: :)
Nhập Môn Lập Trình C - Phần 1
Mã:
https://vn-z.vn/threads/nhap-mon-lap-trinh-c-phan-1.16898/#post-229706
Nhập Môn Lập Trình C - Phần 2
Mã:
https://vn-z.vn/threads/nhap-mon-lap-trinh-c-phan-2.17051/#post-233562