Bài 10.2: Bài tập thực hành hàm với tham số trong C++

Bài 10.2: Bài tập thực hành hàm với tham số trong C++
Chào mừng trở lại với series học lập trình C++ tại FullhouseDev!
Trong bài trước, chúng ta đã cùng nhau khám phá sức mạnh của hàm và đặc biệt là cách sử dụng tham số để truyền dữ liệu vào hàm. Tham số chính là điều biến hàm trở nên linh hoạt, cho phép chúng ta thực hiện cùng một thao tác trên nhiều bộ dữ liệu khác nhau mà không cần viết lại code.
Lý thuyết rất quan trọng, nhưng trong lập trình, thực hành còn quan trọng hơn gấp bội. Đây là lúc chúng ta sẽ "xắn tay áo" lên và bắt tay vào giải quyết các bài tập nhỏ để củng cố kiến thức về hàm có tham số. Hãy chuẩn bị trình biên dịch C++ của bạn và cùng bắt đầu nào!
Tại sao phải thực hành với Tham số?
Nhắc lại một chút, tham số (parameters) là những "đầu vào" mà chúng ta định nghĩa cho hàm. Khi gọi hàm, chúng ta sẽ cung cấp các đối số (arguments) tương ứng với các tham số này.
Việc thực hành giúp bạn:
- Nắm vững cú pháp khai báo và định nghĩa hàm với tham số.
- Hiểu rõ cách dữ liệu được truyền từ lúc gọi hàm đến bên trong hàm.
- Làm quen với việc sử dụng các kiểu dữ liệu khác nhau làm tham số (số nguyên, số thực, chuỗi, boolean...).
- Giải quyết các vấn đề thực tế bằng cách chia nhỏ chúng thành các hàm con.
Okay, không dài dòng nữa, hãy bắt đầu với bài tập đầu tiên!
Bài Tập 1: Hàm Cộng Hai Số
Yêu cầu: Viết một hàm nhận vào hai số nguyên và trả về tổng của chúng.
Đây là một bài tập kinh điển nhưng cực kỳ hiệu quả để làm quen với hàm có tham số và giá trị trả về.
Phân tích:
- Hàm cần nhận 2 giá trị đầu vào, cả hai đều là số nguyên. Vậy, hàm sẽ có 2 tham số kiểu
int
. - Hàm cần trả về kết quả là tổng của hai số đó. Tổng hai số nguyên cũng là số nguyên, nên kiểu trả về của hàm là
int
. - Tên hàm nên gợi nhớ chức năng của nó, ví dụ
addNumbers
.
- Hàm cần nhận 2 giá trị đầu vào, cả hai đều là số nguyên. Vậy, hàm sẽ có 2 tham số kiểu
Code minh họa:
#include <iostream> // Cần cho cout và endl
// Khai báo (prototype) hàm - Tùy chọn nhưng là practice tốt
// int addNumbers(int num1, int num2);
// Định nghĩa hàm: Nhận hai tham số int, trả về int
int addNumbers(int a, int b) {
// Bên trong hàm, 'a' và 'b' là các biến cục bộ chứa giá trị được truyền vào
int sum = a + b;
return sum; // Trả về kết quả
}
int main() {
// Gọi hàm addNumbers với các đối số cụ thể (5 và 10)
int result1 = addNumbers(5, 10);
cout << "5 + 10 = " << result1 << endl; // Output: 5 + 10 = 15
// Gọi hàm với các biến làm đối số
int number1 = 20;
int number2 = 35;
int result2 = addNumbers(number1, number2); // Truyền giá trị của number1 và number2
cout << number1 << " + " << number2 << " = " << result2 << endl; // Output: 20 + 35 = 55
// Gọi hàm trực tiếp trong câu lệnh in
cout << "100 + 200 = " << addNumbers(100, 200) << endl; // Output: 100 + 200 = 300
return 0;
}
- Giải thích:
- Chúng ta định nghĩa hàm
addNumbers
nhận hai tham sốint a
vàint b
. Khi hàm được gọi, giá trị của đối số đầu tiên sẽ được gán vào biếna
, và đối số thứ hai được gán vào biếnb
bên trong hàm. - Câu lệnh
return sum;
sẽ trả giá trị của biếnsum
(là tổng củaa
vàb
) về nơi hàm được gọi. - Trong
main
, chúng ta gọi hàm này ba lần với các đối số khác nhau: hằng số (5
,10
), biến (number1
,number2
), và thậm chí là trực tiếp trong câu lệnhcout
. Điều này cho thấy sự linh hoạt của hàm khi làm việc với tham số.
- Chúng ta định nghĩa hàm
Bài Tập 2: Hàm Tìm Số Lớn Nhất
Yêu cầu: Viết một hàm nhận vào hai số thực (kiểu double
) và trả về số lớn hơn trong hai số đó.
Bài này tương tự bài 1 nhưng sử dụng kiểu dữ liệu khác và logic so sánh.
Phân tích:
- Hàm nhận 2 giá trị đầu vào, cả hai đều là số thực. Hàm sẽ có 2 tham số kiểu
double
. - Hàm trả về số lớn hơn, đó cũng là số thực. Kiểu trả về của hàm là
double
. - Tên hàm có thể là
findMax
.
- Hàm nhận 2 giá trị đầu vào, cả hai đều là số thực. Hàm sẽ có 2 tham số kiểu
Code minh họa:
#include <iostream>
#include <algorithm> // Thư viện chứa max
// Định nghĩa hàm: Nhận hai tham số double, trả về double
double findMax(double x, double y) {
// Chúng ta có thể dùng câu lệnh if/else truyền thống:
// if (x > y) {
// return x;
// } else {
// return y;
// }
// Hoặc dùng hàm max có sẵn trong thư viện <algorithm> (tiện lợi hơn!)
return max(x, y);
}
int main() {
double value1 = 17.5;
double value2 = 12.3;
double max_value = findMax(value1, value2);
cout << "Số lớn nhất giữa " << value1 << " và " << value2 << " là: " << max_value << endl; // Output: ... 17.5
cout << "Số lớn nhất giữa 99.9 và 100.1 là: " << findMax(99.9, 100.1) << endl; // Output: ... 100.1
return 0;
}
- Giải thích:
- Hàm
findMax
làm việc với kiểudouble
, cho phép chúng ta xử lý số thập phân. - Logic so sánh (
x > y
) được sử dụng để xác định số nào lớn hơn. Hàmmax
là một cách gọn gàng hơn để thực hiện điều này, minh họa cách chúng ta có thể tận dụng các hàm có sẵn trong thư viện chuẩn của C++. - Lần nữa, chúng ta thấy cách truyền các giá trị
double
(từ biến hoặc hằng số) vào tham sốdouble
của hàm.
- Hàm
Bài Tập 3: Hàm Chào Hỏi Cá Nhân
Yêu cầu: Viết một hàm nhận vào một tên (là một chuỗi ký tự) và in ra màn hình lời chào "Xin chào, [Tên]!". Hàm này không cần trả về giá trị nào.
Bài này giới thiệu việc sử dụng kiểu dữ liệu chuỗi (string
) làm tham số và hàm không có giá trị trả về (void
).
Phân tích:
- Hàm nhận 1 giá trị đầu vào là tên, đó là một chuỗi. Tham số sẽ là kiểu
string
. - Hàm chỉ thực hiện việc in ra màn hình, không cần trả về kết quả tính toán nào. Kiểu trả về của hàm là
void
. - Tên hàm có thể là
greet
.
- Hàm nhận 1 giá trị đầu vào là tên, đó là một chuỗi. Tham số sẽ là kiểu
Code minh họa:
#include <iostream>
#include <string> // Cần include thư viện string để sử dụng string
// Định nghĩa hàm: Nhận một tham số string, không trả về gì (void)
// Sử dụng `const string&` là một practice tốt cho chuỗi lớn để tránh copy
void greet(const string& name) {
// Bên trong hàm, 'name' chứa chuỗi được truyền vào
cout << "Xin chào, " << name << "!" << endl;
// Hàm void không cần câu lệnh return (hoặc chỉ return; trống)
}
int main() {
string userName = "FullhouseDev Reader";
greet(userName); // Gọi hàm với biến kiểu string
greet("Bạn lập trình viên"); // Gọi hàm với một chuỗi literal (hằng chuỗi)
return 0;
}
- Giải thích:
- Hàm
greet
có kiểu trả về làvoid
, cho biết nó không trả về bất kỳ giá trị nào. Chức năng của nó là thực hiện một hành động (in ra màn hình). - Tham số
const string& name
nhận một chuỗi. Việc sử dụngconst&
ở đây là practice tốt trong C++ khi truyền các đối tượng lớn (như chuỗi) để tránh việc tạo ra một bản sao không cần thiết, giúp chương trình chạy hiệu quả hơn.const
đảm bảo rằng hàm không thay đổi chuỗi gốc. - Chúng ta gọi hàm
greet
với cả biến kiểustring
và một chuỗi literal.
- Hàm
Bài Tập 4: Hàm Tính Diện Tích Hình Chữ Nhật
Yêu cầu: Viết một hàm nhận vào chiều dài và chiều rộng của hình chữ nhật (kiểu double
) và trả về diện tích của nó. Cần xử lý trường hợp chiều dài hoặc chiều rộng không hợp lệ (âm hoặc bằng không).
Bài này kết hợp nhiều tham số và một chút xử lý lỗi đơn giản.
Phân tích:
- Hàm nhận 2 giá trị đầu vào: chiều dài và chiều rộng, cả hai đều là số thực. Hàm sẽ có 2 tham số kiểu
double
. - Hàm trả về diện tích, là tích của hai số thực, nên cũng là số thực. Kiểu trả về là
double
. - Cần kiểm tra điều kiện
length > 0
vàwidth > 0
. Nếu không, có thể in thông báo lỗi và trả về một giá trị đặc biệt (ví dụ 0 hoặc -1) để báo hiệu lỗi, hoặc ném một ngoại lệ (khái niệm nâng cao hơn). Ở đây, chúng ta sẽ in lỗi và trả về 0. - Tên hàm có thể là
calculateRectangleArea
.
- Hàm nhận 2 giá trị đầu vào: chiều dài và chiều rộng, cả hai đều là số thực. Hàm sẽ có 2 tham số kiểu
Code minh họa:
#include <iostream>
#include <limits> // Có thể dùng cho các giá trị đặc biệt, nhưng ở đây dùng 0.0
// Định nghĩa hàm: Nhận hai tham số double, trả về double
double calculateRectangleArea(double length, double width) {
// Kiểm tra điều kiện đầu vào
if (length <= 0 || width <= 0) {
// Sử dụng cerr để in thông báo lỗi ra luồng lỗi chuẩn
cerr << "Lỗi: Chiều dài và chiều rộng phải là số dương!" << endl;
return 0.0; // Trả về 0.0 hoặc một giá trị đặc biệt để báo hiệu lỗi
}
// Nếu đầu vào hợp lệ, tính và trả về diện tích
return length * width;
}
int main() {
double rect_length = 12.5;
double rect_width = 8.0;
double area1 = calculateRectangleArea(rect_length, rect_width);
cout << "Diện tích hình chữ nhật (" << rect_length << "x" << rect_width << ") là: " << area1 << endl; // Output: ... 100
double rect_length_bad = -5.0;
double rect_width_bad = 10.0;
double area2 = calculateRectangleArea(rect_length_bad, rect_width_bad); // Gọi hàm với đầu vào không hợp lệ
// Sẽ in ra thông báo lỗi từ bên trong hàm trước câu lệnh này
cout << "Diện tích hình chữ nhật (" << rect_length_bad << "x" << rect_width_bad << ") là: " << area2 << endl; // Output: ... 0
return 0;
}
- Giải thích:
- Hàm
calculateRectangleArea
nhận hai tham sốdouble length
vàdouble width
. - Câu lệnh
if (length <= 0 || width <= 0)
kiểm tra xem có bất kỳ tham số nào không hợp lệ không. Dấu||
(OR) nghĩa là nếu một trong hai điều kiện đúng thì khốiif
sẽ được thực thi. - Nếu điều kiện đúng, hàm in thông báo lỗi ra
cerr
(thay vìcout
thường dùng cho output bình thường) và trả về0.0
. Đây là một cách đơn giản để báo hiệu rằng tính toán không thành công do đầu vào sai. - Nếu cả hai tham số đều dương, hàm tính toán và trả về tích của chúng.
- Trong
main
, chúng ta thử cả hai trường hợp: đầu vào hợp lệ và không hợp lệ để thấy cách hàm xử lý.
- Hàm
Lời Khuyên Khi Thực Hành
- Tự gõ lại code: Đừng chỉ copy-paste! Tự gõ lại các ví dụ giúp bạn nhớ cú pháp tốt hơn và dễ dàng phát hiện lỗi của chính mình.
- Thay đổi và thử nghiệm: Hãy thử thay đổi các giá trị đối số, thay đổi kiểu dữ liệu (nếu có thể), hoặc thêm bớt logic vào các hàm ví dụ. Điều này giúp bạn hiểu sâu hơn về cách mọi thứ hoạt động.
- Giải các bài tập khác: Tìm kiếm các bài tập lập trình C++ cơ bản trên mạng và thử giải chúng bằng cách sử dụng hàm có tham số. Bắt đầu từ những bài đơn giản nhất.
- Chia nhỏ vấn đề: Khi gặp một bài toán lớn, hãy tập thói quen chia nó thành các công việc nhỏ hơn mà mỗi công việc có thể được thực hiện bởi một hàm riêng biệt với các tham số phù hợp.
Comments