Menu
CoddyTech

Ví dụ kinh điển: hoán đổi

Thuộc phần Logic và luồng điều khiển trong hành trình C của Coddy. Bài học 28 trên 63.

hàm swap là một trong những ví dụ nổi tiếng nhất cho thấy vì sao con trỏ rất cần thiết trong lập trình C. Mục tiêu rất đơn giản: viết một hàm (function) để hoán đổi giá trị của hai biến. Tuy nhiên, nhiệm vụ tưởng chừng đơn giản này cho thấy một hạn chế cơ bản của cách truyền đối số theo giá trị.

Hãy xem điều gì xảy ra nếu bạn thử hoán đổi hai biến bằng cách truyền giá trị thông thường:

void badSwap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    // Thao tác này chỉ hoán đổi các bản sao, không hoán đổi các biến (variables) ban đầu!
}

Cách làm này không hiệu quả vì hàm chỉ nhận bản sao của các giá trị. Các biến ban đầu trong hàm gọi nó vẫn không thay đổi.

Lời giải yêu cầu truyền con trỏ đến các biến thay thế:

void swap(int *a, int *b) {
    int temp = *a;  // Lưu giá trị tại địa chỉ a
    *a = *b;        // Gán giá trị tại địa chỉ b cho địa chỉ a
    *b = temp;      // Gán giá trị đã lưu cho địa chỉ b
}

Bằng cách truyền địa chỉ của các biến và dùng toán tử giải tham chiếu, hàm có thể trực tiếp thay đổi giá trị của các biến ban đầu. Điều này khiến hàm hoán đổi trở thành ví dụ hoàn hảo để minh họa khi nào và vì sao bạn cần con trỏ để thực hiện những việc mà cách truyền giá trị không thể xử lý.

challenge icon

Thử thách

Dễ

Viết chương trình C triển khai và minh họa hàm hoán đổi kinh điển bằng con trỏ. Chương trình của bạn cần:

  1. Tạo hàm có tên swap, nhận hai con trỏ đến số nguyên làm tham số
  2. Bên trong hàm swap, hoán đổi các giá trị tại địa chỉ bộ nhớ mà hai con trỏ trỏ đến bằng cách sử dụng một biến tạm
  3. Trong hàm main, đọc hai số nguyên từ đầu vào của người dùng
  4. In các giá trị ban đầu theo định dạng: Before swap: a = [value], b = [value]
  5. Gọi hàm swap và truyền địa chỉ của cả hai biến bằng toán tử lấy địa chỉ
  6. Sau khi gọi hàm, in các giá trị đã hoán đổi theo định dạng: After swap: a = [value], b = [value]

Đầu ra cần cho thấy hàm hoán đổi thành công các giá trị của những biến ban đầu:

Before swap: a = [first_input], b = [second_input]
After swap: a = [second_input], b = [first_input]

Thử thách này cho thấy vì sao con trỏ rất cần thiết cho thao tác hoán đổi: hàm phải truy cập các vị trí bộ nhớ của những biến ban đầu để hoán đổi vĩnh viễn các giá trị của chúng, điều mà cách truyền giá trị không thể làm được.

Tự làm thử

#include <stdio.h>

// TODO: Viết hàm (function) hoán đổi tại đây

int main() {
    int a, b;
    
    // Đọc đầu vào
    scanf("%d", &a);
    scanf("%d", &b);
    
    // In ra các giá trị ban đầu
    printf("Before swap: a = %d, b = %d\n", a, b);
    
    // TODO: Gọi hàm hoán đổi tại đây
    
    // In ra các giá trị sau khi hoán đổi
    printf("After swap: a = %d, b = %d\n", a, b);
    
    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Logic và luồng điều khiển

Tự luyện tập: Trình biên dịch C online