Bài 10.1: Bài tập thực hành hàm cơ bản trong C++

Bài 10.1: Hàm cơ bản trong C++
Chào mừng trở lại với series blog về C++! Hôm nay chúng ta sẽ cùng nhau đi sâu vào một trong những khái niệm cốt lõi và quan trọng nhất trong lập trình: hàm (functions). Hàm giống như những "cỗ máy" nhỏ thực hiện một công việc cụ thể, giúp code của chúng ta gọn gàng, dễ đọc và dễ tái sử dụng.
Trong bài này, chúng ta sẽ không chỉ tìm hiểu về cấu trúc của hàm mà còn thực hành ngay với những ví dụ thật đơn giản, giúp bạn làm quen với việc định nghĩa và gọi hàm trong C++.
Tại sao cần dùng Hàm?
Hãy tưởng tượng bạn cần thực hiện một công việc giống nhau ở nhiều vị trí khác nhau trong chương trình, ví dụ như tính diện tích hình tròn hay in ra một thông báo đặc biệt. Nếu không có hàm, bạn sẽ phải viết đi viết lại cùng một đoạn code. Điều này rất tốn thời gian, dễ gây lỗi và khó bảo trì.
Hàm ra đời để giải quyết vấn đề này:
- Tái sử dụng: Viết code một lần, gọi dùng ở nhiều nơi.
- Module hóa: Chia chương trình lớn thành các phần nhỏ hơn, độc lập, dễ quản lý.
- Dễ đọc: Code được chia thành các hàm với tên gọi ý nghĩa giúp chương trình dễ hiểu hơn.
- Dễ sửa lỗi: Khi có lỗi, bạn có thể khoanh vùng tìm lỗi trong từng hàm cụ thể.
Cấu trúc cơ bản của một Hàm trong C++
Một hàm trong C++ có cấu trúc như sau:
kieu_tra_ve ten_ham(danh_sach_tham_so) {
// Thân hàm (Function Body)
// Các câu lệnh thực hiện công việc của hàm
// Nếu kieu_tra_ve KHÔNG phải là void, cần có lệnh return
// return gia_tri_tra_ve;
}
- kieu_tra_ve: Kiểu dữ liệu của giá trị mà hàm sẽ trả về sau khi thực hiện xong (ví dụ:
int
,double
,string
,bool
). Nếu hàm không trả về giá trị nào, chúng ta dùng từ khóavoid
. - ten_ham: Tên bạn đặt cho hàm, nên tuân thủ quy tắc đặt tên biến và thể hiện rõ chức năng của hàm.
- danh_sach_tham_so: (Tùy chọn) Danh sách các biến mà hàm cần nhận để thực hiện công việc của nó. Mỗi tham số gồm kiểu dữ liệu và tên biến, cách nhau bởi dấu phẩy (ví dụ:
int a, double b
). Nếu hàm không nhận tham số nào, danh sách này để trống()
. - Thân hàm: Khối lệnh nằm trong cặp dấu ngoặc nhọn
{}
. Đây là nơi chứa logic thực hiện công việc của hàm. - return: (Nếu kiểu trả về không phải là
void
) Lệnh này dùng để kết thúc hàm và trả về một giá trị có kiểu dữ liệu giống vớikieu_tra_ve
.
Thực hành 1: Hàm đơn giản nhất (Không tham số, không trả về)
Đây là loại hàm chỉ thực hiện một hành động nào đó mà không cần dữ liệu đầu vào và không trả lại kết quả.
#include <iostream>
using namespace std;
void say_hello() {
cout << "Xin chao tu ham say_hello!" << endl;
}
int main() {
say_hello();
say_hello();
say_hello();
return 0;
}
Xin chao tu ham say_hello!
Xin chao tu ham say_hello!
Xin chao tu ham say_hello!
Giải thích:
- Hàm
say_hello
cóvoid
là kiểu trả về, tức là nó không trả về bất kỳ giá trị nào. - Nó không có tham số nào trong dấu ngoặc đơn
()
. - Thân hàm chỉ chứa một lệnh in ra màn hình.
- Trong hàm
main
, chúng ta gọi hàmsay_hello()
bằng cách viết tên hàm theo sau là dấu ngoặc()
và kết thúc bằng dấu;
. Mỗi lần gọi, code trong thân hàmsay_hello
sẽ được thực thi.
Thực hành 2: Hàm có tham số (Nhận dữ liệu đầu vào)
Hàm có thể nhận dữ liệu từ bên ngoài để thực hiện công việc của mình. Dữ liệu này được truyền vào qua các tham số.
#include <iostream>
#include <string>
using namespace std;
void print_message_n_times(string s, int n) {
for (int i = 0; i < n; ++i) {
cout << s << endl;
}
}
int main() {
print_message_n_times("Hello, C++!", 3);
print_message_n_times("Day la bai tap ve ham.", 2);
return 0;
}
Hello, C++!
Hello, C++!
Hello, C++!
Day la bai tap ve ham.
Day la bai tap ve ham.
Giải thích:
- Hàm
print_message_n_times
nhận hai tham số:string text
vàint n
. - Kiểu trả về vẫn là
void
vì hàm này chỉ thực hiện hành động in ấn chứ không trả lại giá trị nào. - Khi gọi hàm trong
main
, chúng ta truyền vào các đối số (arguments) là"Hello, C++!"
và3
, hoặc"Day la bai tap ve ham."
và2
. Các đối số này sẽ được gán cho các tham số tương ứngtext
vàn
bên trong hàm. - Thân hàm sử dụng vòng lặp
for
để in chuỗitext
ran
lần.
Thực hành 3: Hàm có trả về giá trị
Hàm có thể tính toán hoặc xử lý dữ liệu và trả lại một kết quả để chúng ta sử dụng tiếp trong phần còn lại của chương trình.
#include <iostream>
using namespace std;
int tong(int a, int b) {
return a + b;
}
double dtHinhTron(double r) {
const double PI = 3.14159;
return PI * r * r;
}
int main() {
int n1 = 10;
int n2 = 25;
int ketQua = tong(n1, n2);
cout << "Tong cua " << n1 << " va " << n2 << " la: " << ketQua << endl;
cout << "Tong cua 50 va 70 la: " << tong(50, 70) << endl;
double r = 5.0;
double dt = dtHinhTron(r);
cout << "Dien tich hinh tron ban kinh " << r << " la: " << dt << endl;
return 0;
}
Tong cua 10 va 25 la: 35
Tong cua 50 va 70 la: 120
Dien tich hinh tron ban kinh 5 la: 78.53975
Giải thích:
- Hàm
add_numbers
có kiểu trả về làint
. Nó nhận hai tham sốint a, int b
. - Câu lệnh
return sum;
(hoặcreturn a + b;
) tính toán tổng và "đưa" giá trị tổng đó ra ngoài. - Hàm
calculate_area_circle
có kiểu trả về làdouble
, nhận tham sốdouble radius
và trả về kết quả tính toán kiểudouble
. - Trong hàm
main
, chúng ta gọi các hàm này và gán giá trị trả về của chúng cho các biến cùng kiểu (result_sum
,area
). Chúng ta cũng có thể sử dụng trực tiếp giá trị trả về của hàm trong biểu thức hoặc câu lệnh in.
Thực hành 4: Nguyên mẫu hàm (Function Prototype)
Đôi khi, bạn muốn gọi một hàm trước khi định nghĩa chi tiết nó (ví dụ: định nghĩa tất cả các hàm sau hàm main
). Lúc này, bạn cần khai báo nguyên mẫu hàm để trình biên dịch biết về sự tồn tại của hàm đó.
#include <iostream>
using namespace std;
int tich(int x, int y);
int main() {
int a = 8;
int b = 9;
int kq = tich(a, b);
cout << "Tich cua " << a << " va " << b << " la: " << kq << endl;
return 0;
}
int tich(int x, int y) {
return x * y;
}
Tich cua 8 va 9 la: 72
Giải thích:
- Dòng
int multiply(int x, int y);
là nguyên mẫu hàm. Nó chỉ bao gồm kiểu trả về (int
), tên hàm (multiply
) và danh sách kiểu tham số (int, int
), kết thúc bằng dấu;
. Tên biến trong ngoặc(x, y)
là tùy chọn trong nguyên mẫu, nhưng thường được thêm vào để dễ đọc. - Nguyên mẫu hàm này nằm trước hàm
main
, báo cho trình biên dịch biết rằng hàmmultiply
tồn tại và sẽ được định nghĩa ở đâu đó sau này. - Điều này cho phép chúng ta gọi
multiply(num_a, num_b)
bên trongmain
mà không gặp lỗi "hàm chưa được khai báo". - Phần định nghĩa chi tiết của hàm
multiply
nằm sau hàmmain
và chứa toàn bộ logic thực hiện công việc.
Các bài tập thực hành nhỏ
Hãy thử tự viết các hàm cho các công việc sau để luyện tập:
- Viết hàm
is_positive
nhận một số nguyên, trả vềtrue
nếu số đó dương, ngược lại trả vềfalse
. - Viết hàm
get_smaller
nhận hai số double, trả về số nhỏ hơn trong hai số đó. - Viết hàm
print_greeting
nhận một chuỗi tên và in ra lời chào "Xin chào, [Tên]!".
Comments