Xem thêm

Bài 27. Hàm trong C

Huy Erick
Trong bài viết này, chúng ta sẽ tìm hiểu về hàm trong ngôn ngữ lập trình C. Chúng ta sẽ không chỉ đưa ra lý do tại sao nên sử dụng hàm, cách gọi hàm...

Trong bài viết này, chúng ta sẽ tìm hiểu về hàm trong ngôn ngữ lập trình C. Chúng ta sẽ không chỉ đưa ra lý do tại sao nên sử dụng hàm, cách gọi hàm và cách hoạt động của một chương trình sử dụng hàm, mà còn đi sâu vào một số ưu điểm và cách sử dụng hàm một cách hiệu quả. Bài viết sẽ giúp bạn hiểu rõ hơn về chức năng và quy trình làm việc của hàm trong ngôn ngữ lập trình C.

Hàm trong C là gì?

Hãy cùng đặt một tình huống! Giả sử bạn đang muốn xây dựng một công ty (một chương trình máy tính nhỏ). Công ty của bạn có 4 mục tiêu chính: tính tổng, hiệu, tích và thương của hai số nguyên được nhập từ bàn phím.

Nếu chỉ có một người và người đó phải tự thực hiện và quản lý cả 4 công việc (viết mã trong hàm main()), điều này hoàn toàn khả thi. Nhưng hãy nghĩ xem, nếu bạn đơn độc phải làm cả 4 công việc, liệu bạn có thể quản lý tốt nó không? Bạn có đủ thời gian để tối ưu hóa và phát triển từng công việc không? Bạn nghĩ sao nếu trong lúc căng thẳng bạn quên hoặc làm nhầm công việc cần làm?

Giải pháp: Thuê 4 nhân viên và trả lương cho họ, mỗi người chỉ thực hiện một công việc duy nhất. Khi đó, công việc của sếp (hàm main()) là quản lý những nhân viên này, khi cần thì gọi họ làm việc và nếu có vấn đề gì, sẽ xử lý với từng nhân viên.

Vậy hàm trong C là gì? Hàm chính là những nhân viên trong vấn đề trên. Trong lập trình, hàm là những khối mã nhỏ chỉ thực hiện một chức năng cụ thể của bài toán lớn.

Bạn có thể hình dung công ty sẽ như thế nào sau khi áp dụng giải pháp trên:

#include  

int add(int a, int b) {
    // Hàm này là nhân viên làm công việc phép cộng
}

int subtract(int a, int b) {
    // Hàm này là nhân viên làm công việc phép trừ
}

int multiply(int a, int b) {
    // Hàm này là nhân viên làm công việc phép nhân
}

float divide(int a, int b) {
    // Hàm này là nhân viên làm công việc phép chia
}

int main(){
    // Hàm này là sếp
}

Ưu điểm khi sử dụng hàm

Dưới đây là một số ưu điểm nổi bật khi sử dụng hàm trong lập trình C. Hãy thử thực hành viết code của bạn bằng cách sử dụng hàm nếu có thể nhé.

  • Dễ hiểu và dễ quản lý: Sử dụng hàm khiến code trở nên sáng sủa và gọn gàng hơn, người đọc code sẽ dễ hiểu hơn bằng cách nhìn vào từng hàm, ta có thể dễ dàng xác định vai trò của nó trong chương trình.

  • Dễ quản lý, nâng cấp và tìm lỗi: Bạn biết rõ hàm nào đang làm gì, nếu gặp lỗi, bạn có thể nhanh chóng xác định lỗi đó thuộc về hàm nào thay vì phải tìm lỗi từng dòng trong hàm main.

  • Viết 1 lần, sử dụng ở nhiều nơi: Khi sử dụng hàm, bạn chỉ cần viết một lần và gọi nó bất kỳ khi nào bạn muốn. Bạn cũng có thể đóng gói các hàm đó để sử dụng cho các chương trình khác.

Cách hoạt động của hàm trong C

Hình ảnh dưới đây cho bạn thấy cách hoạt động của hàm trong ngôn ngữ C. Khi một lời gọi hàm được thực thi, chương trình của bạn sẽ nhảy tới nơi định nghĩa hàm đó và thực thi các lệnh từ trên xuống dưới trong hàm đó. Khi hàm thực hiện xong, chương trình sẽ tiếp tục thực hiện các lệnh phía sau lời gọi hàm.

Hình ảnh minh họa cách hoạt động của hàm trong ngôn ngữ C

Chương trình máy tính bỏ túi đơn giản

Dưới đây, chúng ta sẽ xem một ví dụ sử dụng hàm trong C để xây dựng một ứng dụng máy tính bỏ túi đơn giản, thực hiện 4 chức năng cơ bản là cộng, trừ, nhân và chia. Hãy xem giải thích trong code và xem video để hiểu rõ hơn.

#include 

/* Cách khai báo hàm   () {
    // thân hàm
    return ; // value phải cùng kiểu 
} */

// Tính tổng của hai số
// a: số thứ nhất
// b: số thứ hai
int add(int a, int b) {
    int sum = a + b;
    return sum; // lệnh return trả về giá trị cùng kiểu dữ liệu với kiểu dữ liệu của hàm
}

// Tính hiệu của a - b
int subtract(int a, int b) {
    return a - b;
}

// Tính tích của a * b
int multiply(int a, int b) {
    return a * b;
}

// Tính thương của a / b
float divide(int a, int b) {
    return (float) a / b;
}

int main() {
    int a = 3, b = 4;

    // Sử dụng tên hàm để gọi nó,
    // truyền các tham số đúng theo kiểu của hàm yêu cầu
    printf("%d + %d = %d\n", a, b, add(a, b));
    printf("%d - %d = %d\n", a, b, subtract(a, b));
    printf("%d * %d = %d\n", a, b, multiply(a, b));
    if(b != 0){
        printf("%d / %d = %.2f\n", a, b, divide(a, b));
    }
    return 0;
}

Kết quả chạy chương trình:

3 + 4 = 7
3 - 4 = -1
3 * 4 = 12
3 / 4 = 0.75

Các bài viết tiếp theo sẽ nói rõ hơn về các loại hàm và cung cấp nhiều bài tập thực hành. Hãy tiếp tục theo dõi để cung cấp kiến thức đầy đủ về hàm trong ngôn ngữ lập trình C.

Các loại hàm trong C

Dưới đây là một ví dụ từ tài liệu tham khảo [2] để thể hiện cho bạn 4 loại hàm trong C. Chúng ta sẽ sử dụng 4 cách để giải quyết cùng một bài toán: "Kiểm tra xem một số nhập từ bàn phím có phải số nguyên tố không". Cuối cùng, chúng ta sẽ rút ra những kết luận!

Hàm không có tham số, không có giá trị trả về

#include 

void checkPrimeNumber();

int main() {
    checkPrimeNumber(); // không truyền tham số
    return 0;
}

// Kiểu trả về là void nghĩa là không trả về giá trị nào
void checkPrimeNumber() {
    int n, i, flag = 0;
    printf("Nhập một số nguyên dương: ");
    scanf("%d", &n);
    for(i=2; i <= n/2; ++i) {
        if(n%i == 0) {
            flag = 1;
            break;
        }
    }
    if (flag == 1)
        printf("%d không phải là số nguyên tố.", n);
    else
        printf("%d là số nguyên tố.", n);
}

Nhận xét:

  • Hàm checkPrimeNumber() không có tham số đầu vào, nó tự thực hiện việc nhận giá trị từ bàn phím, kiểm tra và in kết quả. Vì không trả về giá trị nào, chúng ta sử dụng kiểu dữ liệu void. Hàm này thực hiện 3 chức năng cùng lúc, nhưng một hàm chỉ nên làm một chức năng.

Hàm không có tham số, có trả về giá trị

#include 

int getInteger();

int main() {
    int n, i, flag = 0;
    // không truyền tham số
    n = getInteger();
    for(i=2; i <= n/2; ++i) {
        if(n%i==0){
            flag = 1;
            break;
        }
    }
    if (flag == 1)
        printf("%d không phải là số nguyên tố.", n);
    else
        printf("%d là số nguyên tố.", n);
    return 0;
}

// Trả về giá trị là số nguyên được người dùng nhập
int getInteger() {
    int n;
    printf("Nhập một số nguyên dương: ");
    scanf("%d", &n);
    return n;
}

Nhận xét:

  • Hàm getInteger() nhập một số từ bàn phím và trả về giá trị đó. Còn việc kiểm tra số nguyên tố hay không, chúng ta viết trong hàm main(). Vì chúng ta muốn viết một hàm kiểm tra số nguyên tố, hàm này cần tham số là "số cần kiểm tra".

Hàm có tham số, không trả về giá trị

#include 

void checkPrimeAndDisplay(int n);

int main() {
    int n;
    printf("Nhập một số nguyên dương: ");
    scanf("%d", &n);
    // truyền n vào hàm checkPrimeAndDisplay()
    checkPrimeAndDisplay(n);
    return 0;
}

// Kiểu trả về là void nghĩa là không trả về giá trị nào
void checkPrimeAndDisplay(int n) {
    int i, flag = 0;
    for(i=2; i <= n/2; ++i) {
        if(n%i == 0){
            flag = 1;
            break;
        }
    }
    if(flag == 1)
        printf("%d không phải là số nguyên tố.",n);
    else
        printf("%d là số nguyên tố.", n);
}

Nhận xét:

  • Hàm checkPrimeAndDisplay() nhận tham số là một số cần kiểm tra, sau đó thực hiện kiểm tra và in ra kết quả.

Hàm có tham số, có trả về giá trị

#include 

int checkPrimeNumber(int n);

int main() {
    int n, flag;
    printf("Nhập một số nguyên dương: ");
    scanf("%d", &n);
    // n được truyền vào hàm checkPrimeNumber()
    // giá trị trả về được gán cho biến flag
    flag = checkPrimeNumber(n);
    if(flag == 1)
        printf("%d không phải là số nguyên tố.",n);
    else
        printf("%d là số nguyên tố.", n);
    return 0;
}

// Hàm trả về giá trị là số nguyên
int checkPrimeNumber(int n) {
    int i;
    for(i=2; i <= n/2; ++i) {
        if(n%i == 0)
            return 1;
    }
    return 0;
}

Nhận xét:

  • Hàm checkPrimeNumber() chỉ có nhiệm vụ nhận một số và kiểm tra xem số đó có phải số nguyên tố hay không.

Các hàm trong ví dụ trên được tách thành các chức năng riêng biệt và tiến hành trong cùng một chương trình. Một số cách viết hàm tốt là một hàm chỉ nên thực hiện một việc duy nhất, và hàm main nên chỉ nhận và xuất dữ liệu.

Tài liệu tham khảo

1