Skip to content

🔧 Hàm cơ bản trong C++

📖 Giới thiệu

Hàm (function) là một khối code có tên được thiết kế để thực hiện một nhiệm vụ cụ thể. Hàm giúp chia nhỏ chương trình lớn thành những phần nhỏ hơn, dễ quản lý và có thể tái sử dụng.

Trong cuộc sống, chúng ta thường phân chia công việc thành các bước nhỏ: "nấu cơm", "rửa bát", "quét nhà". Lập trình cũng vậy - thay vì viết tất cả code trong hàm main(), chúng ta tạo các hàm riêng cho từng chức năng.

Việc sử dụng hàm không chỉ giúp code gọn gàng mà còn dễ đọc, dễ debug, và dễ bảo trì. Một lần viết hàm, có thể sử dụng nhiều lần ở nhiều nơi khác nhau.

🔧 Cú pháp

Cấu trúc hàm cơ bản

cpp
// Khai báo hàm (function declaration/prototype)
kiểu_trả_về tên_hàm(danh_sách_tham_số);

// Định nghĩa hàm (function definition)
kiểu_trả_về tên_hàm(danh_sách_tham_số) {
    // Thân hàm
    // Code thực thi
    return giá_trị;  // Nếu hàm có trả về
}

// Gọi hàm (function call)
tên_hàm(danh_sách_đối_số);

Ví dụ đơn giản để bắt đầu

Trước khi tìm hiểu chi tiết, hãy xem ví dụ đơn giản nhất về hàm:

cpp
#include <iostream>
using namespace std;

// Hàm đơn giản - chào hỏi
void chaoHoi() {
    cout << "Xin chào!" << endl;
}

// Hàm đơn giản - cộng hai số
int cong(int a, int b) {
    return a + b;
}

int main() {
    // Gọi hàm
    chaoHoi();
    
    int ketQua = cong(3, 5);
    cout << "3 + 5 = " << ketQua << endl;
    
    return 0;
}

Kết quả:

Xin chào!
3 + 5 = 8

Ví dụ cụ thể

cpp
#include <iostream>
using namespace std;

// Khai báo hàm
int add(int a, int b);
void greet(string name);
double calculateArea(double radius);

// Định nghĩa hàm
int add(int a, int b) {
    return a + b;
}

void greet(string name) {
    cout << "Xin chào, " << name << "!" << endl;
}

double calculateArea(double radius) {
    const double PI = 3.14159;
    return PI * radius * radius;
}

int main() {
    // Gọi hàm
    int result = add(5, 3);        // result = 8
    greet("Nam");                  // In: Xin chào, Nam!
    double area = calculateArea(5); // area = 78.5397
    
    return 0;
}

Các loại hàm

cpp
// Hàm không tham số, không trả về
void sayHello() {
    cout << "Hello World!" << endl;
}

// Hàm có tham số, không trả về
void printNumber(int n) {
    cout << "Số là: " << n << endl;
}

// Hàm không tham số, có trả về
int getCurrentYear() {
    return 2024;
}

// Hàm có tham số, có trả về
double power(double base, int exponent) {
    double result = 1;
    for (int i = 0; i < exponent; i++) {
        result *= base;
    }
    return result;
}

🔬 Phân tích & Giải thích chi tiết

Tại sao cần sử dụng hàm?

1. Tái sử dụng code (Reusability)

cpp
// Thay vì viết lặp lại
cout << "Điểm của bạn: " << score1 << (score1 >= 5 ? " - Đậu" : " - Trượt") << endl;
cout << "Điểm của bạn: " << score2 << (score2 >= 5 ? " - Đậu" : " - Trượt") << endl;

// Viết hàm một lần, dùng nhiều lần
void printResult(double score) {
    cout << "Điểm của bạn: " << score << (score >= 5 ? " - Đậu" : " - Trượt") << endl;
}

2. Modularity (Tính mô-đun)

cpp
int main() {
    // Chương trình chính rõ ràng, dễ hiểu
    displayMenu();
    int choice = getUserChoice();
    processChoice(choice);
    return 0;
}

3. Easier Debugging

  • Lỗi trong hàm cụ thể → dễ tìm và sửa
  • Test từng hàm riêng biệt
  • Thay đổi logic chỉ ở một nơi

4. Team Work

  • Mỗi người làm một vài hàm
  • Interface rõ ràng (tham số, return type)
  • Dễ phân chia công việc

Function Signature và Overloading

cpp
// Function signature bao gồm: tên hàm + danh sách tham số
int add(int a, int b);           // Signature: add(int, int)
double add(double a, double b);  // Signature: add(double, double)
int add(int a, int b, int c);    // Signature: add(int, int, int)

// Đây là function overloading - cùng tên nhưng khác signature

Local vs Global Scope trong hàm

cpp
int globalVar = 100;  // Biến toàn cục

void function1() {
    int localVar = 10;     // Biến cục bộ
    cout << globalVar;     // OK - truy cập được global
    cout << localVar;      // OK - trong cùng scope
}

void function2() {
    cout << globalVar;     // OK - truy cập được global
    // cout << localVar;   // LỖI - localVar không tồn tại ở đây
}

Stack và Function Call

Khi gọi hàm, một "stack frame" mới được tạo:

Stack Memory:
+-------------------+
| main()            |
| - int x = 5       |
+-------------------+
| add(int a, int b) |
| - a = 5           |
| - b = 3           |
| - return 8        |
+-------------------+

💻 Ví dụ minh họa

Chương trình đơn giản với hàm cơ bản

cpp
#include <iostream>
using namespace std;

// Hàm chào hỏi
void sayHello() {
    cout << "Xin chào! Chào mừng bạn đến với C++!" << endl;
}

// Hàm tính tổng hai số
int add(int a, int b) {
    return a + b;
}

// Hàm tính bình phương
int square(int x) {
    return x * x;
}

// Hàm kiểm tra số chẵn
bool isEven(int number) {
    return number % 2 == 0;
}

// Hàm in bảng cửu chương
void printMultiplicationTable(int n) {
    cout << "Bảng cửu chương " << n << ":" << endl;
    for (int i = 1; i <= 10; i++) {
        cout << n << " x " << i << " = " << (n * i) << endl;
    }
}

int main() {
    // Gọi hàm chào hỏi
    sayHello();
    
    // Sử dụng hàm tính tổng
    int num1 = 5, num2 = 3;
    int sum = add(num1, num2);
    cout << "\n" << num1 << " + " << num2 << " = " << sum << endl;
    
    // Sử dụng hàm tính bình phương
    int number = 4;
    cout << "Bình phương của " << number << " = " << square(number) << endl;
    
    // Kiểm tra số chẵn lẻ
    int testNum = 7;
    if (isEven(testNum)) {
        cout << testNum << " là số chẵn" << endl;
    } else {
        cout << testNum << " là số lẻ" << endl;
    }
    
    // In bảng cửu chương
    cout << endl;
    printMultiplicationTable(5);
    
    return 0;
}

Kết quả chạy:

Xin chào! Chào mừng bạn đến với C++!

5 + 3 = 8
Bình phương của 4 = 16
7 là số lẻ

Bảng cửu chương 5:
5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50

Chương trình tính toán hình học

cpp
#include <iostream>
#include <cmath>
using namespace std;

// Hàm tính diện tích hình tròn
double circleArea(double radius) {
    const double PI = 3.14159265359;
    return PI * radius * radius;
}

// Hàm tính chu vi hình tròn
double circlePerimeter(double radius) {
    const double PI = 3.14159265359;
    return 2 * PI * radius;
}

// Hàm tính diện tích hình chữ nhật
double rectangleArea(double length, double width) {
    return length * width;
}

// Hàm tính chu vi hình chữ nhật
double rectanglePerimeter(double length, double width) {
    return 2 * (length + width);
}

// Hàm tính diện tích tam giác (công thức Heron)
double triangleArea(double a, double b, double c) {
    // Kiểm tra tam giác hợp lệ
    if (a + b <= c || a + c <= b || b + c <= a) {
        return -1;  // Tam giác không hợp lệ
    }
    
    double s = (a + b + c) / 2;  // Nửa chu vi
    return sqrt(s * (s - a) * (s - b) * (s - c));
}

// Hàm hiển thị menu
void displayMenu() {
    cout << "\n=== CHƯƠNG TRÌNH TÍNH TOÁN HÌNH HỌC ===" << endl;
    cout << "1. Hình tròn" << endl;
    cout << "2. Hình chữ nhật" << endl;
    cout << "3. Tam giác" << endl;
    cout << "4. Thoát" << endl;
    cout << "Chọn hình (1-4): ";
}

// Hàm xử lý hình tròn
void processCircle() {
    double radius;
    cout << "Nhập bán kính: ";
    cin >> radius;
    
    if (radius <= 0) {
        cout << "Lỗi: Bán kính phải > 0!" << endl;
        return;
    }
    
    cout << "Diện tích: " << circleArea(radius) << endl;
    cout << "Chu vi: " << circlePerimeter(radius) << endl;
}

// Hàm xử lý hình chữ nhật
void processRectangle() {
    double length, width;
    cout << "Nhập chiều dài: ";
    cin >> length;
    cout << "Nhập chiều rộng: ";
    cin >> width;
    
    if (length <= 0 || width <= 0) {
        cout << "Lỗi: Chiều dài và rộng phải > 0!" << endl;
        return;
    }
    
    cout << "Diện tích: " << rectangleArea(length, width) << endl;
    cout << "Chu vi: " << rectanglePerimeter(length, width) << endl;
}

// Hàm xử lý tam giác
void processTriangle() {
    double a, b, c;
    cout << "Nhập 3 cạnh tam giác:" << endl;
    cout << "Cạnh a: ";
    cin >> a;
    cout << "Cạnh b: ";
    cin >> b;
    cout << "Cạnh c: ";
    cin >> c;
    
    if (a <= 0 || b <= 0 || c <= 0) {
        cout << "Lỗi: Độ dài cạnh phải > 0!" << endl;
        return;
    }
    
    double area = triangleArea(a, b, c);
    if (area == -1) {
        cout << "Lỗi: Không phải tam giác hợp lệ!" << endl;
    } else {
        cout << "Diện tích: " << area << endl;
        cout << "Chu vi: " << (a + b + c) << endl;
    }
}

int main() {
    int choice;
    
    do {
        displayMenu();
        cin >> choice;
        
        switch (choice) {
            case 1:
                processCircle();
                break;
            case 2:
                processRectangle();
                break;
            case 3:
                processTriangle();
                break;
            case 4:
                cout << "Tạm biệt!" << endl;
                break;
            default:
                cout << "Lựa chọn không hợp lệ!" << endl;
        }
        
    } while (choice != 4);
    
    return 0;
}

Chương trình quản lý mảng với hàm

cpp
#include <iostream>
using namespace std;

// Hàm nhập mảng
void inputArray(int arr[], int size) {
    cout << "Nhập " << size << " phần tử:" << endl;
    for (int i = 0; i < size; i++) {
        cout << "Phần tử " << (i + 1) << ": ";
        cin >> arr[i];
    }
}

// Hàm in mảng
void printArray(int arr[], int size, string title = "Mảng") {
    cout << title << ": ";
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// Hàm tìm giá trị lớn nhất
int findMax(int arr[], int size) {
    int max = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

// Hàm tìm giá trị nhỏ nhất
int findMin(int arr[], int size) {
    int min = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    return min;
}

// Hàm tính tổng
int calculateSum(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// Hàm tính trung bình
double calculateAverage(int arr[], int size) {
    return (double)calculateSum(arr, size) / size;
}

// Hàm tìm kiếm
int linearSearch(int arr[], int size, int target) {
    for (int i = 0; i < size; i++) {
        if (arr[i] == target) {
            return i;
        }
    }
    return -1;
}

// Hàm sắp xếp (Bubble Sort)
void bubbleSort(int arr[], int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // Swap
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

// Hàm hiển thị thống kê
void displayStatistics(int arr[], int size) {
    cout << "\n=== THỐNG KÊ MẢNG ===" << endl;
    cout << "Số phần tử: " << size << endl;
    cout << "Giá trị lớn nhất: " << findMax(arr, size) << endl;
    cout << "Giá trị nhỏ nhất: " << findMin(arr, size) << endl;
    cout << "Tổng: " << calculateSum(arr, size) << endl;
    cout << "Trung bình: " << calculateAverage(arr, size) << endl;
}

int main() {
    const int MAX_SIZE = 100;
    int arr[MAX_SIZE];
    int size;
    
    cout << "=== CHƯƠNG TRÌNH QUẢN LÝ MẢNG ===" << endl;
    cout << "Nhập số phần tử (tối đa " << MAX_SIZE << "): ";
    cin >> size;
    
    if (size <= 0 || size > MAX_SIZE) {
        cout << "Kích thước không hợp lệ!" << endl;
        return 1;
    }
    
    // Nhập mảng
    inputArray(arr, size);
    
    // Hiển thị mảng ban đầu
    printArray(arr, size, "Mảng ban đầu");
    
    // Hiển thị thống kê
    displayStatistics(arr, size);
    
    // Tìm kiếm
    int target;
    cout << "\nNhập giá trị cần tìm: ";
    cin >> target;
    
    int index = linearSearch(arr, size, target);
    if (index != -1) {
        cout << "Tìm thấy " << target << " tại vị trí " << index << endl;
    } else {
        cout << "Không tìm thấy " << target << " trong mảng" << endl;
    }
    
    // Sắp xếp
    cout << "\nSắp xếp mảng..." << endl;
    bubbleSort(arr, size);
    printArray(arr, size, "Mảng sau khi sắp xếp");
    
    return 0;
}

Chương trình game với hàm

cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

// Hàm khởi tạo game
void initializeGame() {
    srand(time(0));  // Khởi tạo random seed
    cout << "=== GAME ĐOÁN SỐ ===" << endl;
    cout << "Tôi sẽ nghĩ ra một số từ 1 đến 100." << endl;
    cout << "Nhiệm vụ của bạn là đoán số đó!" << endl;
}

// Hàm tạo số ngẫu nhiên
int generateRandomNumber(int min, int max) {
    return rand() % (max - min + 1) + min;
}

// Hàm nhập guess của người chơi
int getPlayerGuess() {
    int guess;
    cout << "Nhập số bạn đoán: ";
    cin >> guess;
    return guess;
}

// Hàm đưa ra gợi ý
void giveHint(int guess, int secret) {
    if (guess < secret) {
        cout << "Số bạn đoán NHỎ HƠN số bí mật!" << endl;
    } else if (guess > secret) {
        cout << "Số bạn đoán LỚN HƠN số bí mật!" << endl;
    } else {
        cout << "🎉 CHÚC MỪNG! Bạn đã đoán đúng!" << endl;
    }
}

// Hàm đánh giá hiệu suất
void evaluatePerformance(int attempts) {
    cout << "\nBạn đã đoán trong " << attempts << " lần!" << endl;
    
    if (attempts <= 3) {
        cout << "⭐⭐⭐ Xuất sắc! Bạn là thiên tài!" << endl;
    } else if (attempts <= 5) {
        cout << "⭐⭐ Tốt lắm! Bạn rất thông minh!" << endl;
    } else if (attempts <= 7) {
        cout << "⭐ Không tệ! Cố gắng thêm!" << endl;
    } else {
        cout << "Cần luyện tập thêm!" << endl;
    }
}

// Hàm hỏi chơi lại
bool askPlayAgain() {
    char choice;
    cout << "\nBạn có muốn chơi lại không? (y/n): ";
    cin >> choice;
    return (choice == 'y' || choice == 'Y');
}

// Hàm chơi một round
void playOneRound() {
    int secretNumber = generateRandomNumber(1, 100);
    int attempts = 0;
    int maxAttempts = 7;
    bool hasWon = false;
    
    cout << "\nTôi đã nghĩ ra một số. Bạn có " << maxAttempts << " lần đoán!" << endl;
    
    while (attempts < maxAttempts && !hasWon) {
        attempts++;
        cout << "\nLần đoán thứ " << attempts << "/" << maxAttempts << endl;
        
        int guess = getPlayerGuess();
        
        if (guess == secretNumber) {
            hasWon = true;
            giveHint(guess, secretNumber);
            evaluatePerformance(attempts);
        } else {
            giveHint(guess, secretNumber);
            
            if (attempts < maxAttempts) {
                cout << "Bạn còn " << (maxAttempts - attempts) << " lần đoán!" << endl;
            }
        }
    }
    
    if (!hasWon) {
        cout << "\n😞 Hết lượt rồi! Số bí mật là: " << secretNumber << endl;
    }
}

int main() {
    initializeGame();
    
    do {
        playOneRound();
    } while (askPlayAgain());
    
    cout << "\nCảm ơn bạn đã chơi! Tạm biệt!" << endl;
    
    return 0;
}

🏋️ Thực hành

Bài tập 1: Hàm toán học

Viết các hàm:

  • int factorial(int n) - Tính giai thừa
  • bool isPrime(int n) - Kiểm tra số nguyên tố
  • int gcd(int a, int b) - Tìm ước chung lớn nhất
  • double power(double base, int exp) - Tính lũy thừa

Bài tập 2: Hàm xử lý chuỗi

Viết các hàm:

  • int stringLength(string s) - Đếm độ dài chuỗi
  • string reverseString(string s) - Đảo ngược chuỗi
  • bool isPalindrome(string s) - Kiểm tra palindrome
  • int countWords(string s) - Đếm số từ

Bài tập 3: Hàm menu

Tạo chương trình menu calculator với các hàm:

  • void displayMenu()
  • int getChoice()
  • double add(double a, double b)
  • double subtract(double a, double b)
  • double multiply(double a, double b)
  • double divide(double a, double b)

Bài tập 4: Hàm quản lý sinh viên

Viết hàm để:

  • Nhập thông tin n sinh viên
  • Tìm sinh viên có điểm cao nhất
  • Tính điểm trung bình của lớp
  • Liệt kê sinh viên đậu/trượt

Lời giải chi tiết

Bài tập 1:

cpp
#include <iostream>
using namespace std;

int factorial(int n) {
    if (n < 0) return -1;  // Invalid
    if (n <= 1) return 1;
    
    int result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

bool isPrime(int n) {
    if (n < 2) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) return false;
    }
    return true;
}

int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

double power(double base, int exp) {
    if (exp == 0) return 1;
    if (exp < 0) return 1.0 / power(base, -exp);
    
    double result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

int main() {
    cout << "5! = " << factorial(5) << endl;
    cout << "17 is prime: " << isPrime(17) << endl;
    cout << "GCD(48, 18) = " << gcd(48, 18) << endl;
    cout << "2^10 = " << power(2, 10) << endl;
    
    return 0;
}

📋 Tóm tắt

🎯 Những gì đã học

  • Cấu trúc hàm: Khai báo, định nghĩa, gọi hàm
  • Tham số và return: Truyền dữ liệu vào và nhận kết quả
  • Scope: Phạm vi biến local/global trong hàm
  • Function overloading: Cùng tên, khác signature
  • Modular programming: Chia nhỏ chương trình thành các hàm

🔧 Best Practices

  • Đặt tên hàm có ý nghĩa, mô tả chức năng
  • Một hàm chỉ nên làm một việc (Single Responsibility)
  • Sử dụng const cho tham số không thay đổi
  • Khai báo hàm trước khi sử dụng
  • Viết comment mô tả hàm phức tạp

🚀 Chuẩn bị cho bước tiếp theo

Bài học tiếp theo sẽ tìm hiểu về tham số hàm. Đảm bảo bạn đã:

  • [x] Hiểu cấu trúc và cách viết hàm
  • [x] Phân biệt được khai báo và định nghĩa hàm
  • [x] Sử dụng được return để trả về giá trị
  • [x] Chia nhỏ chương trình thành các hàm hợp lý

💡 Lời khuyên

"Hàm giống như công cụ trong hộp đồ nghề - mỗi công cụ có một mục đích riêng. Hãy tạo những 'công cụ' tốt để xây dựng 'sản phẩm' hoàn hảo!"


Chuyển sang: Tham số hàm để học về pass by value, pass by reference và các cách truyền dữ liệu!

Khóa học C++ miễn phí