Bài 1.5: Bài tập thực hành làm quen với C++

Bài 1.5: Bài tập thực hành làm quen với C++
Chào mừng quay trở lại với chuỗi bài viết về C++!
Sau khi đã làm quen với cấu trúc cơ bản của một chương trình C++ và cách thực hiện nhập/xuất dữ liệu đơn giản ở các bài trước, hôm nay là lúc chúng ta xắn tay áo lên và thực hành! Bài viết này không giới thiệu quá nhiều khái niệm mới toanh, mà tập trung vào việc áp dụng những gì đã học và làm quen thêm một vài "công cụ" cơ bản khác thông qua các ví dụ code cụ thể.
Hãy coi đây là một "sân chơi" để bạn tự tay gõ code, chạy thử, và cảm nhận cách ngôn ngữ C++ hoạt động ở mức độ đơn giản nhất. Thực hành là cách tốt nhất để học!
Chương trình C++ Đầu Tiên (Lại Một Lần Nữa!)
Không có cách nào tốt hơn để bắt đầu ngoài việc lặp lại cấu trúc cơ bản.
#include <iostream> // Bao gom thu vien input/output
int main() { // Ham chinh cua chuong trinh
cout << "Chao mung toi the gioi C++!" << endl; // In ra man hinh
return 0; // Ket thuc chuong trinh thanh cong
}
#include <iostream>
: Dòng này là chỉ thị tiền xử lý. Nó bảo trình biên dịch "nhập" nội dung của thư việniostream
vào chương trình của chúng ta. Thư viện này cung cấp các công cụ để làm việc với dòng nhập (input stream) và dòng xuất (output stream), ví dụ nhưcout
.int main() { ... }
: Đây là hàm chính (main function). Mọi chương trình C++ hợp lệ đều phải có một hàmmain
, và việc thực thi chương trình sẽ bắt đầu từ đây.int
là kiểu dữ liệu trả về của hàmmain
, theo quy ước, trả về 0 thường có nghĩa là chương trình kết thúc mà không gặp lỗi.cout << "..." << endl;
: Dòng này sử dụng đối tượngcout
(standard output stream) để gửi dữ liệu ("Chao mung toi the gioi C++!") ra thiết bị xuất chuẩn (thường là màn hình). Toán tử<<
được gọi là toán tử chèn (insertion operator).endl
là một "manipulator" chèn ký tự xuống dòng và "đẩy" (flush) bộ đệm, đảm bảo nội dung hiển thị ngay lập tức.return 0;
: Câu lệnh này kết thúc hàmmain
và trả về giá trị 0.
Bài tập nhỏ: Hãy thử thay đổi chuỗi "Chao mung toi the gioi C++!"
thành một câu khác mà bạn thích và chạy chương trình xem sao nhé!
Làm Việc Với Biến và Các Kiểu Dữ Liệu Cơ Bản
Trong lập trình, chúng ta cần nơi để lưu trữ dữ liệu. Đó chính là mục đích của biến (variables). Mỗi biến có một kiểu dữ liệu (data type) nhất định, quy định loại giá trị nó có thể chứa (số nguyên, số thực, ký tự, v.v.) và kích thước bộ nhớ cần thiết.
Hãy xem cách khai báo, gán giá trị và sử dụng biến:
#include <iostream>
#include <string> // Can them thu vien nay cho string
int main() {
// Khai bao (tao) cac bien voi cac kieu du lieu khac nhau
int soLuongQuaTao; // So nguyen
double giaMoiKilogram; // So thuc (co phan thap phan)
char kyTuDauTienTenBan; // Ky tu don
bool dangHocLapTrinh; // Gia tri logic (true/false)
string tenMonHoc; // Chuoi ky tu (can #include <string>)
// Gan gia tri cho cac bien
soLuongQuaTao = 50;
giaMoiKilogram = 1.5;
kyTuDauTienTenBan = 'H'; // Ky tu dung dau nhay don ''
dangHocLapTrinh = true; // Gia tri true hoac false
tenMonHoc = "C++ Programming"; // Chuoi dung dau nhay kep ""
// In gia tri cua cac bien ra man hinh
cout << "So luong tao: " << soLuongQuaTao << endl;
cout << "Gia moi kg: $" << giaMoiKilogram << endl;
cout << "Ky tu dau ten ban: " << kyTuDauTienTenBan << endl;
cout << "Dang hoc lap trinh: " << dangHocLapTrinh << endl; // true in ra 1, false in ra 0
cout << "Mon hoc: " << tenMonHoc << endl;
return 0;
}
- Khai báo biến: Cú pháp cơ bản là
KieuDuLieu TenBien;
. Ví dụ:int soLuongQuaTao;
. Dòng này yêu cầu hệ thống cấp phát một vùng nhớ để lưu một số nguyên và đặt tên cho vùng nhớ đó làsoLuongQuaTao
. - Gán giá trị: Sử dụng toán tử gán
=
. Ví dụ:soLuongQuaTao = 50;
. Dòng này đưa giá trị 50 vào vùng nhớ được đặt tên làsoLuongQuaTao
. - Bạn có thể khai báo và gán giá trị ngay lập tức (khởi tạo - initialization):
int soLuongQuaLe = 20;
. Đây là cách làm thường được khuyến khích để tránh biến có giá trị "rác" (không xác định) ban đầu. - Kiểu
char
dùng để lưu một ký tự đơn, được đặt trong dấu nháy đơn ('A'
,'b'
,'5'
,'$'
). - Kiểu
bool
chỉ có hai giá trị:true
(đúng) hoặcfalse
(sai). Khi in ra màn hình vớicout
,true
thường hiển thị là1
,false
là0
. - Kiểu
string
dùng để lưu trữ chuỗi ký tự (nhiều ký tự nối lại), được đặt trong dấu nháy kép ("Hello"
,"FullhouseDev"
). Để sử dụngstring
, bạn cần#include <string>
.
Bài tập nhỏ: Hãy thêm các biến với kiểu dữ liệu khác (ví dụ: float
, long long
) và thử lưu trữ các giá trị khác nhau vào chúng.
Thực Hiện Các Phép Tính Toán Học Đơn Giản
C++ cung cấp các toán tử cơ bản để thực hiện các phép tính:
#include <iostream>
int main() {
int a = 10;
int b = 3;
int tong = a + b; // Phep cong
int hieu = a - b; // Phep tru
int tich = a * b; // Phep nhan
int thuongNguyen = a / b; // Phep chia lay phan nguyen (khi ca hai la so nguyen)
int soDu = a % b; // Phep chia lay so du (modulo) - chi dung voi so nguyen
double x = 10.0; // Su dung so thuc de co ket qua chia thuc
double y = 3.0;
double thuongThuc = x / y; // Phep chia lay phan thuc
cout << "a = " << a << ", b = " << b << endl;
cout << "Tong: " << tong << endl; // 13
cout << "Hieu: " << hieu << endl; // 7
cout << "Tich: " << tich << endl; // 30
cout << "Thuong (nguyen): " << thuongNguyen << endl; // 3
cout << "So du: " << soDu << endl; // 1
cout << "x = " << x << ", y = " << y << endl;
cout << "Thuong (thuc): " << thuongThuc << endl; // 3.333...
// Ket hop phep toan va in truc tiep
cout << "Tong cua a va b la: " << a + b << endl;
return 0;
}
- Các toán tử
+
,-
,*
,/
hoạt động như trong toán học thông thường. - Toán tử
%
(modulo) trả về số dư của phép chia. Nó chỉ hoạt động với các số nguyên. - Lưu ý quan trọng về phép chia
/
:- Nếu cả hai toán hạng (số bị chia và số chia) đều là kiểu số nguyên (
int
), kết quả sẽ là phần nguyên của phép chia (phần thập phân bị cắt bỏ). - Nếu ít nhất một trong hai toán hạng là kiểu số thực (
double
,float
), kết quả sẽ là phép chia số thực. Bạn có thể "ép kiểu" (type casting) tạm thời một số nguyên thành số thực để thực hiện phép chia thực, ví dụ:double thuong = (double)a / b;
.
- Nếu cả hai toán hạng (số bị chia và số chia) đều là kiểu số nguyên (
- Bạn có thể thực hiện các phép toán ngay trong câu lệnh
cout
.
Bài tập nhỏ: Hãy viết chương trình nhỏ nhập vào bán kính hình tròn từ người dùng (double banKinh; cin >> banKinh;
) và tính diện tích, chu vi của hình tròn đó (S = pi R^2, C = 2 pi * R). Sử dụng const double PI = 3.14159;
để khai báo hằng số PI.
Nhập Xuất (I/O) "Nâng Cấp" Một Chút
Chúng ta đã dùng cin
để nhập một giá trị. Bạn hoàn toàn có thể nhập nhiều giá trị cùng lúc và kết hợp nhập/xuất một cách linh hoạt hơn.
#include <iostream>
#include <string>
int main() {
int so1, so2; // Khai bao nhieu bien cung kieu tren mot dong
cout << "Nhap hai so nguyen (cach nhau bang khoang trang): ";
cin >> so1 >> so2; // Doc hai so lien tiep tu mot dong
cout << "Ban da nhap: " << so1 << " va " << so2 << endl;
cout << "Tong cua hai so la: " << so1 + so2 << endl;
string tenDayDu;
// cout << "Nhap ten day du cua ban: ";
// cin >> tenDayDu; // Chi doc duoc tu dau den khoang trang dau tien!
// cout << "Ten da nhap: " << tenDayDu << endl; // Se bi sai neu ten co khoang trang
// De doc ca dong (bao gom khoang trang), dung getline
cin.ignore(); // Loai bo ky tu xuong dong con lai tu lenh nhap truoc
cout << "Nhap ten day du cua ban: ";
getline(cin, tenDayDu); // Doc ca dong cho den khi gap Enter
cout << "Xin chao, " << tenDayDu << "!" << endl;
return 0;
}
- Bạn có thể dùng toán tử
>>
nối tiếp nhau (cin >> var1 >> var2;
) để đọc nhiều giá trị từ dòng nhập.cin
sẽ tự động bỏ qua các ký tự trắng (khoảng trắng, tab, xuống dòng) giữa các giá trị. cin
với toán tử>>
dừng đọc khi gặp ký tự trắng. Điều này có nghĩa là nó không phù hợp để đọc chuỗi có chứa khoảng trắng (ví dụ: tên đầy đủ).- Để đọc toàn bộ một dòng nhập từ người dùng (bao gồm cả khoảng trắng), bạn nên dùng hàm
getline(cin, bien_string);
. - Lưu ý dòng
cin.ignore();
. Khi bạn dùngcin >>
để đọc số (hoặc bất kỳ kiểu dữ liệu nào khác không phải chuỗi), ký tự xuống dòng (\n
) mà bạn gõ khi nhấn Enter vẫn còn lại trong bộ đệm nhập. Nếu ngay sau đó bạn dùnggetline
,getline
sẽ đọc ngay ký tự xuống dòng đó và nghĩ rằng đã kết thúc dòng, dẫn đến việc bỏ qua dòng nhập thực tế của bạn.cin.ignore();
được dùng để loại bỏ (bỏ qua) ký tự xuống dòng còn sót lại đó, chuẩn bị bộ đệm chogetline
.
Bài tập nhỏ: Hãy viết chương trình nhập vào 3 số nguyên và in ra tổng, trung bình cộng, tích của chúng.
Rẽ Nhánh Chương Trình với if
Các chương trình thường cần đưa ra quyết định dựa trên các điều kiện khác nhau. Câu lệnh if
là cách cơ bản nhất để làm điều này.
#include <iostream>
int main() {
int diemSo;
cout << "Nhap diem so cua ban (0-100): ";
cin >> diemSo;
// Kiem tra dieu kien
if (diemSo >= 50) {
cout << "Chuc mung! Ban da dau." << endl;
}
// Co the ket hop voi else de xu ly truong hop dieu kien sai
if (diemSo < 50) {
cout << "Ban chua dat. Hay co gang hon nhe!" << endl;
} else { // Neu dieu kien tren (diemSo < 50) la SAI, thi thuc hien khoi code nay
cout << "Va ban co the tiep tuc hoc cac bai nang cao hon." << endl;
}
// Ket hop voi else if cho nhieu truong hop
if (diemSo >= 90) {
cout << "Ban dat loai Xuat sac!" << endl;
} else if (diemSo >= 75) { // Chi kiem tra dieu kien nay neu dieu kien tren SAI
cout << "Ban dat loai Gioi." << endl;
} else if (diemSo >= 50) { // Chi kiem tra dieu kien nay neu cac dieu kien tren SAI
cout << "Ban dat loai Kha." << endl;
} else { // Neu tat ca cac dieu kien tren deu SAI
cout << "Ban dat loai Trung binh hoac Yeu." << endl;
}
cout << "Ket thuc chuong trinh danh gia diem." << endl;
return 0;
}
- Cú pháp cơ bản:
if (dieu_kien) { // code thuc thi neu dieu_kien la true }
. dieu_kien
là một biểu thức logic, kết quả của nó phải làtrue
hoặcfalse
. Các toán tử so sánh thường dùng:>
(lớn hơn),<
(nhỏ hơn),>=
(lớn hơn hoặc bằng),<=
(nhỏ hơn hoặc bằng),==
(bằng),!=
(khác).- Khối code bên trong cặp dấu ngoặc nhọn
{}
là phần sẽ được thực thi chỉ khidieu_kien
là đúng. Nếu chỉ có một dòng lệnh sauif
, bạn có thể bỏ qua cặp{}
nhưng luôn khuyến khích sử dụng chúng để code rõ ràng hơn và tránh lỗi. - Bạn có thể thêm
else { ... }
sau khốiif
. Phần code trongelse
sẽ được thực thi chỉ khi điều kiện trongif
là sai. - Bạn có thể dùng
else if (dieu_kien_moi) { ... }
để kiểm tra nhiều điều kiện theo thứ tự. Các điều kiện này chỉ được kiểm tra nếu các điều kiệnif
hoặcelse if
đứng trước nó đều sai. Chương trình sẽ thực thi khối code của điều kiện đúng đầu tiên mà nó gặp và bỏ qua các phầnelse if
vàelse
còn lại.
Bài tập nhỏ: Nhập vào một số nguyên. Dùng if
kiểm tra xem số đó là số chẵn hay số lẻ (gợi ý: dùng toán tử %).
Lặp Lại Công Việc với Vòng Lặp for
Khi bạn cần thực hiện một công việc lặp đi lặp lại một số lần nhất định, vòng lặp là cứu cánh. Vòng lặp for
là một trong những vòng lặp phổ biến nhất, thường dùng khi bạn biết trước số lần lặp hoặc muốn lặp qua một dãy giá trị.
#include <iostream>
int main() {
// Lap 5 lan de in ra mot loi chao
for (int i = 0; i < 5; ++i) {
// Khoi code nay se lap lai
cout << "Hello lap trinh vien! Day la lan lap thu " << i + 1 << endl;
}
cout << "Vong lap for da ket thuc." << endl;
// Vi du khac: Lap tu 10 den 1
for (int j = 10; j > 0; --j) {
cout << "Dem nguoc: " << j << endl;
}
// Vi du: Lap voi buoc nhay khac 1
for (int k = 0; k <= 20; k = k + 2) { // k += 2; cung tuong tu
cout << "So chan: " << k << endl;
}
return 0;
}
- Cấu trúc của vòng lặp
for
là:for (khoi_tao; dieu_kien; cap_nhat) { // code can lap }
.khoi_tao
: Phần này được thực thi một lần duy nhất khi vòng lặp bắt đầu. Thường dùng để khai báo và gán giá trị ban đầu cho biến đếm (counter variable).dieu_kien
: Phần này được kiểm tra trước mỗi lần lặp. Nếudieu_kien
làtrue
, thân vòng lặp ({...}
) sẽ được thực thi. Nếu làfalse
, vòng lặp kết thúc.cap_nhat
: Phần này được thực thi sau mỗi lần thân vòng lặp được thực thi. Thường dùng để thay đổi giá trị của biến đếm (tăng hoặc giảm).
- Trong ví dụ đầu tiên:
int i = 0;
(khởi tạoi
bằng 0),i < 5;
(lặp khii
nhỏ hơn 5),++i;
(tăngi
lên 1 sau mỗi vòng). Vòng lặp sẽ chạy vớii
có giá trị 0, 1, 2, 3, 4 (tổng cộng 5 lần). ++i
vài++
đều là toán tử tăng (increment)i
lên 1. Trong phầncap_nhat
của vòng lặpfor
, chúng thường có tác dụng tương tự.--j
là toán tử giảm (decrement).
Bài tập nhỏ: Viết chương trình sử dụng vòng lặp for
để tính tổng các số nguyên từ 1 đến 100.
Thêm Ghi Chú Cho Code "Dễ Hiểu Hơn"
Khi viết code, đặc biệt là những đoạn phức tạp, việc thêm comment (ghi chú) là cực kỳ quan trọng. Comment là những dòng văn bản mà trình biên dịch sẽ hoàn toàn bỏ qua, nhưng chúng giúp bạn (và những người khác đọc code của bạn) hiểu rõ hơn mục đích, cách hoạt động của từng phần code.
C++ hỗ trợ hai loại comment:
#include <iostream>
int main() {
// Day la mot comment tren mot dong.
// Moi thu sau // tren cung mot dong se bi bo qua boi trinh bien dich.
/*
Day la mot comment tren nhieu dong.
No bat dau bang /*
va ket thuc bang */.
Ban co the viet nhieu dong tuy thich o giua.
*/
int diemTrungBinh = 85; // Co the dat comment o cuoi dong code de giai thich bien
cout << "Diem trung binh: " << diemTrungBinh << endl; // In ra diem trung binh
return 0;
}
- Comment một dòng: Bắt đầu bằng
//
. Mọi ký tự từ//
đến cuối dòng đều là comment. - Comment nhiều dòng: Bắt đầu bằng
/*
và kết thúc bằng*/
. Mọi thứ nằm giữa hai ký hiệu này (trên một hoặc nhiều dòng) đều là comment. - Sử dụng comment một cách thông minh. Đừng chỉ diễn tả lại code (ví dụ:
// Tang i len 1
sau++i;
). Hãy giải thích tại sao bạn làm điều đó, mục đích của một khối code phức tạp, hoặc các giả định quan trọng.
Bài tập nhỏ: Quay lại một trong các ví dụ code ở trên và thêm comment vào để giải thích các phần khác nhau của code.
Tóm Lại (Không Phải Kết Luận Nhé!)
Qua bài thực hành này, bạn đã làm quen (hoặc củng cố kiến thức) về:
- Cấu trúc cơ bản của chương trình C++.
- Cách sử dụng biến và các kiểu dữ liệu thông dụng (
int
,double
,char
,bool
,string
). - Thực hiện các phép tính cơ bản.
- Sử dụng
cin
vàcout
để nhập/xuất dữ liệu, bao gồm cả đọc chuỗi có khoảng trắng vớigetline
. - Đưa ra quyết định trong chương trình với câu lệnh
if
(vàelse
,else if
). - Lặp lại công việc với vòng lặp
for
. - Cách thêm ghi chú (comment) vào code.
Bài tập ví dụ: C++ Bài 1.A5: Hàm sqrt và cbrt.
Cho số nguyên dương \(a\), nhiệm vụ của bạn là tính căn bậc \(2\) và căn bậc \(3\) của \(a\).
Input Format
Nhập vào số nguyên dương \(a\). \((-10^9 ≤ a ≤ 10^9).\)
Output Format
In ra căn bậc \(2\) của \(a\) với \(3\) số sau dấu phẩy và căn bậc \(3\) của \(a\) với \(3\) số sau dấu phẩy mỗi đáp án cách nhau \(1\) dấu cách.
Ví dụ:
Dữ liệu vào:
28
Dữ liệu ra:
5.292 3.037
Giải thích ví dụ mẫu:
- Căn bậc 2 của 28 là 5.292 và căn bậc 3 là 3.037.
Mục tiêu: Đọc một số nguyên
a
, tính căn bậc 2 và căn bậc 3 củaa
, sau đó in kết quả với độ chính xác 3 chữ số thập phân.Các thư viện cần dùng:
- Cần thư viện để nhập xuất dữ liệu:
iostream
. - Cần thư viện chứa các hàm toán học như căn bậc 2 (
sqrt
) và căn bậc 3 (cbrt
):cmath
. - Cần thư viện để định dạng đầu ra (số chữ số sau dấu phẩy):
iomanip
.
- Cần thư viện để nhập xuất dữ liệu:
Đọc dữ liệu:
- Khai báo một biến kiểu số nguyên (int) để lưu giá trị của
a
. - Sử dụng đối tượng
cin
để đọc giá trị củaa
từ đầu vào chuẩn.
- Khai báo một biến kiểu số nguyên (int) để lưu giá trị của
Tính toán:
- Hàm
sqrt()
vàcbrt()
trong thư việncmath
nhận đối số kiểu dấu phẩy động (nhưdouble
) và trả về kết quả kiểu dấu phẩy động. - Bạn cần truyền biến
a
vào hai hàm này. Biếna
kiểuint
sẽ được tự động chuyển đổi sang kiểu dấu phẩy động khi truyền vào các hàm này, hoặc bạn có thể ép kiểu tường minh sangdouble
nếu muốn (ví dụ:sqrt((double)a)
). - Lưu kết quả tính toán vào hai biến kiểu dấu phẩy động (ví dụ:
double
).
- Hàm
Định dạng và in kết quả:
- Sử dụng đối tượng
cout
để in kết quả. - Để định dạng số chữ số sau dấu phẩy khi in ra bằng
cout
, bạn cần sử dụng các "manipulator" từ thư việniomanip
. - Sử dụng
fixed
để đảm bảo in số theo dạng thập phân cố định, không phải dạng khoa học (ví dụ: 1.234e+05). - Sử dụng
setprecision(3)
để chỉ định số chữ số sau dấu phẩy là 3 khi dùng kèm vớifixed
. - In kết quả của căn bậc 2, sau đó in một dấu cách (
" "
), rồi in kết quả của căn bậc 3. - Kết thúc dòng bằng
endl
hoặc'\n'
.
- Sử dụng đối tượng
Cấu trúc chương trình:
- Bắt đầu với hàm
main()
. - Bao gồm các câu lệnh
#include
cho các thư viện cần thiết. - Viết các bước đọc dữ liệu, tính toán và in kết quả bên trong hàm
main()
. - Kết thúc hàm
main()
bằngreturn 0;
.
- Bắt đầu với hàm
Lưu ý về giới hạn đầu vào: Mặc dù đề bài ghi "số nguyên dương a" nhưng lại cho giới hạn "-10^9 ≤ a ≤ 10^9", bao gồm cả số âm.
- Hàm
sqrt()
của số âm sẽ trả về một giá trị biểu diễn "Not a Number" (NaN
). - Hàm
cbrt()
xử lý số âm bình thường và trả về kết quả âm (ví dụ:cbrt(-8)
là-2
). - Cách
cout
in giá trịNaN
với định dạng cố định có thể khác nhau tùy hệ thống, nhưng thông thường sẽ in ra chuỗi như "nan". Dạng output "___.___" cho phép hiển thị cả "nan".
Comments