Nội Dung
1
Cú PhápCơ Bản
Biến, kiểu dữ liệu, toán tử và cấu trúc điều
khiển
2
Hàm & Mảng
Định nghĩa hàm, tham số, mảng một chiều
và đa chiều
Con Trỏ
Khái niệm, khai báo và sử dụng con trỏ trong
C++
4
Bài Tập Tổng Hợp
Áp dụng kiến thức vào các bài tập thực tế
3
3.
Cấu Trúc CơBản Chương Trình C++
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
Giải thích:
#include <iostream>: Thư viện nhập/xuất
using namespace std: Sử dụng không gian tên chuẩn
int main(): Hàm chính của chương trình
return 0: Trả về giá trị thành công
Lưu ý: Mọi chương trình C++ đều phải có hàm
main() để bắt đầu thực thi.
4.
Kiểu Dữ LiệuCơ
Bản
Số Nguyên
int: 4 bytes (-2^31 đến 2^31-1)
short: 2 bytes
long: 8 bytes
unsigned: Chỉ số dương
Số Thực
float: 4 bytes, 7 chữ số
double: 8 bytes, 15 chữ số
long double: Độ chính xác cao
Khác
char: Ký tự (1 byte)
bool: true/false
string: Chuỗi ký tự
5.
Khai Báo Biến- Ví Dụ Thực Tế
Cú Pháp Cơ Bản
// Khai báo từng biến
int tuoi = 20;
float diem = 8.5;
char xepLoai = 'A';
bool daTotNghiep = false;
string hoTen = "Nguyen Van A";
int a = 5, b = 10, c;
Bài Tập Áp Dụng
Đề bài: Tạo chương trình quản lý thông tin sinh viên với các
thông tin: họ tên, tuổi, điểm trung bình, xếp loại.
Nhập và xuất thông tin của sinh viên.
6.
Toán Tử TrongC++
Toán Tử Số Học
+ (cộng), - (trừ)
* (nhân), / (chia)
% (chia lấy dư)
++ (tăng 1), -- (giảm 1)
Toán Tử So Sánh
== (bằng), != (khác)
> (lớn hơn), < (nhỏ hơn)
>= (lớn hơn hoặc bằng)
<= (nhỏ hơn hoặc bằng)
Toán Tử Logic
&& (AND - và)
|| (OR - hoặc)
! (NOT - phủ định)
Cấu Trúc ĐiềuKhiển: if-else
Cú Pháp
if (điều_kiện) { // Khối lệnh 1}
else if (điều_kiện_2) { // Khối lệnh 2}
else { // Khối lệnh 3}
Chú ý: Sử dụng dấu ngoặc nhọn {} ngay cả khi chỉ
có một lệnh để tránh lỗi logic.
Ví Dụ: Xếp Loại Học Lực
9.
Bài Tập ThựcHành Cấu Trúc Điều Khiển
Hãy áp dụng kiến thức về cấu trúc if-else để giải các bài tập dưới đây.
Bài 1: Kiểm Tra Số Chẵn/Lẻ
Viết chương trình nhập vào một số nguyên từ bàn phím. Đưa ra thông báo số đó là "Số chẵn" hay "Số lẻ".
Bài 2: Phân Loại Số Nâng Cao
Viết chương trình yêu cầu người dùng nhập vào một số nguyên N.
Xác định N là "Số dương", "Số âm" hay "Số 0".
Nếu N là số dương, kiểm tra và thông báo thêm liệu N có phải là "Số chính phương" và "Số nguyên tố" hay không. (Lưu ý: số 1 không phải số nguyên tố, số chính phương là
bình phương của một số nguyên).
Bài 3: Tính Tiền Giảm Giá Phức Tạp
Một cửa hàng áp dụng chính sách giảm giá linh hoạt dựa trên nhiều yếu tố. Viết chương trình để tính tổng số tiền phải thanh toán cuối cùng.
Nhập tổng giá trị đơn hàng, loại khách hàng ("VIP" hoặc "Thường"), số lượng sản phẩm mua, và mã giảm giá (nếu có, ví dụ: "SALE20").
Các mức giảm giá cơ bản (áp dụng cho tất cả):- Đơn hàng dưới 500.000 VNĐ: không giảm giá.- Đơn hàng từ 500.000 VNĐ đến dưới 1.000.000 VNĐ: giảm 5%.- Đơn hàng từ
1.000.000 VNĐ đến dưới 2.000.000 VNĐ: giảm 10%.- Đơn hàng từ 2.000.000 VNĐ trở lên: giảm 15%.
Ưu đãi bổ sung:- Khách hàng VIP: được giảm thêm 5% trên giá đã giảm nếu tổng số sản phẩm từ 5 trở lên.
Mã giảm giá:- Nếu nhập mã "SALE20": giảm thêm 20% trên giá đã giảm, nhưng không áp dụng đồng thời với ưu đãi VIP. (Tức là, nếu là VIP và đủ điều kiện, khách hàng sẽ
chọn giảm 20% hoặc ưu đãi VIP + giảm giá cơ bản, tùy cái nào lợi hơn).
Quy tắc ưu tiên: Các giảm giá được áp dụng theo thứ tự: giảm giá cơ bản -> ưu đãi VIP (nếu đủ điều kiện và không có mã SALE20) hoặc mã giảm giá SALE20 (nếu có và
không nhận ưu đãi VIP).
10.
Bài Tập: TínhTiền Điện
Đề bài: Viết chương trình tính tiền điện theo bậc thang:
• 0-50 kWh: 1,678 đồng/kWh
• 51-100 kWh: 1,734 đồng/kWh
• 101-200 kWh: 2,014 đồng/kWh
• Trên 200 kWh: 2,536 đồng/kWh
11.
Cấu Trúc Lặp:for
Khởi tạo
Thiết lập giá trị ban đầu cho biến đếm
Điều kiện
Kiểm tra điều kiện tiếp tục vòng lặp
Cập nhật
Thay đổi giá trị biến đếm sau mỗi lần lặp
Cú Pháp
for (khởi_tạo; điều_kiện; cập_nhật) { // Khối
lệnh lặp
}
Ví Dụ
// In các số từ 1 đến 10
for (int i = 1; i <= 10; i++)
{ cout << i << " ";}
// Kết quả: 1 2 3 4 5 6 7 8 9 10
12.
Cấu Trúc Lặp:while và do-
while
Vòng Lặp while
int i = 1;
while (i <= 5) {
cout << "Lần " << i <<
endl; i++;}
Đặc điểm: Kiểm tra điều kiện trước
khi thực thi
Vòng Lặp do-while
int i = 1;
do { cout << "Lần " << i
<< endl; i+
+;
} while (i <= 5);
Đặc điểm: Thực thi ít nhất một lần
trước khi kiểm tra điều kiện
13.
Bài Tập: TínhTổng và Trung Bình
Đề bài: Nhập n số nguyên từ bàn phím, tính tổng và trung bình cộng của chúng.
Bổ sung: tính tổng các số chia hết cho 3 dư 1
14.
Định Nghĩa vàGọi
Hàm
Cú Pháp Định Nghĩa
Hàm
kiểu_trả_về tên_hàm(tham_số) {
// Nội dung hàm
return giá_trị; // nếu có}
Ví Dụ Hàm Đơn Giản
int cong(int a, int b) {
return a + b;
}
void chaoHoi() {
cout << "Xin chào!" << endl;
}
Gọi Hàm Trong
main()
int main() { // Gọi hàm không trả về giá trị
chaoHoi(); // Gọi hàm có trả về giá trị
int ketQua = cong(5, 3);
cout << "5 + 3 = " << ketQua;
return 0;
}
Mẹo: Hàm void không cần return, hàm khác phải có return.
15.
Hàm Với ThamSố Mặc
Định
#include <iostream>using namespace std;
// Hàm tính lũy thừa với số mũ mặc định là 2
double luyThua(double coBan, int soMu = 2) {
double ketQua = 1;
for (int i = 0; i < soMu; i++) {
ketQua *= coBan; }
return ketQua;
}
int main() {
cout << "5^2 = " << luyThua(5) << endl; // Sử dụng giá trị mặc
định cout << "2^3 = " << luyThua(2, 3) << endl; // Cung cấp cả
hai tham số return 0;
}
Ưu điểm: Tham số mặc định giúp hàm linh hoạt hơn và giảm số lượng tham số cần
truyền.
16.
Bài Tập: HàmKiểm Tra Số Nguyên Tố
Đề bài: Viết hàm kiểm tra một số có phải số nguyên tố không và chương trình liệt kê các số nguyên tố từ 1 đến n.
17.
Mảng Một Chiều
KhaiBáo
int arr[5]; // 5 phần tử
int nums[] = {1, 2, 3, 4, 5};
int data[100] = {0}; // Khởi
tạo 0
Truy Cập
arr[0] = 10; // Gán giá trị
cout << arr[0]; // In giá trị
int x = arr[2]; // Lấy giá trị
Duyệt Mảng
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
Lưu ý: Chỉ số mảng bắt đầu từ 0. Mảng có n phần tử thì chỉ số từ 0 đến n-1.
18.
Mảng Hai Chiều
KhaiBáo và Khởi Tạo
// Khai báo ma trận 3x3
int matrix[3][3];// Khởi tạo với giá trị
int mat[2][3] = { {1, 2, 3}, {4, 5, 6}};
Truy Cập Phần Tử
matrix[0][0] = 10; // Hàng 0, cột 0
int value = matrix[1][2]; // Lấy giá trị
Duyệt Ma Trận
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " "; } cout << endl; //
Xuống dòng}
19.
Con Trỏ -Khái Niệm Cơ Bản
1 Khai Báo Con Trỏ
int x = 10;int* ptr; // Con trỏ đến int
2 Gán Địa Chỉ
ptr = &x; // ptr trỏ đến x
cout << ptr; // In địa chỉ
3 Truy Cập Giá Trị
cout << *ptr; // In giá trị 10
*ptr = 20; // Thay đổi giá trị x
Ghi nhớ: & lấy địa chỉ, * lấy giá trị tại địa chỉ
20.
Cấp Phát ĐộngBộ
Nhớ
Toán Tử new và
delete
// Cấp phát cho một biến
int* p = new int(10);// xin cấp phát 10 ô nhớ kiểu int
cout << *p;
int n = 5;
int* arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = i * 2;
}
delete[] arr; // Giải phóng mảng
Ví Dụ Thực Tế
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Nhập kích thước: ";
cin >> n;
double* diem = new double[n];
for (int i = 0; i < n; i++) {
cout << "Điểm " << i+1 << ": ";
cin >> diem[i];
} // Xử lý dữ liệu...
For ( int i=0; i < n; i++){
count <<“Điểm thứ “<<i+1<<diem[i]<<endl;
}
delete[] diem; // giải phóng bộ nhớ
return 0;
}
21.
Bài Tập TổngHợp C++
Bài 1: Tính Tổng Các Số Chẵn
Viết chương trình C++ yêu cầu người dùng nhập vào hai số nguyên dương a và b (với a < b). Sau đó,
tính và in ra tổng tất cả các số chẵn trong khoảng từ a đến b (bao gồm cả a và b nếu chúng là số chẵn).
Yêu cầu: Sử dụng vòng lặp for hoặc while để duyệt qua các số và điều kiện if để kiểm tra số chẵn.
Bài 2: Tìm Phần Tử Lớn Nhất và Nhỏ Nhất trong Mảng
Xây dựng một hàm C++ có tên findMinMax nhận vào một mảng số nguyên và kích thước của mảng.
Hàm này sẽ tìm và trả về phần tử lớn nhất và phần tử nhỏ nhất trong mảng.
Yêu cầu:
Hàm findMinMax nên sử dụng con trỏ hoặc tham chiếu để trả về cả hai giá trị.
Trong hàm main, khởi tạo một mảng với ít nhất 5 phần tử, gọi hàm và in kết quả ra màn hình.
Bài 3: Tính Giai Thừa của Một Số
Viết một hàm C++ tên là tinhGiaiThua nhận vào một số nguyên không âm n. Hàm này sẽ tính và trả về
giá trị giai thừa của n (n!).
Yêu cầu:
Sử dụng vòng lặp for để tính giai thừa.
Xử lý trường hợp đặc biệt khi n = 0 (0! = 1).
Trong hàm main, yêu cầu người dùng nhập một số, gọi hàm và in kết quả.
Bài 4: Phân Tích Điểm Số Sinh Viên
Viết chương trình cho phép người dùng nhập điểm của N sinh viên (N do người dùng nhập). Sau đó,
tính điểm trung bình của các sinh viên và đếm xem có bao nhiêu sinh viên có điểm cao hơn hoặc bằng
điểm trung bình.
Yêu cầu:
• Sử dụng mảng động để lưu trữ điểm.
• Sử dụng hàm để tính điểm trung bình và một hàm khác để đếm số sinh viên trên trung bình.
• Giải phóng bộ nhớ đã cấp phát sau khi hoàn thành.
Editor's Notes
#3 Chỉ thị tiền xử lý: các thư viện,file tách mã nguồn, các hang số…
2. Khai báo biến Global - có phạm vi truy cập cả chương trình kết thúc khi gặp return trong main
3. Khai báo hàm;
4. Hàm main – hàm chính để bắt đầu thực thi
#11 Chúng ta sẽ tìm hiểu về cấu trúc lặp for trong lập trình
Cấu trúc for có 3 thành phần chính:
Khởi tạo: Thiết lập giá trị ban đầu cho biến đếm
Điều kiện: Kiểm tra điều kiện để tiếp tục vòng lặp
Cập nhật: Thay đổi giá trị biến đếm sau mỗi lần lặp
Cú pháp cơ bản của vòng lặp for:
for (khởi_tạo; điều_kiện; cập_nhật) { // Khối lệnh lặp }
Ví dụ: In các số từ 1 đến 10
for (int i = 1; i <= 10; i++) { cout << i << " "; }
Kết quả: 1 2 3 4 5 6 7 8 9 10
#12 1. Mở đầu: Giới thiệu về vòng lặp while và do-while
Vòng lặp được sử dụng để thực thi một khối lệnh lặp đi lặp lại nhiều lần cho đến khi một điều kiện nào đó không còn đúng nữa.
Vòng lặp while: Kiểm tra điều kiện ngay từ đầu. Nếu điều kiện đúng, khối lệnh mới được thực thi. Nếu điều kiện sai ngay từ đầu, khối lệnh bên trong vòng lặp sẽ không bao giờ được thực thi.
Vòng lặp do-while: Luôn thực thi khối lệnh ít nhất một lần, sau đó mới kiểm tra điều kiện. Nếu điều kiện đúng, vòng lặp tiếp tục; nếu sai, vòng lặp kết thúc.
3. Khi nào nên sử dụng while vs do-while
Sử dụng while: Khi bạn cần đảm bảo rằng một khối mã chỉ chạy khi một điều kiện cụ thể được đáp ứng, và có khả năng khối mã đó không chạy lần nào. Ví dụ: đọc dữ liệu từ tệp cho đến khi hết tệp, chờ người dùng nhập đúng thông tin.
Sử dụng do-while: Khi bạn cần đảm bảo khối mã được thực thi ít nhất một lần, sau đó mới kiểm tra điều kiện để quyết định lặp lại hay không. Ví dụ: yêu cầu người dùng nhập input cho đến khi input hợp lệ, menu lựa chọn cho người dùng.
5. Các lỗi thường gặp và cách tránh
Vòng lặp vô hạn (Infinite Loop): Xảy ra khi điều kiện lặp luôn đúng và không bao giờ bị thay đổi để trở thành sai.
Cách tránh: Luôn đảm bảo có một cơ chế để thay đổi biến điều kiện trong mỗi lần lặp (`i++` trong ví dụ).
Lỗi "Off-by-one": Lặp thiếu hoặc thừa một lần.
Cách tránh: Kiểm tra kỹ điều kiện biên (ví dụ: `<` vs `<=`). Chạy thử với các giá trị cận biên để xem kết quả.
Sử dụng biến chưa được khởi tạo: Biến điều kiện cần có giá trị ban đầu xác định.
6. Mẹo sử dụng hiệu quả
Đảm bảo biến điều khiển vòng lặp được khởi tạo đúng và thay đổi đúng cách bên trong vòng lặp.
Sử dụng cấu trúc `while` khi số lần lặp không xác định trước và có thể là 0.
Sử dụng cấu trúc `do-while` khi bạn cần thực thi khối lệnh ít nhất một lần.
Giữ điều kiện lặp đơn giản và dễ hiểu.
7. So sánh với vòng lặp for
Vòng lặp for: Thường dùng khi số lần lặp đã biết trước hoặc có thể dễ dàng tính toán được. Cấu trúc gọn gàng, khởi tạo, điều kiện, cập nhật đều ở một dòng.
Vòng lặp while/do-while: Phù hợp hơn khi số lần lặp không xác định trước và phụ thuộc vào một điều kiện nào đó.
Về cơ bản, mọi vòng lặp `for` có thể chuyển thành `while` và ngược lại, nhưng nên chọn loại vòng lặp nào rõ ràng và dễ đọc hơn cho từng trường hợp cụ thể.
8. Bài tập thực hành gợi ý
Viết chương trình sử dụng `while` để tính tổng các số từ 1 đến N (do người dùng nhập).
Viết chương trình sử dụng `do-while` để yêu cầu người dùng nhập một số nguyên dương. Nếu nhập số âm hoặc 0, yêu cầu nhập lại.
Viết chương trình sử dụng `while` hoặc `do-while` để tìm số Fibonacci thứ N.
#13 #include <iostream>
using namespace std;
int main() {
int n, so, tong = 0;
cout << "Nhập số lượng số: ";
cin >> n;
for (int i = 1; i <= n; i++) {
cout << "Nhập số thứ " << i << ": ";
cin >> so;
tong += so;
}
double trungBinh = (double)tong / n;
cout << "Tổng: " << tong << endl;
cout << "Trung bình: " << trungBinh << endl;
return 0;
}
#14 Mở đầu: Tại sao cần sử dụng hàm trong lập trình?
Tái sử dụng mã (Code Reusability): Tránh lặp lại cùng một đoạn mã nhiều lần. Viết một lần, sử dụng nhiều nơi.
Mô đun hóa (Modularity): Chia chương trình lớn thành các phần nhỏ hơn, dễ quản lý và phát triển hơn.
Dễ đọc và bảo trì (Readability & Maintainability): Code được tổ chức rõ ràng, dễ hiểu và dễ sửa lỗi, nâng cấp.
Trừu tượng hóa (Abstraction): Che giấu chi tiết cài đặt, chỉ để lộ giao diện sử dụng.
Giải thích chi tiết cú pháp định nghĩa hàm:
kiểu_trả_về: Kiểu dữ liệu mà hàm sẽ trả về sau khi thực thi (ví dụ: int, double, string, void). Nếu không muốn trả về gì, dùng void.
tên_hàm: Tên duy nhất để gọi hàm, thường theo quy tắc camelCase hoặc snake_case, phản ánh chức năng của hàm (ví dụ: cong, tinhTong).
(tham_số): Danh sách các biến đầu vào mà hàm cần để thực hiện công việc. Mỗi tham số bao gồm kiểu dữ liệu và tên biến (ví dụ: int a, int b). Các tham số này là biến cục bộ chỉ tồn tại trong hàm.
// Nội dung hàm: Các câu lệnh sẽ được thực thi khi hàm được gọi.
return giá_trị;: Dùng để trả về một giá trị có kiểu trùng với kiểu_trả_về và thoát khỏi hàm. Bắt buộc phải có nếu kiểu_trả_về không phải là void.
Phân biệt hàm có trả về giá trị và hàm void:
Hàm có trả về giá trị (ví dụ: int cong(int a, int b)): Thực hiện một tác vụ và sau đó "trả lại" một kết quả cho nơi đã gọi nó. Kết quả này có thể được gán vào một biến, hoặc sử dụng trực tiếp trong biểu thức.
Hàm void (ví dụ: void chaoHoi()): Thực hiện một tác vụ nhưng không trả về bất kỳ giá trị nào. Thường dùng cho các hàm chỉ thực hiện in ra màn hình, thay đổi trạng thái của đối tượng, hoặc các tác vụ không cần một "kết quả" cụ thể.
Cách gọi hàm và sử dụng giá trị trả về:
Gọi hàm void: Chỉ cần viết tên_hàm(); hoặc tên_hàm(đối_số);. Ví dụ: chaoHoi();
Gọi hàm có trả về giá trị: Giá trị trả về có thể được gán vào một biến cùng kiểu hoặc sử dụng trực tiếp. Ví dụ: int ketQua = cong(5, 3); hoặc cout << cong(5, 3);
đối_số: Là các giá trị thực tế truyền vào khi gọi hàm, chúng sẽ được gán cho các tham_số tương ứng.
Phạm vi biến (Scope) trong hàm:
Các biến được khai báo bên trong một hàm (bao gồm cả tham số) chỉ có thể được truy cập bên trong hàm đó. Chúng được gọi là biến cục bộ.
Khi hàm kết thúc, các biến cục bộ này sẽ bị hủy.
Điều này giúp tránh xung đột tên biến giữa các hàm khác nhau.
Các lỗi thường gặp khi định nghĩa và gọi hàm:
Sai kiểu trả về hoặc không có return cho hàm không phải void.
Truyền sai số lượng hoặc sai kiểu đối số khi gọi hàm.
Sử dụng biến cục bộ của hàm này ở hàm khác.
Quên khai báo hàm (function prototype) nếu định nghĩa hàm sau hàm main().
Mẹo và best practices:
Đặt tên hàm rõ ràng, dễ hiểu.
Mỗi hàm chỉ nên thực hiện một công việc duy nhất (Single Responsibility Principle).
Tránh hàm quá dài, nên chia nhỏ thành các hàm con.
Sử dụng chú thích (comments) cho các hàm phức tạp hoặc có logic đặc biệt.
Luôn khai báo prototype hàm trước khi sử dụng nếu định nghĩa hàm sau hàm main().
Bài tập thực hành gợi ý:
Viết hàm tính diện tích hình chữ nhật.
Viết hàm kiểm tra một số có phải số nguyên tố không.
Viết hàm tìm số lớn nhất trong hai số.
Viết hàm void in ra các số chẵn từ 1 đến N.
#16 #include <iostream>
#include <cmath>
using namespace std;
bool laSoNguyenTo(int n) {
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (int i = 3; i <= sqrt(n); i += 2) {
if (n % i == 0) return false;
}
return true;
}
int main() {
int n;
cout << "Nhập n: ";
cin >> n;
cout << "Các số nguyên tố từ 1 đến " << n << ": ";
for (int i = 2; i <= n; i++) {
if (laSoNguyenTo(i)) {
cout << i << " ";
}
}
return 0;
}
#17 Mảng là một cấu trúc dữ liệu cơ bản trong lập trình, cho phép lưu trữ nhiều giá trị cùng kiểu dữ liệu trong một biến.
Khi khai báo mảng, ta cần chỉ rõ số lượng phần tử. Ví dụ: int arr[5]; là một mảng 5 phần tử.
Có thể khởi tạo giá trị cho mảng ngay khi khai báo, như int nums[] = {1, 2, 3, 4, 5};.
Để truy cập các phần tử trong mảng, ta dùng chỉ số bắt đầu từ 0. Ví dụ arr[0] là phần tử đầu tiên.
Có thể gán giá trị cho các phần tử bằng cách arr[0] = 10; hoặc lấy giá trị bằng int x = arr[2];.
Duyệt qua các phần tử của mảng thường được thực hiện bằng vòng lặp for.
Lưu ý rằng chỉ số của mảng bắt đầu từ 0, do đó phần tử cuối cùng có chỉ số là n-1 với n là số lượng phần tử.
#18 được sử dụng để lưu trữ và xử lý dữ liệu dưới dạng bảng (ma trận) với các hàng và cột.