g8-cs106 / dataset /knowledge_base.json
gracephamit's picture
Upload 29 files
0dd9600 verified
[
{
"id": "slide_3",
"topic": "Chương: Thuật toán và lưu đồ",
"type": "title",
"content_for_embedding": "Thuật toán và lưu đồ",
"metadata": {
"raw_text": "Thuật toán và lưu đồ",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_3.png",
"page_number": 3,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_4",
"topic": "Thuật toán là gì?",
"type": "text",
"content_for_embedding": "Thuật toán là tập hợp dãy hữu hạn các chỉ thị hay hành động được định nghĩa rõ ràng nhằm giải quyết một bài toán cụ thể nào đó. Các phương pháp biểu diễn thuật toán gồm: dùng ngôn ngữ tự nhiên, dùng lưu đồ hoặc sơ đồ khối, và dùng mã giả.",
"metadata": {
"raw_text": "Thuật toán là gì?\nLà tập hợp (dãy) hữu hạn các chỉ thị (hành động) được định nghĩa rõ ràng nhằm giải quyết một bài toán cụ thể nào đó.\nCác phương pháp biểu diễn thuật toán:\n• Dùng ngôn ngữ tự nhiên\n• Dùng lưu đồ - sơ đồ khối (flowchart)\n• Dùng mã giả (pseudocode)",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_4.png",
"page_number": 4,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_5",
"topic": "Biểu diễn thuật toán bằng lưu đồ",
"type": "text",
"content_for_embedding": "Dùng lưu đồ - sơ đồ khối. Là một công cụ trực quan để diễn đạt các thuật toán. Biểu diễn thuật toán bằng lưu đồ giúp người đọc theo dõi được sự phân cấp các trường hợp và quá trình xử lý của thuật toán. Phương pháp lưu đồ thường được dùng trong những thuật toán có tính rắc rối, khó theo dõi được quá trình xử lý.",
"metadata": {
"raw_text": "Dùng lưu đồ - sơ đồ khối\n• Là một công cụ trực quan để diễn đạt các thuật toán\n• Biểu diễn thuật toán bằng lưu đồ sẽ giúp người đọc theo dõi được sự phân cấp các trường hợp và quá trình xử lý của thuật toán\n• Phương pháp lưu đồ thường được dùng trong những thuật toán có tính rắc rối, khó theo dõi được quá trình xử lý",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_5.png",
"page_number": 5,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_6",
"topic": "Ký hiệu lưu đồ",
"type": "table",
"content_for_embedding": "Bảng ký hiệu lưu đồ gồm: 1. Bắt đầu / Kết thúc chương trình. 2. Điều kiện rẽ nhánh (lựa chọn). 3. Luồng xử lý. 4. Nhập. 5. Xuất. 6. Xử lý / tính toán / gán. 7. Trả về giá trị (return). 8. Điểm nối liên kết.",
"metadata": {
"raw_text": "STT 1: Bắt đầu / Kết thúc chương trình\nSTT 2: Điều kiện rẽ nhánh (lựa chọn)\nSTT 3: Luồng xử lý\nSTT 4: Nhập\nSTT 5: Xuất\nSTT 6: Xử lý / tính toán / gán\nSTT 7: Trả về giá trị (return)\nSTT 8: Điểm nối liên kết",
"diagram_text": "1: Terminator (Start/End)\n2: Decision (Diamond)\n3: Flow line (Arrow)\n4: Input (Parallelogram)\n5: Output (Parallelogram)\n6: Process (Rectangle)\n7: Return symbol\n8: Connector",
"has_diagram": true,
"image_path": "images/slide_6.png",
"page_number": 6,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_7",
"topic": "Ví dụ thuật toán giải phương trình bậc nhất",
"type": "text",
"content_for_embedding": "Thuật toán giải phương trình bậc nhất ax + b = 0. Đầu vào: a, b thuộc R. Đầu ra: nghiệm của phương trình ax + b = 0.",
"metadata": {
"raw_text": "Ví dụ: Thuật toán giải phương trình bậc nhất ax + b = 0 (a, b là số thực)\nĐầu vào: a, b thuộc R\nĐầu ra: nghiệm phương trình ax + b = 0",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_7.png",
"page_number": 7,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_8",
"topic": "Lưu đồ giải phương trình bậc nhất",
"type": "flowchart",
"content_for_embedding": "Lưu đồ giải phương trình ax + b = 0. Bắt đầu → nhập a, b → kiểm tra a = 0 → nếu a ≠ 0 thì x = −b/a và xuất x → nếu a = 0 thì kiểm tra b = 0 → nếu b = 0 thì phương trình có vô số nghiệm → nếu b ≠ 0 thì phương trình vô nghiệm → kết thúc.",
"metadata": {
"raw_text": "Giải phương trình ax + b = 0 bằng lưu đồ.\nCác bước chính: Bắt đầu → Nhập a, b → Kiểm tra a = 0 → Nếu a ≠ 0: x = −b/a → Xuất x → Kết thúc. Nếu a = 0: tiếp tục kiểm tra b = 0 → Nếu b = 0: Vô số nghiệm → Kết thúc. Nếu b ≠ 0: Vô nghiệm → Kết thúc.",
"diagram_text": "Bắt đầu → Nhập a, b → a = 0?\n ├── Sai: x = −b/a → Xuất x → Kết thúc\n └── Đúng: b = 0?\n ├── Đúng: Vô số nghiệm → Kết thúc\n └── Sai: Vô nghiệm → Kết thúc",
"has_diagram": true,
"image_path": "images/slide_8.png",
"page_number": 8,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_9",
"topic": "Các ví dụ thuật toán",
"type": "text",
"content_for_embedding": "Một số ví dụ về thuật toán gồm: Ví dụ 1: Vẽ lưu đồ thuật toán tính tổng các số nguyên dương lẻ từ 1 đến n. Ví dụ 2: Vẽ lưu đồ thuật toán liệt kê tất cả các ước số của số nguyên dương n. Extra: Vẽ lưu đồ thuật toán tìm nghiệm của phương trình bậc hai một ẩn.",
"metadata": {
"raw_text": "Một số ví dụ về thuật toán:\n• VD1: Vẽ lưu đồ thuật toán Tính tổng các số nguyên dương lẻ từ 1 đến n\n• VD2: Vẽ lưu đồ thuật toán Liệt kê tất cả các ước số của số nguyên dương n\n• Extra: Vẽ lưu đồ thuật toán Tìm nghiệm của phương trình bậc hai một ẩn",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_9.png",
"page_number": 9,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_10",
"topic": "VD1: Tính tổng các số nguyên dương lẻ từ 1 đến n",
"type": "flowchart",
"content_for_embedding": "Lưu đồ tính tổng các số nguyên dương lẻ từ 1 đến n: Bắt đầu → Đọc n → Khởi tạo S = 0 và i = 1 → kiểm tra i ≤ n → nếu đúng thì cộng S = S + i và tăng i = i + 2 → lặp lại cho đến khi i > n → khi sai, xuất S và kết thúc.",
"metadata": {
"raw_text": "VD1: Tổng các số nguyên dương lẻ từ 1 đến n.\nBắt đầu → Đọc n → S = 0, i = 1 → kiểm tra i ≤ n → nếu đúng: S = S + i, i = i + 2 → quay lại kiểm tra → nếu sai: Xuất S → Kết thúc.",
"diagram_text": "Bắt đầu → Đọc n → S = 0, i = 1 → i ≤ n?\n ├── Đúng: S = S + i → i = i + 2 → quay lại i ≤ n\n └── Sai: Xuất S → Kết thúc",
"has_diagram": true,
"image_path": "images/slide_10.png",
"page_number": 10,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_11",
"topic": "VD2: Liệt kê các ước số của n",
"type": "flowchart",
"content_for_embedding": "Lưu đồ liệt kê các ước số của n: Bắt đầu → Đọc n → i = 1 → kiểm tra i ≤ n → nếu đúng thì kiểm tra n % i = 0 → nếu đúng thì xuất i → tăng i = i + 1 → quay lại kiểm tra i ≤ n → nếu n % i ≠ 0 thì chỉ tăng i rồi quay lại. Khi i > n thì kết thúc.",
"metadata": {
"raw_text": "VD2: Liệt kê các ước số của n.\nBắt đầu → Đọc n → i = 1 → kiểm tra i ≤ n → nếu đúng: kiểm tra n % i = 0 → nếu đúng thì xuất i, tăng i = i + 1 → quay lại → nếu sai thì tăng i = i + 1 → quay lại → nếu i > n thì kết thúc.",
"diagram_text": "Bắt đầu → Đọc n → i = 1 → i ≤ n?\n ├── Đúng: n % i = 0?\n │ ├── Đúng: Xuất i → i = i + 1 → quay lại i ≤ n\n │ └── Sai: i = i + 1 → quay lại i ≤ n\n └── Sai: Kết thúc",
"has_diagram": true,
"image_path": "images/slide_11.png",
"page_number": 11,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán và lưu đồ"
},
{
"id": "slide_12",
"topic": "Kiểu dữ liệu cơ bản và phép toán",
"type": "title",
"content_for_embedding": "Kiểu dữ liệu cơ bản và các phép toán trong lập trình.",
"metadata": {
"raw_text": "Kiểu dữ liệu cơ bản và phép toán",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_12.png",
"page_number": 12,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_13",
"topic": "Kiểu số nguyên",
"type": "table",
"content_for_embedding": "Các kiểu số nguyên gồm: short (2 bytes, phạm vi -32.768 đến 32.767), unsigned short (2 bytes, 0 đến 65.535), int (4 bytes, -2.147.483.648 đến 2.147.483.647), unsigned int (4 bytes, 0 đến 4.294.967.295), long (4 bytes, -2.147.483.648 đến 2.147.483.647), unsigned long (4 bytes, 0 đến 4.294.967.295), long long (8 bytes, -9.223.372.036.854.775.807 đến 9.223.372.036.854.775.807), unsigned long long (8 bytes, 0 đến 18.446.744.073.709.551.615).",
"metadata": {
"raw_text": "Kiểu số nguyên:\nshort – 2 bytes – [-32.768, 32.767]\nunsigned short – 2 bytes – [0, 65.535]\nint – 4 bytes – [-2.147.483.648, 2.147.483.647]\nunsigned – 4 bytes – [0, 4.294.967.295]\nlong – 4 bytes – [-2.147.483.648, 2.147.483.647]\nunsigned long – 4 bytes – [0, 4.294.967.295]\nlong long – 8 bytes – [-9.223.372.036.854.775.807, 9.223.372.036.854.775.807]\nunsigned long long – 8 bytes – [0, 18.446.744.073.709.551.615]",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_13.png",
"page_number": 13,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_14",
"topic": "Kiểu số thực, ký tự và logic",
"type": "table",
"content_for_embedding": "Các kiểu dữ liệu cơ bản gồm: Kiểu số thực: float (4 bytes, phạm vi khoảng 3.4E−38 đến 3.4E+38, ~7 chữ số chính xác), double (8 bytes, 1.7E−308 đến 1.7E+308, ~15 chữ số), long double (8 bytes, phạm vi tương tự double). Kiểu ký tự: char (1 byte, giá trị trong [-128, 127] hoặc [0, 255]), unsigned char (1 byte, giá trị trong [0, 255]). Kiểu logic: bool (1 byte, false = 0, true = giá trị khác 0).",
"metadata": {
"raw_text": "Kiểu số thực:\nfloat – 4 bytes – [3.4E−38, 3.4E+38] (~7 chữ số)\ndouble – 8 bytes – [1.7E−308, 1.7E+308] (~15 chữ số)\nlong double – 8 bytes – [1.7E−308, 1.7E+308] (~15 chữ số)\n\nKiểu ký tự:\nchar – 1 byte – [-128, 127] hoặc [0, 255]\nunsigned char – 1 byte – [0, 255]\n\nKiểu logic:\nbool – 1 byte – false = giá trị 0, true = giá trị khác 0",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_14.png",
"page_number": 14,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_15",
"topic": "Các phép toán",
"type": "text",
"content_for_embedding": "Các phép toán trong lập trình bao gồm: toán tử gán, toán tử toán học, toán tử tăng giảm, toán tử toán học kết hợp với gán, toán tử quan hệ và toán tử luận lý.",
"metadata": {
"raw_text": "Các phép toán:\n• Toán tử gán\n• Toán tử toán học\n• Toán tử tăng giảm\n• Toán tử toán học và gán\n• Toán tử quan hệ\n• Toán tử luận lý",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_15.png",
"page_number": 15,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_16",
"topic": "Toán tử gán và toán tử toán học",
"type": "table",
"content_for_embedding": "Toán tử gán dùng để gán giá trị cho một biến. Ví dụ: int x = 10 gán giá trị 10 cho biến x; int y = x gán giá trị của biến x cho y. Các toán tử toán học gồm: cộng (+), trừ (-), nhân (*), chia (/), và chia lấy dư (%). Ví dụ: 10 + 20 = 30; 8 - 2 = 5; 7 * 5 = 35; 15 / 3 = 5; 27 % 5 = 2.",
"metadata": {
"raw_text": "Toán tử gán:\n- Dùng để gán giá trị cho 1 biến\n- Ví dụ:\n int x = 10; → Gán 10 cho biến x\n int y = x; → Gán giá trị của biến x cho biến y\n\nToán tử toán học:\n+ : Cộng hai toán hạng – 10 + 20 cho kết quả 30\n- : Trừ hai toán hạng – 8 - 2 cho kết quả 5\n* : Nhân hai toán hạng – 7 * 5 cho kết quả 35\n/ : Phép chia – 15 / 3 cho kết quả 5\n% : Phép chia lấy số dư – 27 % 5 cho kết quả 2",
"diagram_text": null,
"has_diagram": true,
"image_path": "images/slide_16.png",
"page_number": 16,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_17",
"topic": "Toán tử tăng giảm (++ và --)",
"type": "text",
"content_for_embedding": "Toán tử tăng giảm được dùng để tăng hoặc giảm giá trị của biến một đơn vị. Ví dụ tăng biến a lên 1: a = a + 1, a += 1, hoặc a++. Sự khác biệt giữa ++x và x++: ++x tăng giá trị trước rồi trả về giá trị mới; x++ trả về giá trị cũ rồi mới tăng. Ví dụ: int x = 5; int y = ++x; kết quả x = 6, y = 6. Với x++: int x = 5; int y = x++; kết quả x = 6, y = 5.",
"metadata": {
"raw_text": "Toán tử tăng giảm:\n• Dùng để tăng ++ hoặc giảm -- một đơn vị.\n• Ví dụ: để tăng giá trị biến a lên 1 đơn vị có thể dùng: a = a + 1; a += 1; a++.\n• Sự khác biệt giữa ++x và x++:\n\nVí dụ 1:\nint x = 5;\nint y = ++x;\n// x = 6, y = 6\n1. ++x → x = 6\n2. y = x → y = 6\n\nVí dụ 2:\nint x = 5;\nint y = x++;\n// x = 6, y = 5\n1. y = x → y = 5\n2. x++ → x = 6",
"diagram_text": "Tiền tố (++x): tăng giá trị rồi trả về giá trị mới. Hậu tố (x++): trả về giá trị cũ rồi mới tăng.",
"has_diagram": true,
"image_path": "images/slide_17.png",
"page_number": 17,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_18",
"topic": "Toán tử quan hệ",
"type": "table",
"content_for_embedding": "Các toán tử quan hệ gồm: == kiểm tra hai toán hạng bằng nhau; != kiểm tra hai toán hạng khác nhau; > kiểm tra toán hạng bên trái lớn hơn bên phải; < kiểm tra toán hạng bên trái nhỏ hơn bên phải; >= kiểm tra lớn hơn hoặc bằng; <= kiểm tra nhỏ hơn hoặc bằng. Ví dụ: 10 == 20 là false, 10 != 20 là true, 10 > 20 là false, 10 < 20 là true, 10 >= 20 là false, 10 <= 20 là true.",
"metadata": {
"raw_text": "Toán tử quan hệ:\n== : Kiểm tra nếu 2 toán hạng bằng nhau hay không. Nếu bằng thì kết quả là true. Ví dụ: 10 == 20 là false.\n!= : Kiểm tra 2 toán hạng có giá trị khác nhau hay không. Nếu khác thì kết quả là true. Ví dụ: 10 != 20 là true.\n> : Kiểm tra toán hạng bên trái có giá trị lớn hơn toán hạng bên phải hay không. Ví dụ: 10 > 20 là false.\n< : Kiểm tra toán hạng bên trái nhỏ hơn toán hạng bên phải hay không. Ví dụ: 10 < 20 là true.\n>= : Kiểm tra toán hạng bên trái lớn hơn hoặc bằng toán hạng bên phải. Ví dụ: 10 >= 20 là false.\n<= : Kiểm tra toán hạng bên trái nhỏ hơn hoặc bằng toán hạng bên phải. Ví dụ: 10 <= 20 là true.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_18.png",
"page_number": 18,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_19",
"topic": "Toán tử luận lý",
"type": "table",
"content_for_embedding": "Các toán tử luận lý gồm: && là toán tử AND, chỉ trả về true khi cả hai toán hạng đều true; || là toán tử OR, trả về true nếu một trong hai toán hạng là true; ! là toán tử NOT, đảo ngược giá trị logic của toán hạng. Ví dụ: (true && false) là false; (true || false) là true; !(true && false) là true.",
"metadata": {
"raw_text": "Toán tử luận lý:\n&& : Được gọi là toán tử logic AND (và). Nếu cả hai toán hạng đều có giá trị true thì kết quả là true. Ví dụ: (true && false) là false.\n|| : Được gọi là toán tử logic OR (hoặc). Nếu một trong hai toán hạng có giá trị true thì kết quả là true. Ví dụ: (true || false) là true.\n! : Được gọi là toán tử NOT (phủ định). Sử dụng để đảo ngược giá trị logic của toán hạng. Nếu toán hạng là true thì phủ định là false. Ví dụ: !(true && false) là true.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_19.png",
"page_number": 19,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu dữ liệu và toán tử"
},
{
"id": "slide_20",
"topic": "Cấu trúc điều khiển",
"type": "title",
"content_for_embedding": "Cấu trúc điều khiển trong lập trình: bao gồm cấu trúc rẽ nhánh và cấu trúc lặp.",
"metadata": {
"raw_text": "Cấu trúc điều khiển",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_20.png",
"page_number": 20,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_21",
"topic": "Các cấu trúc rẽ nhánh",
"type": "text",
"content_for_embedding": "Ba dạng cấu trúc rẽ nhánh trong lập trình gồm: cấu trúc rẽ nhánh if, cấu trúc rẽ nhánh if-else và cấu trúc rẽ nhánh switch-case.",
"metadata": {
"raw_text": "1. Cấu trúc rẽ nhánh if\n2. Cấu trúc rẽ nhánh if-else\n3. Cấu trúc rẽ nhánh switch-case",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_21.png",
"page_number": 21,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_22",
"topic": "Cấu trúc rẽ nhánh if",
"type": "flowchart",
"content_for_embedding": "Cấu trúc rẽ nhánh if gồm cú pháp: if (điều kiện) câu lệnh;. Lưu đồ hoạt động như sau: bắt đầu, kiểm tra điều kiện, nếu đúng thì thực hiện câu lệnh, nếu sai thì bỏ qua câu lệnh, sau đó kết thúc.",
"metadata": {
"raw_text": "Cấu trúc rẽ nhánh if:\nCú pháp: if (<điều kiện>) <câu lệnh>;\nLưu đồ: Điều kiện → Đúng: thực hiện câu lệnh; Sai: bỏ qua; sau đó đi đến kết thúc.",
"diagram_text": "Bắt đầu → Điều kiện?\n ├── Đúng: Thực hiện câu lệnh → Kết thúc\n └── Sai: Bỏ qua câu lệnh → Kết thúc",
"has_diagram": true,
"image_path": "images/slide_22.png",
"page_number": 22,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_23",
"topic": "Ví dụ if: Tìm giá trị lớn nhất trong ba số",
"type": "code",
"content_for_embedding": "Ví dụ sử dụng cấu trúc rẽ nhánh if để tìm giá trị lớn nhất trong ba số a, b, c. Ý tưởng: gán giá trị của a vào m, sau đó so sánh lần lượt với b và c; nếu b > m thì m = b; nếu c > m thì m = c. Cuối cùng xuất m. Code minh họa bằng C++.",
"metadata": {
"raw_text": "VD1: Viết chương trình tìm giá trị lớn nhất trong ba số a, b, c cho trước.\nÝ tưởng: gán giá trị a vào m → so sánh m lần lượt với b và c. Nếu m nhỏ hơn thì gán giá trị đó vào m → Xuất m.\nCode:\n#include <iostream>\nusing namespace std;\nint main() {\n int m, a, b, c;\n cout << \"Nhap cac gia tri a, b, c \"; cin >> a >> b >> c;\n m = a;\n if (m < b) m = b;\n if (m < c) m = c;\n cout << \"Gia tri lon nhat la: \" << m;\n return 0;\n}",
"diagram_text": "Thuật toán: m = a → so sánh m với b → nếu b lớn hơn thì m = b → so sánh m với c → nếu c lớn hơn thì m = c → xuất m.",
"has_diagram": false,
"image_path": "images/slide_23.png",
"page_number": 23,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_24",
"topic": "Ví dụ if: Kiểm tra số chẵn lẻ",
"type": "code",
"content_for_embedding": "Ví dụ sử dụng cấu trúc rẽ nhánh if để kiểm tra số nguyên n là chẵn hay lẻ. Ý tưởng: lấy phần dư n % 2; nếu bằng 0 thì n là số chẵn, nếu khác 0 thì n là số lẻ. Code minh họa bằng C++.",
"metadata": {
"raw_text": "VD2: Viết chương trình kiểm tra tính chẵn lẻ của một số nguyên n.\nÝ tưởng: chia lấy phần dư n cho 2. Nếu bằng 0 là số chẵn, khác 0 là số lẻ.\nCode:\n#include <iostream>\nusing namespace std;\nint main()\n{\n int n;\n cout << \"Nhap so nguyen n: \"; cin >> n;\n if (n % 2 == 0) cout << n << \" la so chan\" << endl;\n if (n % 2 != 0) cout << n << \" la so le\";\n return 0;\n}",
"diagram_text": "Thuật toán: Nhập n → kiểm tra n % 2 == 0 → nếu đúng: n là số chẵn → nếu sai: n là số lẻ.",
"has_diagram": false,
"image_path": "images/slide_24.png",
"page_number": 24,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_25",
"topic": "Cấu trúc rẽ nhánh if-else",
"type": "flowchart",
"content_for_embedding": "Cấu trúc rẽ nhánh if-else gồm cú pháp: if (điều kiện) câu lệnh 1; else câu lệnh 2;. Lưu đồ: bắt đầu, kiểm tra điều kiện, nếu đúng thì thực hiện câu lệnh 1, nếu sai thì thực hiện câu lệnh 2, sau đó kết thúc.",
"metadata": {
"raw_text": "Cấu trúc rẽ nhánh if-else:\nCú pháp:\nif (<điều kiện>) <câu lệnh 1>;\nelse <câu lệnh 2>;\nLưu đồ: Điều kiện → Đúng: Câu lệnh 1 → Kết thúc; Sai: Câu lệnh 2 → Kết thúc.",
"diagram_text": "Bắt đầu → Điều kiện?\n ├── Đúng: Thực hiện câu lệnh 1 → Kết thúc\n └── Sai: Thực hiện câu lệnh 2 → Kết thúc",
"has_diagram": true,
"image_path": "images/slide_25.png",
"page_number": 25,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_26",
"topic": "Ví dụ if-else: Tính điểm trung bình và kiểm tra đậu/rớt",
"type": "code",
"content_for_embedding": "Ví dụ sử dụng cấu trúc rẽ nhánh if-else để tính điểm trung bình ba môn và kiểm tra sinh viên đậu hay không. Ý tưởng: tính dtb = (a + b + c) / 3; nếu dtb < 5 thì không đậu, ngược lại thì đậu. Đoạn code minh họa viết bằng C++.",
"metadata": {
"raw_text": "VD: Nhập điểm ba môn học. Tính điểm trung bình và kiểm tra đậu hay không đậu.\nÝ tưởng: Tính dtb → Nếu nhỏ hơn 5 → không đậu, ngược lại → đậu.\nCode:\n#include <iostream>\nusing namespace std;\nint main()\n{\n int a, b, c, dtb;\n cout << \"Nhap diem 3 mon hoc: \";\n cin >> a >> b >> c;\n dtb = (a + b + c) / 3;\n if (dtb < 5) cout << \"Bai thi khong dau\";\n else cout << \"Bai thi dau\";\n return 0;\n}",
"diagram_text": "Thuật toán: Nhập điểm a, b, c → tính dtb = (a + b + c) / 3 → kiểm tra dtb < 5 → nếu đúng: không đậu → nếu sai: đậu.",
"has_diagram": false,
"image_path": "images/slide_26.png",
"page_number": 26,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_27",
"topic": "Ví dụ if lồng nhau: kiểm tra tam giác và tam giác vuông",
"type": "text",
"content_for_embedding": "Ví dụ về câu lệnh if lồng nhau: nhập vào ba số nguyên và kiểm tra xem ba số đó có thể tạo thành các cạnh của một tam giác hay không, bằng điều kiện tổng hai cạnh bất kỳ lớn hơn cạnh còn lại. Nếu là tam giác, tiếp tục kiểm tra có phải tam giác vuông không bằng điều kiện tổng bình phương hai cạnh bằng bình phương cạnh còn lại.",
"metadata": {
"raw_text": "VD: Viết chương trình nhập vào 3 số nguyên, kiểm tra xem 3 số đó có tạo thành ba cạnh của một tam giác vuông hay không.\nÝ tưởng:\n- Nhập 3 số nguyên\n- Kiểm tra 3 số nguyên có tạo thành một tam giác hay không (Tổng 2 cạnh bất kì lớn hơn cạnh còn lại)\n- Nếu tạo thành một tam giác thì 3 số nguyên có tạo thành một tam giác vuông không (Tổng bình phương 2 cạnh bất kì bằng bình phương cạnh còn lại)",
"diagram_text": "Thuật toán: Nhập a, b, c → kiểm tra điều kiện tam giác: a + b > c, a + c > b, b + c > a → nếu đúng: kiểm tra tam giác vuông bằng a² + b² = c² hoặc tương đương các hoán vị → kết luận.",
"has_diagram": false,
"image_path": "images/slide_27.png",
"page_number": 27,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_28",
"topic": "Code ví dụ if lồng nhau: kiểm tra tam giác và tam giác vuông",
"type": "code",
"content_for_embedding": "Ví dụ sử dụng if lồng nhau để kiểm tra ba số a, b, c có tạo thành tam giác hay không bằng điều kiện a + b > c, a + c > b và b + c > a. Nếu là tam giác, tiếp tục kiểm tra tam giác vuông bằng cách so sánh bình phương các cạnh: a^2 + b^2 = c^2 hoặc các hoán vị tương đương. Code minh họa viết bằng C++.",
"metadata": {
"raw_text": "VD: Viết chương trình nhập vào 3 số nguyên, kiểm tra xem 3 số đó có tạo thành ba cạnh của một tam giác vuông hay không.\nCode:\n#include <iostream>\nusing namespace std;\nint main()\n{\n double a, b, c;\n cout << \"Nhap 3 so: \"; cin >> a >> b >> c;\n if ((a + b > c) && (a + c > b) && (b + c > a))\n if ((a * a + b * b == c * c) || (a * a + c * c == b * b) || (b * b + c * c == a * a))\n cout << \"3 so tao thanh tam giac vuong\";\n else\n cout << \"3 so khong tao thanh tam giac vuong\";\n else\n cout << \"3 so khong tao thanh tam giac\";\n return 0;\n}",
"diagram_text": "Thuật toán: Nhập a, b, c → kiểm tra điều kiện tam giác → nếu đúng: kiểm tra tam giác vuông bằng a² + b² = c² hoặc các hoán vị → in kết quả → nếu không phải tam giác → thông báo không hợp lệ.",
"has_diagram": false,
"image_path": "images/slide_28.png",
"page_number": 28,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_29",
"topic": "Cấu trúc switch-case",
"type": "text",
"content_for_embedding": "Cấu trúc switch-case được dùng để so sánh một biểu thức với nhiều giá trị. Mỗi case ứng với một giá trị cụ thể và chứa câu lệnh tương ứng. Nếu không khớp với bất kỳ case nào thì thực hiện nhánh default. Mỗi case thường kết thúc bằng break để tránh rơi xuống case tiếp theo.",
"metadata": {
"raw_text": "Cấu trúc switch case:\nCú pháp:\nswitch (<biểu thức điều kiện>)\n{\n case <giá trị 1>: <câu lệnh 1>; break;\n case <giá trị 2>: <câu lệnh 2>; break;\n …………\n case <giá trị n>: <câu lệnh n>; break;\n default:\n <câu lệnh mặc định>;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_29.png",
"page_number": 29,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_30",
"topic": "Ví dụ switch-case: đọc số từ 0 đến 9",
"type": "code",
"content_for_embedding": "Ví dụ sử dụng cấu trúc switch-case để đọc số nguyên n và hiển thị cách đọc của các số từ 0 đến 9. Nếu n không thuộc khoảng 0 đến 9 thì in ra 'Khong doc duoc'. Mỗi case tương ứng một cách đọc số. Code minh họa bằng C++.",
"metadata": {
"raw_text": "VD: Nhập số nguyên. Hiển thị cách đọc số đó có giá trị từ 0 đến 9. Nếu không thì xuất 'Không đọc được'.\nCode:\n#include <iostream>\nusing namespace std;\nint main()\n{\n int n;\n cout << \"Nhap so nguyen n: \"; cin >> n;\n switch (n)\n {\n case 0: cout << \" khong\"; break;\n case 1: cout << \" Mot\"; break;\n case 2: cout << \" Hai\"; break;\n case 3: cout << \" Ba\"; break;\n case 4: cout << \" Bon\"; break;\n case 5: cout << \" Nam\"; break;\n case 6: cout << \" Sau\"; break;\n case 7: cout << \" Bay\"; break;\n case 8: cout << \" Tam\"; break;\n case 9: cout << \" Chin\"; break;\n default: cout << \"Khong doc duoc\";\n }\n return 0;\n}",
"diagram_text": "Thuật toán: Nhập n → dùng switch để so sánh n với các giá trị từ 0 đến 9 → nếu khớp, in cách đọc tương ứng → nếu không khớp, in 'Không đọc được'.",
"has_diagram": false,
"image_path": "images/slide_30.png",
"page_number": 30,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển"
},
{
"id": "slide_31",
"topic": "Cấu trúc lặp",
"type": "title",
"content_for_embedding": "Cấu trúc lặp trong lập trình bao gồm các dạng lặp như while, do-while và for, dùng để thực hiện lặp lại một khối lệnh cho đến khi điều kiện dừng được thỏa mãn.",
"metadata": {
"raw_text": "Cấu trúc lặp",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_31.png",
"page_number": 31,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_32",
"topic": "Vòng lặp for",
"type": "text",
"content_for_embedding": "Vòng lặp for có cú pháp: for (khởi tạo; điều kiện; bước nhảy) câu lệnh;. Khởi tạo dùng để tạo biến đếm, điều kiện quyết định việc tiếp tục lặp, và bước nhảy thay đổi giá trị biến đếm mỗi vòng. Cả ba phần có thể có hoặc không. Câu lệnh trong vòng lặp được thực hiện khi điều kiện đúng.",
"metadata": {
"raw_text": "1. Vòng lặp for\nCú pháp:\nfor ([khởi tạo]; [điều kiện]; [bước nhảy]) <câu lệnh>;\nTrong đó:\n- [khởi tạo] là phần để khởi tạo biến đếm. Biến đếm có thể khai báo ngay trong phần khởi tạo. Phần này chỉ chạy một lần duy nhất khi bắt đầu vòng lặp.\n- [điều kiện] là điều kiện của vòng lặp. Khi điều kiện sai thì kết thúc vòng lặp.\n- [bước nhảy] phần này được thực thi ở cuối vòng lặp. Thường dùng để tăng hoặc giảm giá trị biến đếm.\n- <câu lệnh> được thực hiện khi điều kiện đúng.\nCác phần [khởi tạo], [điều kiện], [bước nhảy] có thể có nhiều biến, nhiều biểu thức. Những phần này có thể có hoặc không.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_32.png",
"page_number": 32,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_33",
"topic": "Vòng lặp while",
"type": "text",
"content_for_embedding": "Vòng lặp while thực hiện lặp lại một câu lệnh khi điều kiện còn đúng. Điều kiện thường là biểu thức quan hệ trả về true hoặc false. Khi điều kiện trở thành false thì vòng lặp dừng.",
"metadata": {
"raw_text": "2. Vòng lặp while\nCú pháp:\nwhile (<điều kiện>)\n <câu lệnh>;\nTrong đó:\n• <điều kiện> thường là biểu thức quan hệ, trả về kết quả true hoặc false.\n• <câu lệnh> là câu lệnh được lặp lại cho đến khi điều kiện sai (false).",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_33.png",
"page_number": 33,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_34",
"topic": "Vòng lặp do-while",
"type": "text",
"content_for_embedding": "Vòng lặp do-while thực hiện câu lệnh trước rồi mới kiểm tra điều kiện. Vòng lặp luôn chạy ít nhất một lần. Khi điều kiện còn đúng thì tiếp tục lặp lại khối lệnh.",
"metadata": {
"raw_text": "3. Vòng lặp do while\nCú pháp:\ndo {\n <câu lệnh>;\n} while (<điều kiện>);\nTrong đó:\n• <câu lệnh> là lệnh được thực thi trong vòng lặp.\n• <điều kiện> là điều kiện của vòng lặp.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_34.png",
"page_number": 34,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_35",
"topic": "Ví dụ vòng lặp: Tính tổng số nguyên dương chẵn nhỏ hơn N",
"type": "text",
"content_for_embedding": "Ví dụ sử dụng vòng lặp để tính tổng các số nguyên dương chẵn nhỏ hơn N. Ý tưởng: duyệt qua các số từ 1 đến N-1, kiểm tra số đó có chia hết cho 2 hay không, nếu có thì cộng vào tổng.",
"metadata": {
"raw_text": "Ví dụ 1: Viết chương trình tính tổng các số nguyên dương chẵn nhỏ hơn N. Với N nhập từ bàn phím.\nÝ tưởng:\n- Tìm các số dương nhỏ hơn n\n- Các số này chia hết cho 2 không?\n>> Tính tổng nếu có",
"diagram_text": "Thuật toán: Nhập N → khởi tạo tổng S = 0 → lặp i từ 1 đến N-1 → nếu i % 2 == 0 thì S = S + i → kết thúc lặp → in S.",
"has_diagram": false,
"image_path": "images/slide_35.png",
"page_number": 35,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_36",
"topic": "Lưu đồ: Tính tổng số nguyên dương chẵn nhỏ hơn N",
"type": "flowchart",
"content_for_embedding": "Lưu đồ mô tả thuật toán tính tổng các số nguyên dương chẵn nhỏ hơn N. Thuật toán: nhập N, khởi tạo i = 0 và Tong = 0, lặp khi i < N. Nếu i là số chẵn thì cộng vào Tong, sau đó tăng i. Khi điều kiện i < N sai thì xuất Tong và kết thúc.",
"metadata": {
"raw_text": "Lưu đồ gồm các bước: Bắt đầu → Nhập n → i = 0, Tong = 0 → kiểm tra i < n → nếu False: Xuất Tong và kết thúc → nếu True: kiểm tra i % 2 == 0 → nếu True: Tong = Tong + i → i++ → quay lại kiểm tra i < n.",
"diagram_text": "Bắt đầu → Nhập n → i = 0, Tong = 0 → kiểm tra i < n?\n ├── False: Xuất Tong → Kết thúc\n └── True: kiểm tra i % 2 == 0?\n ├── True: Tong = Tong + i\n └── False: bỏ qua\n → i++ → quay lại kiểm tra i < n",
"has_diagram": true,
"image_path": "images/slide_36.png",
"page_number": 36,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_37",
"topic": "Hai cách viết vòng lặp tính tổng số chẵn nhỏ hơn N",
"type": "code",
"content_for_embedding": "Có hai cách viết chương trình tính tổng các số nguyên dương chẵn nhỏ hơn N. Cách 1: duyệt i từ 1 đến N-1 và kiểm tra i % 2 == 0 để cộng vào tổng. Cách 2: duyệt trực tiếp các số chẵn bằng vòng lặp for từ i = 2 đến N-1 với bước nhảy i += 2, sau đó cộng các giá trị vào tổng. Cả hai chương trình đều xuất ra tổng các số chẵn nhỏ hơn N.",
"metadata": {
"raw_text": "Code 1:\n#include <iostream>\nusing namespace std;\nint main() {\n int n; cin >> n;\n int sum = 0;\n for (int i = 1; i < n; i++) {\n if (i % 2 == 0)\n sum = sum + i;\n }\n cout << sum;\n return 0;\n}\n\nCode 2:\n#include <iostream>\nusing namespace std;\nint main() {\n int N; cin >> N;\n int sum = 0;\n for (int i = 2; i < N; i += 2)\n sum += i;\n cout << sum << endl;\n return 0;\n}",
"diagram_text": "Thuật toán 1: duyệt i từ 1 đến N-1 → nếu i chẵn thì cộng sum. Thuật toán 2: duyệt trực tiếp i = 2, 4, 6,… < N → cộng sum.",
"has_diagram": false,
"image_path": "images/slide_37.png",
"page_number": 37,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấu trúc điều khiển – Cấu trúc lặp"
},
{
"id": "slide_38",
"topic": "Hàm",
"type": "title",
"content_for_embedding": "Chương 4 giới thiệu về hàm trong lập trình: khai báo hàm, định nghĩa hàm, tham số, giá trị trả về và cách sử dụng hàm để tổ chức chương trình.",
"metadata": {
"raw_text": "4. Hàm",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_38.png",
"page_number": 38,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Hàm"
},
{
"id": "slide_39",
"topic": "So sánh sử dụng hàm và không sử dụng hàm",
"type": "code",
"content_for_embedding": "Ví dụ so sánh chương trình không sử dụng hàm với chương trình sử dụng hàm. Không dùng hàm khiến việc nhập dữ liệu lặp lại nhiều lần. Khi dùng hàm, tạo một hàm nhap_so_duong để nhập một số nguyên dương, giúp tái sử dụng, giảm trùng lặp và mã nguồn gọn gàng hơn.",
"metadata": {
"raw_text": "Không sử dụng hàm:\nint a, b, c, d;\ndo {\n cout << \"Nhap mot so nguyen duong\";\n cin >> a;\n} while (a <= 0);\ndo {\n cout << \"Nhap mot so nguyen duong\";\n cin >> b;\n} while (b <= 0);\ndo {\n cout << \"Nhap mot so nguyen duong\";\n cin >> c;\n} while (c <= 0);\ndo {\n cout << \"Nhap mot so nguyen duong\";\n cin >> d;\n} while (d <= 0);\n\nCó sử dụng hàm:\nint nhap_so_duong(){\n int n;\n do {\n cout << \"Nhap mot so nguyen duong\";\n cin >> n;\n } while (n <= 0);\n return n;\n}\n\na = nhap_so_duong();\nb = nhap_so_duong();\nc = nhap_so_duong();\nd = nhap_so_duong();",
"diagram_text": "So sánh logic: Không dùng hàm → lặp lại cùng một đoạn mã nhập số dương cho a, b, c, d. Dùng hàm → gom đoạn mã nhập số dương vào một hàm nhap_so_duong(), sau đó gọi lại nhiều lần.",
"has_diagram": false,
"image_path": "images/slide_39.png",
"page_number": 39,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Hàm"
},
{
"id": "slide_40",
"topic": "Khái niệm hàm",
"type": "text",
"content_for_embedding": "Hàm là một đoạn chương trình có tên, có đầu vào và đầu ra, dùng để giải quyết một nhiệm vụ cụ thể. Hàm có thể được gọi nhiều lần với các đối số khác nhau và giúp tái sử dụng mã, sửa lỗi và cải tiến dễ dàng hơn.",
"metadata": {
"raw_text": "Khái niệm hàm:\nMột đoạn chương trình có tên, đầu vào và đầu ra.\nCó chức năng giải quyết một số vấn đề chuyên biệt cho chương trình chính.\nCó thể được gọi nhiều lần với các đối số khác nhau.\nĐược sử dụng khi có nhu cầu:\n• Tái sử dụng.\n• Sửa lỗi và cải tiến.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_40.png",
"page_number": 40,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Hàm"
},
{
"id": "slide_41",
"topic": "Cú pháp của hàm",
"type": "text",
"content_for_embedding": "Cú pháp khai báo hàm trong C++ gồm: kiểu trả về, tên hàm và danh sách tham số. Phần thân hàm chứa các câu lệnh và lệnh return để trả về giá trị nếu hàm có kiểu trả về khác void. Tên hàm tuân theo quy tắc định danh, tham số là các biến đầu vào được khai báo trong ngoặc đơn và cách nhau bằng dấu phẩy.",
"metadata": {
"raw_text": "Cú pháp: <kiểu_trả_về> <tên_hàm>([danh sách tham số]) {\n <các câu lệnh>\n return <giá_trị_trả_về>;\n}\nTrong đó:\n• <kiểu trả về>: kiểu dữ liệu bất kỳ của C++ (char, int, long, float,...). Đặc biệt nếu hàm không trả về thì dùng kiểu void.\n• <tên hàm>: theo quy tắc đặt tên định danh.\n• <danh sách tham số>: tham số hình thức đầu vào giống khai báo biến, cách nhau bằng dấu ','.\n• <giá trị>: trả về cho hàm qua lệnh return. Nếu kiểu trả về là void thì không có lệnh này.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_41.png",
"page_number": 41,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Hàm"
},
{
"id": "slide_42",
"topic": "Ví dụ về hàm trong C++",
"type": "code",
"content_for_embedding": "Ví dụ về một hàm C++ có kiểu trả về int, tên hàm nhap_so_duong. Hàm yêu cầu người dùng nhập một số nguyên dương, kiểm tra bằng vòng lặp do-while và trả về giá trị hợp lệ qua lệnh return.",
"metadata": {
"raw_text": "int nhap_so_duong() {\n int n;\n do {\n cout << \"Nhap mot so nguyen duong\";\n cin >> n;\n } while (n <= 0);\n return n;\n}\nGiải thích:\n<int>: Kiểu dữ liệu trả về\n<nhap_so_duong>: Tên hàm\n<return n>: Giá trị trả về qua biến n",
"code_block": "int nhap_so_duong(){\n int n;\n do {\n cout << \"Nhap mot so nguyen duong\";\n cin >> n;\n } while (n <= 0);\n return n;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_42.png",
"page_number": 42,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Hàm"
},
{
"id": "slide_43",
"topic": "Tham số hàm",
"type": "text",
"content_for_embedding": "Tham số hàm trong C++ gồm tham trị và tham chiếu. Tham trị tạo ra một bản sao của biến nên việc thay đổi trong hàm không ảnh hưởng biến gốc. Tham chiếu dùng toán tử & để liên kết trực tiếp với biến gốc, mọi thay đổi trong hàm đều ảnh hưởng giá trị bên ngoài.",
"metadata": {
"raw_text": "Tham chiếu:\n- Khai báo hàm sử dụng tham số dưới dạng tham chiếu bằng cách thêm dấu & vào trước tham số đó.\n- Khi một biến a được truyền vào lời gọi hàm (int &x) làm tham số dưới dạng tham chiếu, thì biến x của hàm (int &x) và biến a thực chất là một. Do đó, nếu hàm thay đổi giá trị của x trong hàm thì đồng nghĩa biến a cũng bị thay đổi theo.\n\nTham trị:\n- Khi một biến a được truyền vào lời gọi hàm (int x) làm tham số dưới dạng tham trị, thì biến x của hàm (int x) và biến a là hai biến độc lập. Vì là tham trị, hàm sẽ tạo ra bản sao của biến và sao chép giá trị của a vào x. Do đó, nếu hàm thay đổi giá trị của x, biến a không thay đổi.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_43.png",
"page_number": 43,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Hàm"
},
{
"id": "slide_44",
"topic": "Tham số hàm (tham trị và tham chiếu)",
"type": "code",
"content_for_embedding": "Ví dụ minh họa hàm sử dụng tham trị cho các biến x, y và tham chiếu cho biến thuong. Hàm phep_chia kiểm tra y có bằng 0 hay không. Nếu hợp lệ, hàm gán kết quả phép chia vào tham chiếu thuong và trả về true. Nếu không thể chia, hàm trả về false. main() gọi hàm và xuất kết quả.",
"metadata": {
"raw_text": "bool phep_chia(int x, int y, double& thuong){\n if (y != 0) {\n thuong = double(x)/y;\n return true;\n } else {\n return false;\n }\n}\n\nint main(){\n double thuong;\n if (phep_chia(5, 3, thuong)){\n cout << \"Thuong so la \" << thuong;\n } else {\n cout << \"Khong the chia duoc\";\n }\n}",
"code_block": "bool phep_chia(int x, int y, double& thuong){\n if (y != 0) {\n thuong = double(x)/y;\n return true;\n } else {\n return false;\n }\n}\n\nint main(){\n double thuong;\n if (phep_chia(5, 3, thuong)){\n cout << \"Thuong so la \" << thuong;\n } else {\n cout << \"Khong the chia duoc\";\n }\n}",
"diagram_text": "Ghi chú: x, y là tham trị; thuong là tham chiếu.",
"has_diagram": false,
"image_path": "images/slide_44.png",
"page_number": 44,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Hàm"
},
{
"id": "slide_45",
"topic": "Bài tập về hàm",
"type": "code",
"content_for_embedding": "Bài tập yêu cầu kiểm tra chương trình C++ có lỗi hay không và xác định kết quả chạy. Hàm find nhận tham trị các biến a, b, c nên các thay đổi trong hàm không ảnh hưởng đến biến trong main. Do thứ tự truyền vào là find(three, two, one) nên a=15, b=10, c=5 trong hàm. Sau tính toán, giá trị one, two, three vẫn giữ nguyên.",
"metadata": {
"raw_text": "- Kiểm tra xem chương trình này có lỗi không? Hãy sửa lại, nếu có.\n- Kết quả sau khi thực thi là gì?\n\n#include <iostream>\nusing namespace std;\n\nvoid find(int a, int& b, int& c)\n{\n int temp;\n c = a + b;\n temp = a;\n a = b;\n b = 2 * temp;\n}\n\nint main()\n{\n int one, two, three;\n one = 5;\n two = 10;\n three = 15;\n\n find(three, two, one);\n cout << one << \", \" << two << \", \" << three << endl;\n\n return 0;\n}",
"code_block": "void find(int a, int& b, int& c){\n int temp;\n c = a + b;\n temp = a;\n a = b;\n b = 2 * temp;\n}\n\nint main(){\n int one = 5, two = 10, three = 15;\n find(three, two, one);\n cout << one << \", \" << two << \", \" << three;\n}",
"analysis": "Hàm find sử dụng tham trị cho a nên a trong main không đổi. Nhưng b và c là tham chiếu (theo bản sửa đúng), nên two và one bị thay đổi. Với a=three=15, b=two=10, c=one=5 → c = 15+10 = 25; b = 2*15 = 30. Kết quả in ra: one = 25, two = 30, three = 15.",
"has_diagram": false,
"image_path": "images/slide_45.png",
"page_number": 45,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Hàm"
},
{
"id": "slide_46",
"topic": "Bài tập về hàm – Kiểm tra số nguyên tố",
"type": "code",
"content_for_embedding": "Bài tập yêu cầu kiểm tra đoạn code có đúng không. Hàm kiem_tra được viết sai vì dùng void nhưng lại cố cout giá trị true/false và main cũng cout kết quả hàm. Hàm cần trả về bool. Vòng lặp kiểm tra điều kiện n % i == 0 phải trả về false ngay lập tức. Nếu lặp xong không chia hết thì trả về true.",
"metadata": {
"raw_text": "Đoạn chương trình bên có đúng không? Nếu sai, thì phải sửa lại ở những điểm nào?\n\n#include <iostream>\nint n;\nusing namespace std;\n\nvoid kiem_tra(int n) {\n for (int i = 2; i <= sqrt(n); i++)\n if (n % i == 0) cout << false;\n cout << true;\n}\n\nint main() {\n cin >> n;\n cout << kiem_tra(n);\n return 0;\n}",
"code_block": "#include <iostream>\nusing namespace std;\n\nbool kiem_tra(int n) {\n if (n < 2) return false;\n for (int i = 2; i <= sqrt(n); i++){\n if (n % i == 0) return false;\n }\n return true;\n}\n\nint main(){\n int n;\n cin >> n;\n cout << kiem_tra(n);\n return 0;\n}",
"analysis": "Sai vì: 1) Hàm kiem_tra khai báo void nhưng main lại cout kiem_tra(n). 2) Hàm cout false bên trong vòng lặp nhưng vẫn tiếp tục chạy. 3) Sau khi cout true ở cuối sẽ luôn in true dù n không phải số nguyên tố. 4) Cần đổi hàm sang bool và dùng return thay cho cout. 5) Cần xử lý n < 2.",
"has_diagram": false,
"image_path": "images/slide_46.png",
"page_number": 46,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Hàm"
},
{
"id": "slide_47",
"topic": "Bài tập về hàm – Sửa lỗi chương trình kiểm tra số nguyên tố",
"type": "code",
"content_for_embedding": "Slide minh họa quá trình sửa lỗi hàm kiểm tra số nguyên tố trong C++. Chương trình ban đầu dùng void và cout để trả về true hoặc false, điều này sai vì main cần nhận giá trị trả về. Chương trình đúng cần đổi hàm sang bool, dùng return false khi n chia hết cho i và return true khi vượt qua vòng lặp. Cần thêm thư viện cmath để dùng sqrt.",
"metadata": {
"raw_text": "#include <iostream>\nint n;\nusing namespace std;\nvoid kiem_tra(int n) {\n for (int i = 2; i <= sqrt(n); i++)\n if (n % i == 0) cout << false;\n cout << true;\n}\nint main() {\n cin >> n;\n cout << kiem_tra(n);\n return 0;\n}\n\n→ Chương trình đúng:\n\n#include <iostream>\n#include <cmath>\nint n;\nusing namespace std;\nbool kiem_tra(int n) {\n for (int i = 2; i <= sqrt(n); i++)\n if (n % i == 0) return false;\n return true;\n}\nint main() {\n cin >> n;\n cout << kiem_tra(n);\n return 0;\n}",
"code_block": "// Bản đúng\n#include <iostream>\n#include <cmath>\nusing namespace std;\n\nbool kiem_tra(int n){\n for (int i = 2; i <= sqrt(n); i++){\n if (n % i == 0) return false;\n }\n return true;\n}\n\nint main(){\n int n;\n cin >> n;\n cout << kiem_tra(n);\n return 0;\n}",
"analysis": "Slide cho thấy quá trình sửa lỗi: 1) hàm phải trả về bool, không phải void. 2) không dùng cout trong hàm logic. 3) cần return ngay khi phát hiện n không phải số nguyên tố. 4) thêm thư viện <cmath> cho sqrt(). 5) main in trực tiếp giá trị boolean.",
"has_diagram": true,
"diagram_text": "Mũi tên thể hiện chuyển từ phiên bản sai sang phiên bản đúng.",
"image_path": "images/slide_47.png",
"page_number": 47,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Hàm"
},
{
"id": "slide_48",
"topic": "Giải đề thi minh họa – Câu 1",
"type": "code",
"content_for_embedding": "Bài toán yêu cầu xác định giá trị của x và y sau khi gọi hàm hamf(x, y). Tham số x được truyền theo tham trị nên thay đổi trong hàm không ảnh hưởng biến x trong main. Tham số y truyền theo tham chiếu nên mọi thay đổi của y trong hàm sẽ ảnh hưởng ra ngoài. Với x=2 và y=1: trong hàm, x = x * y = 2; y = x / y = 2; x = x / y = 1. Kết thúc hàm: giá trị x trong main vẫn bằng 2, còn y trở thành 2.",
"metadata": {
"raw_text": "Câu 1. Bạn hãy cho biết giá trị của x và y sau khi thực thi đoạn chương trình này.\n\n#include <iostream>\nusing namespace std;\n\nvoid hamf(int x, int &y)\n{\n x = x * y;\n y = x / y;\n x = x / y;\n}\n\nint main()\n{\n int x = 2, y = 1;\n hamf(x, y);\n cout << \"x = \" << x << \"\\t\";\n cout << \"y = \" << y;\n return 0;\n}",
"code_block": "void hamf(int x, int &y){\n x = x * y;\n y = x / y;\n x = x / y;\n}\n\nint main(){\n int x = 2, y = 1;\n hamf(x, y);\n cout << \"x = \" << x << \"\\t\";\n cout << \"y = \" << y;\n return 0;\n}",
"analysis": "Do x là tham trị nên không thay đổi trong main. y là tham chiếu nên thay đổi. Với x=2, y=1: trong hàm, bước 1: x=2*1=2; bước 2: y=2/1=2; bước 3: x=2/2=1. Kết quả trả ra: x(main)=2, y(main)=2.",
"has_diagram": false,
"image_path": "images/slide_48.png",
"page_number": 48,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Hàm"
},
{
"id": "slide_49",
"topic": "Giải đề thi minh họa – Câu 2",
"type": "code",
"content_for_embedding": "Chương trình tính tổng tong của các lũy thừa x^i với i chạy từ 0 đến 2*n và chỉ cộng các số mũ chẵn. Giá trị tong là tổng các pow(x, i) với i chẵn. Người dùng nhập n và x.",
"metadata": {
"raw_text": "Câu 2. Bạn hãy cho biết giá trị của tong sau khi thực thi đoạn chương trình này.\n\n#include <iostream>\n#include <cmath>\nusing namespace std;\n\nint main()\n{\n int n, x; cin >> n >> x;\n double tong = 0;\n\n for (int i = 0; i <= 2 * n; i++)\n if (i % 2 == 0) tong = tong + pow(x, i);\n\n cout << tong;\n return 0;\n}",
"code_block": "int n, x; cin >> n >> x;\ndouble tong = 0;\nfor (int i = 0; i <= 2*n; i++)\n if (i % 2 == 0) tong += pow(x, i);\ncout << tong;",
"analysis": "Chương trình cộng tất cả các lũy thừa chẵn của x: x^0 + x^2 + x^4 + ... + x^(2n). Đây là tổng cấp số nhân dạng sum(x^(2k), k=0..n). Với x=1 → tong = n+1. Với x khác 1 → tong = (x^(2(n+1)) - 1) / (x^2 - 1).",
"has_diagram": false,
"image_path": "images/slide_49.png",
"page_number": 49,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Hàm"
},
{
"id": "slide_50",
"topic": "Giải đề thi minh họa – Câu 3",
"type": "diagram",
"content_for_embedding": "Lưu đồ biểu diễn thuật toán giải phương trình bậc nhất ax + b = 0. Nếu a ≠ 0, nghiệm là x = -b/a. Nếu a = 0 và b = 0, phương trình có vô số nghiệm. Nếu a = 0 và b ≠ 0, phương trình vô nghiệm. Bài yêu cầu kiểm tra lưu đồ có đầy đủ không và tính kết quả với các cặp giá trị a, b.",
"metadata": {
"raw_text": "Câu 3.\n- Theo bạn, lưu đồ này hoàn chỉnh chưa?\n- Với a=24, b=16 bạn hãy cho biết kết quả sau khi thực hiện lưu đồ trên.\n- Với a=0, b=-6 bạn hãy cho biết kết quả sau khi thực hiện lưu đồ trên.\n\nLưu đồ:\nBắt đầu → Nhập a, b → kiểm tra a = 0 → nếu Sai: x = -b/a → Xuất x → Kết thúc.\nNếu Đúng: kiểm tra b = 0 → nếu Sai: Vô nghiệm → Kết thúc; nếu Đúng: Vô số nghiệm → Kết thúc.",
"diagram_text": "Thuật toán giải ax + b = 0 với các nhánh: a ≠ 0 → x = -b/a; a = 0 & b = 0 → vô số nghiệm; a = 0 & b ≠ 0 → vô nghiệm.",
"has_diagram": true,
"image_path": "images/slide_50.png",
"page_number": 50,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán"
},
{
"id": "slide_51",
"topic": "Giải đề minh họa – Câu 4",
"type": "diagram",
"content_for_embedding": "Lưu đồ tính tích T của tất cả các số nguyên tố từ 1 đến n. Thuật toán: nhập n, đặt T = 1, i = 1, duyệt i từ 1 đến n; nếu i là số nguyên tố thì T = T * i; cuối cùng xuất T. Với n=4, T=6. Với n=7, T=210.",
"metadata": {
"raw_text": "Câu 4.\n- Với n = 4, hãy cho biết kết quả sau khi thực hiện lưu đồ.\n- Với n = 7, hãy cho biết kết quả sau khi thực hiện lưu đồ.\n\nLưu đồ: Nhập n → T=1, i=1 → kiểm tra i ≤ n → kiểm tra i có phải số nguyên tố không → nếu đúng thì T=T*i → tăng i → lặp lại → nếu i > n thì xuất T.",
"diagram_text": "Lưu đồ kiểm tra nguyên tố và nhân vào T.",
"has_diagram": true,
"image_path": "images/slide_51.png",
"page_number": 51,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán"
},
{
"id": "slide_52",
"topic": "Giải đề minh họa – Câu 5",
"type": "text",
"content_for_embedding": "Bài toán yêu cầu tìm tất cả các ước của n nhưng không là ước của m. Với n=12 và m=4, các ước của 12 là 1, 2, 3, 4, 6, 12; các ước của 4 là 1, 2, 4; loại bỏ ước chung, kết quả là 3, 6, 12.",
"metadata": {
"raw_text": "Câu 5. Cho bài toán: Tìm ước số của n nhưng không phải ước số của m.\n5a. Vẽ lưu đồ\n5b. Viết chương trình thực hiện.\n\nInput: n=12, m=4\nOutput: 3 6 12",
"diagram_text": "Bài toán liệt kê ước của n và lọc bỏ những số đồng thời là ước của m.",
"has_diagram": false,
"image_path": "images/slide_52.png",
"page_number": 52,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán"
},
{
"id": "slide_53",
"topic": "Giải đề minh họa – Câu 5a (Lưu đồ)",
"type": "diagram",
"content_for_embedding": "Lưu đồ mô tả thuật toán liệt kê các ước của n nhưng không là ước của m. Bắt đầu, nhập n và m, đặt i=1. Lặp đến khi i < n: nếu n % i == 0 và m % i != 0 thì xuất i. Sau đó tăng i và tiếp tục. Khi i >= n thì kết thúc.",
"metadata": {
"raw_text": "5a. Vẽ lưu đồ\nLưu đồ gồm các bước: Bắt đầu → Nhập n và m → i = 1 → kiểm tra i < n → nếu sai thì kết thúc. Nếu đúng: kiểm tra n % i == 0 → nếu đúng, tiếp tục kiểm tra m % i == 0 → nếu sai thì Xuất i. Tăng i lên 1 và quay lại bước kiểm tra i < n.",
"diagram_text": "Flowchart: kiểm tra i là ước của n nhưng không là ước của m, sau đó tăng i.",
"has_diagram": true,
"image_path": "images/slide_53.png",
"page_number": 53,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán"
},
{
"id": "slide_54",
"topic": "Giải đề minh họa – Câu 5b (Viết code)",
"type": "code_example",
"content_for_embedding": "Chương trình C++ liệt kê các ước của n nhưng không phải ước của m. Duyệt i từ 2 đến n, kiểm tra nếu n % i == 0 và m % i != 0 thì in i.",
"metadata": {
"raw_text": "5b. Viết code thực hiện bài toán\n#include <iostream>\n#include <cmath>\nusing namespace std;\nint main() {\n int n, m;\n cin >> n >> m;\n for (int i = 2; i <= n; i++) {\n if ((n % i == 0) && (m % i != 0))\n cout << i << \"\\t\";\n }\n}",
"code_language": "C++",
"page_number": 54,
"image_path": "images/slide_54.png",
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Thuật toán"
},
{
"id": "slide_55",
"topic": "6. Các lỗi thường gặp",
"type": "title",
"content_for_embedding": "Phần giới thiệu mục 6: Các lỗi thường gặp khi lập trình C++.",
"metadata": {
"raw_text": "6. Các lỗi thường gặp",
"page_number": 55,
"image_path": "images/slide_55.png",
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Lập trình căn bản"
},
{
"id": "slide_56",
"topic": "Lỗi thường gặp khi code",
"type": "content",
"content_for_embedding": "Một số lỗi thường gặp khi lập trình C++: 1. Chưa khởi tạo giá trị cho biến: ví dụ biến count không được gán giá trị ban đầu nhưng được dùng trong điều kiện while. 2. Sử dụng dấu chấm phẩy không đúng vị trí, ví dụ đặt dấu ; ngay sau for khiến thân vòng lặp không chạy như mong muốn.",
"metadata": {
"raw_text": "1. Chưa khởi tạo giá trị cho biến\nint main(){\n int count;\n while(count < 100){\n cout << count;\n count++;\n }\n return 0;\n}\n\n2. Sử dụng dấu chấm phẩy\nint main(){\n for(int i = 1; i <= 10; i++);\n cout << \"Hello\\n\";\n}",
"page_number": 56,
"image_path": "images/slide_56.png",
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Lập trình căn bản"
},
{
"id": "slide_57",
"topic": "Các lưu ý khi code giấy",
"type": "content",
"content_for_embedding": "Các lỗi thường mắc khi viết code trên giấy trong môn lập trình: thiếu dấu chấm phẩy, thiếu dấu ngoặc, viết sai hoa thường của tên biến, quên khai báo kiểu dữ liệu, sử dụng tên biến trùng với từ khóa của C++, và nhầm lẫn các dấu như = và ==, & và &&, ||.",
"metadata": {
"raw_text": "1. Thiếu dấu chấm phẩy ';'\n2. Thiếu dấu ngoặc nhọn '{' '}'\n3. Sử dụng biến sai chữ hoa chữ thường (ví dụ khai báo biến tên Tong nhưng khi sử dụng lại viết là tong)\n4. Quên không sử dụng kiểu dữ liệu (ví dụ cần khai báo biến Tong = 0, chính xác phải là int Tong = 0 nhưng lại viết là Tong = 0)\n5. Sử dụng tên biến trùng với từ khóa\n6. Nhầm lẫn các dấu:\n + Dấu '=' và '=='\n + Dấu '&', dấu '&&', dấu '||'",
"page_number": 57,
"image_path": "images/slide_57.png",
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Lập trình căn bản"
},
{
"id": "slide_58",
"topic": "Các lưu ý khi code giấy",
"type": "content",
"content_for_embedding": "Một số lưu ý quan trọng khi viết code trên giấy: cần ép kiểu dữ liệu nếu muốn kết quả chính xác, phải khai báo hàm ở phần khai báo, tránh tạo vòng lặp vô hạn, chú ý đến sự khác biệt giữa tham trị và tham chiếu.",
"metadata": {
"raw_text": "1. Ép kiểu dữ liệu (ví dụ cần tính chính xác 1/2 thì cần viết (float)(1)/2, nếu chỉ viết 1/2 thì kết quả = 0)\n2. Không khai báo hàm ở phần khai báo\n3. Vòng lặp vô hạn (vòng lặp while, gọi hàm thành vòng tròn,...)\n4. Không khai báo hàm ở phần khai báo\n5. Chú ý về tham trị và tham chiếu",
"page_number": 58,
"image_path": "images/slide_58.png",
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Lập trình căn bản"
},
{
"id": "slide_array_1",
"topic": "Mảng",
"type": "title",
"content_for_embedding": "Giới thiệu chương về mảng trong lập trình: mảng một chiều, thao tác nhập xuất, xử lý dữ liệu trong mảng.",
"metadata": {
"raw_text": "Mảng",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_1.png",
"page_number": 2,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Mảng"
},
{
"id": "slide_array_2_concept",
"topic": "Mảng – Khái niệm",
"type": "text",
"content_for_embedding": "Mảng là một dãy các phần tử có cùng kiểu dữ liệu, mỗi phần tử biểu diễn một giá trị. Kích thước mảng được xác định khi khai báo và không thay đổi trong quá trình thực thi chương trình. Mảng được phân loại thành mảng một chiều và mảng hai chiều.",
"metadata": {
"raw_text": "Khái niệm:\nLà một dãy các phần tử có cùng kiểu dữ liệu, mỗi phần tử trong mảng biểu diễn một giá trị.\n\nKích thước được xác định ngay khi khai báo và không đổi.\n\nPhân loại:\n• Mảng 1 chiều\n• Mảng 2 chiều",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_2_concept.png",
"page_number": 3,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Mảng"
},
{
"id": "slide_array_1d_1_declare",
"topic": "Mảng 1 chiều – Khai báo",
"type": "text",
"content_for_embedding": "Cú pháp khai báo mảng một chiều trong C++: <tên kiểu> <tên mảng>[số phần tử]. Có thể khởi tạo mảng bằng danh sách giá trị hoặc để trống số phần tử khi danh sách giá trị đã xác định. Ví dụ: int a[1000]; int x[2] = {1, 2, 3}; char s[] = {a, b, c};",
"metadata": {
"raw_text": "Khai báo:\n<tên kiểu> <tên mảng>[số phần tử];\nVí dụ: int a[1000];\n\n<tên kiểu> <tên mảng>[số phần tử]={dãy giá trị};\nVí dụ: int x[2]={1, 2, 3};\n\n<tên kiểu> <tên mảng>[] = {dãy giá trị};\nVí dụ: char s[] = {a, b, c};",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_1d_1_declare.png",
"page_number": 4,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Mảng 1 chiều"
},
{
"id": "slide_array_1d_2_index_access",
"topic": "Mảng 1 chiều – Chỉ số và cách truy cập",
"type": "text",
"content_for_embedding": "Chỉ số mảng là số nguyên không âm, thuộc đoạn [0; n-1] với n là số phần tử. Truy cập phần tử bằng cú pháp <tên mảng>[<chỉ số>]. Ví dụ int a[3] = {30, 3, 2021}; các phần tử hợp lệ là a[0], a[1], a[2]. Truy cập chỉ số âm hoặc chỉ số vượt quá n-1 là không hợp lệ.",
"metadata": {
"raw_text": "Chỉ số mảng là một số nguyên không âm.\nChỉ số thuộc đoạn [0; n-1] (với n là số phần tử).\nTruy cập các phần tử mảng thông qua chỉ số: <Tên mảng>[<chỉ số mảng>].\n\nVí dụ: int a[3] = {30, 3, 2021};\nĐúng: a[0], a[1], a[2]\nSai: a[-1], a[3], a[4]\nGiá trị các phần tử: a[0] = 30; a[1] = 3; a[2] = 2021.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_1d_2_index_access.png",
"page_number": 5,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Mảng 1 chiều"
},
{
"id": "slide_array_1d_3_input_output",
"topic": "Các thuật toán mảng 1 chiều – Nhập và xuất mảng",
"type": "code",
"content_for_embedding": "Thuật toán nhập và xuất mảng một chiều trong C++. Nhập mảng dùng vòng lặp for để đọc từng phần tử a[i]. Xuất mảng dùng vòng lặp for để in từng phần tử a[i] ra màn hình.",
"metadata": {
"raw_text": "Nhập mảng:\nvoid Nhapmang(int a[], int n) {\n for (int i = 0; i < n; i++)\n cin >> a[i];\n}\n\nXuất mảng:\nvoid Xuatmang(int a[], int n) {\n for (int i = 0; i < n; i++)\n cout << a[i] << \" \";\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_1d_3_input_output.png",
"page_number": 6,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Mảng 1 chiều"
},
{
"id": "slide_array_1d_4_sort",
"topic": "Các thuật toán mảng 1 chiều – Sắp xếp",
"type": "code",
"content_for_embedding": "Thuật toán sắp xếp nổi bọt (Bubble Sort) dùng để sắp xếp mảng theo thứ tự tăng dần. Hàm swap hoán đổi giá trị của hai biến tham chiếu. Hàm BubbleSort duyệt qua các cặp phần tử và hoán đổi nếu phần tử trước lớn hơn phần tử sau.",
"metadata": {
"raw_text": "Sắp xếp:\nvoid swap(int &a, int &b)\n{\n int temp = a;\n b = a;\n a = temp;\n}\n\nvoid BubbleSort(int a[], int n)\n{\n for (int i = 0; i < n; i++)\n for (int j = i + 1; j < n; j++)\n if (a[i] > a[j])\n swap(a[i], a[j]);\n}\n// Sap xep tang",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_1d_4_sort.png",
"page_number": 7,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Mảng 1 chiều"
},
{
"id": "slide_array_1d_5_dem_nguyen_to",
"topic": "Các thuật toán mảng 1 chiều – Đếm số nguyên tố",
"type": "code",
"content_for_embedding": "Thuật toán đếm số phần tử là số nguyên tố trong mảng. Hàm checkNguyenTo(x) kiểm tra số nguyên tố bằng cách loại x < 2 và thử chia từ 2 đến sqrt(x). Hàm demNguyenTo duyệt toàn bộ mảng, gọi hàm kiểm tra và đếm số phần tử thỏa điều kiện.",
"metadata": {
"raw_text": "Đếm số nguyên tố:\n#include <math.h>\nbool checkNguyenTo(int x)\n{\n if (x < 2) return false;\n for (int i = 2; i <= sqrt(x); i++)\n if (x % i == 0) return false;\n return true;\n}\n\nint demNguyenTo(int a[], int n)\n{\n int dem = 0;\n for (int i = 0; i < n; i++)\n if (checkNguyenTo(a[i]))\n dem++;\n return dem;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_array_1d_5_dem_nguyen_to.png",
"page_number": 8,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Mảng 1 chiều"
},
{
"id": "slide_array_2d_1_intro",
"topic": "Mảng 2 chiều – Khai báo và truy cập",
"type": "text",
"content_for_embedding": "Mảng hai chiều được khai báo với hai kích thước: số hàng và số cột. Việc duyệt và truyền mảng 2 chiều tương tự mảng 1 chiều nhưng dùng hai vòng lặp lồng nhau. Ví dụ: int a[50][100]; float b[10][10]. Các phần tử được truy cập qua chỉ số hàng và cột.",
"metadata": {
"raw_text": "Khai báo:\n<tên kiểu> <tên mảng>[<số hàng>][<số cột>];\nVí dụ: int a[50][100];\n float b[10][10];\n\nChỉ số và truyền mảng:\nCác thao tác truyền mảng 2 chiều cơ bản giống với mảng 1 chiều, nhưng thay vì dùng một vòng lặp thì dùng hai vòng lặp.\nCó minh hoạ bảng chỉ số 0 1 2 / 0 3 4 2 / 1 8 9 7 / 2 1 5 4.",
"diagram_text": "Ma trận minh hoạ cách đánh chỉ số hàng–cột cho mảng 2 chiều.",
"has_diagram": true,
"image_path": "images/slide_array_2d_1_intro.png",
"page_number": 9,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Mảng 2 chiều"
},
{
"id": "slide_array_2d_2_delete_row",
"topic": "Các thuật toán mảng 2 chiều – Xóa hàng của ma trận",
"type": "code",
"content_for_embedding": "Thuật toán xóa một hàng trong ma trận hai chiều bằng cách dồn các hàng phía sau lên trên. Hàm Tong thực hiện dịch chuyển hàng từ i+1 lên vị trí i trong phạm vi từ hàng x đến hàng n-1. Ví dụ minh họa với x = 2 và n = 3 cho thấy hàng bị xóa được thay bằng hàng tiếp theo.",
"metadata": {
"raw_text": "Xóa hàng của ma trận:\nvoid Tong(int a[][Max], int x, int n)\n{\n for (int i = x; i < n; i++)\n for (int j = 0; j < n; j++)\n a[i][j] = a[i + 1][j];\n}\n\nVí dụ minh họa với x = 2, n = 3 và ma trận ban đầu được dồn hàng.",
"diagram_text": "Hình minh họa: ma trận ban đầu → xóa hàng 2 → ma trận sau khi dồn các hàng xuống.",
"has_diagram": true,
"image_path": "images/slide_array_2d_2_delete_row.png",
"page_number": 10,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Mảng 2 chiều"
},
{
"id": "slide_struct_1_title",
"topic": "Kiểu cấu trúc",
"type": "title",
"content_for_embedding": "Giới thiệu chương về kiểu cấu trúc (struct) trong lập trình C++, bao gồm khai báo, truy cập thành phần và ứng dụng.",
"metadata": {
"raw_text": "Kiểu cấu trúc",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_struct_1_title.png",
"page_number": 11,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_2_concept_syntax",
"topic": "Kiểu cấu trúc – Khái niệm và cú pháp",
"type": "text",
"content_for_embedding": "Kiểu cấu trúc (struct) là một tập hợp các biến có kiểu dữ liệu khác nhau được gộp lại để tạo thành một kiểu dữ liệu mới. Struct cho phép nhóm nhiều thuộc tính liên quan vào một đối tượng. Cú pháp khai báo struct bao gồm các thành viên đặt trong cặp ngoặc nhọn và kết thúc bằng dấu chấm phẩy.",
"metadata": {
"raw_text": "Khái niệm:\nKiểu cấu trúc (struct) là một tập hợp của những kiểu dữ liệu khác nhau được góp lại tạo thành một kiểu dữ liệu mới.\n\nCú pháp:\nstruct <tên kiểu cấu trúc> {\n <kiểu dữ liệu> <tên biến 1>;\n ...\n <kiểu dữ liệu> <tên biến n>;\n};\n\nstruct <tên kiểu cấu trúc> <tên biến>; // C++ có thể bỏ qua\n\nVí dụ:\nstruct PhanSo {\n int TuSo;\n int MauSo;\n};\nstruct PhanSo PSa, PSb;",
"diagram_text": "Ví dụ minh họa struct PhanSo gồm hai thành phần TuSo và MauSo.",
"has_diagram": true,
"image_path": "images/slide_struct_2_concept_syntax.png",
"page_number": 12,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_3_typedef",
"topic": "Kiểu cấu trúc – Sử dụng typedef",
"type": "text",
"content_for_embedding": "typedef cho phép đặt tên mới cho một kiểu cấu trúc, giúp việc khai báo biến đơn giản hơn vì không cần từ khóa struct khi sử dụng. Cấu trúc được định nghĩa trong typedef và tên kiểu mới được đặt phía sau dấu đóng ngoặc.",
"metadata": {
"raw_text": "Cú pháp sử dụng typedef:\ntypedef struct\n{\n <kiểu dữ liệu> <tên biến 1>;\n ...\n <kiểu dữ liệu> <tên biến n>;\n} <tên kiểu cấu trúc>;\n<tên kiểu cấu trúc> <tên biến>;\n\nVí dụ:\ntypedef struct\n{\n int TuSo;\n int MauSo;\n} PhanSo;\nPhanSo PSa, PSb;\n\nKhi dùng typedef không có từ khóa struct lúc khai báo biến.",
"diagram_text": "Hộp ví dụ struct PhanSo được tạo bằng typedef, sau đó khai báo PSa, PSb mà không cần dùng struct.",
"has_diagram": true,
"image_path": "images/slide_struct_3_typedef.png",
"page_number": 13,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_4_init_variable",
"topic": "Kiểu cấu trúc – Khởi tạo cho biến cấu trúc",
"type": "text",
"content_for_embedding": "Biến cấu trúc có thể được khởi tạo bằng cách liệt kê các giá trị của từng trường theo đúng thứ tự đã khai báo trong struct. Cú pháp: struct <tên cấu trúc> { ... }; <tên biến> = {giá trị 1, ...}. Ví dụ: struct PhanSo { int TuSo; int MauSo; }; PhanSo PSa = {3, 4};",
"metadata": {
"raw_text": "Khởi tạo cho biến cấu trúc:\nstruct <tên kiểu cấu trúc>\n{\n <kiểu dữ liệu> <tên biến 1>;\n ...\n <kiểu dữ liệu> <tên biến n>;\n} <tên biến> = {<giá trị 1>, ...};\n\nVí dụ:\nStruct PhanSo\n{\n int TuSo;\n int MauSo;\n};\nPhanSo PSa = {3, 4};",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_struct_4_init_variable.png",
"page_number": 14,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_5_access",
"topic": "Kiểu cấu trúc – Truy xuất dữ liệu kiểu cấu trúc",
"type": "text",
"content_for_embedding": "Dữ liệu trong biến cấu trúc không thể truy xuất trực tiếp mà phải sử dụng toán tử truy cập thành phần (toán tử chấm). Cú pháp: <tên biến cấu trúc>.<tên thành phần>. Ví dụ struct PhanSo { int TuSo, MauSo; }; PhanSo PSa = {3,4}; cout << PSa.TuSo << '/' << PSa.MauSo; cho kết quả 3/4.",
"metadata": {
"raw_text": "Truy xuất dữ liệu kiểu cấu trúc:\nĐặc điểm:\n- Không thể truy xuất trực tiếp\n- Thông qua toán tử thành phần cấu trúc hay còn gọi là toán tử chấm\n\nCú pháp: <tên biến cấu trúc>.<tên thành phần>\n\nVí dụ:\nstruct PhanSo {\n int TuSo, MauSo;\n};\nPhanSo PSa = {3,4};\ncout << PSa.TuSo << \"/\" << PSa.MauSo; // Output: 3/4",
"diagram_text": "Ví dụ minh họa truy xuất PSa.TuSo và PSa.MauSo cho kết quả 3/4.",
"has_diagram": true,
"image_path": "images/slide_struct_5_access.png",
"page_number": 15,
"knowledge_type": [
"Khái niệm",
"Tính chất"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_6_assign",
"topic": "Kiểu cấu trúc – Gán dữ liệu kiểu cấu trúc",
"type": "text",
"content_for_embedding": "Có hai cách gán dữ liệu cho biến cấu trúc: gán trực tiếp và gán từng thành phần. Gán trực tiếp cho phép sao chép toàn bộ dữ liệu từ biến cấu trúc nguồn sang biến cấu trúc đích. Gán từng thành phần cho phép gán từng trường một cách thủ công.",
"metadata": {
"raw_text": "Gán dữ liệu kiểu cấu trúc:\nCó 2 cách:\n1. Gán trực tiếp:\n<biến cấu trúc đích> = <biến cấu trúc nguồn>;\nVí dụ:\nPhanSo PSa = {3,4};\nPhanSo PSb = PSa;\n\n2. Gán từng thành phần:\n<biến cấu trúc đích>.<tên thành phần> = <biến cấu trúc nguồn>.<tên thành phần>;\nVí dụ:\nPhanSo PSa = {3,4};\nPhanSo PSb;\nPSa.TuSo = PSb.TuSo;\nPSa.MauSo = PSb.MauSo * 2;",
"diagram_text": "Bảng minh họa hai cách gán: gán trực tiếp và gán từng trường.",
"has_diagram": true,
"image_path": "images/slide_struct_6_assign.png",
"page_number": 16,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_7_complex",
"topic": "Cấu trúc phức tạp – Struct lồng nhau",
"type": "text",
"content_for_embedding": "Cấu trúc phức tạp là cấu trúc mà thành phần của nó có thể là một cấu trúc khác. Điều này cho phép mô tả các đối tượng có nhiều thuộc tính phân cấp. Ví dụ struct HINHCHUNHAT chứa hai trường là hai struct DIEM: traitren và phaiduoi. Việc truy cập các trường lồng nhau dùng cú pháp <biến>.<thành phần>.<thuộc tính>.",
"metadata": {
"raw_text": "Thành phần của cấu trúc là cấu trúc khác nhau.\nVí dụ:\nstruct DIEM {\n int x;\n int y;\n};\n\nstruct HINHCHUNHAT {\n struct DIEM traitren;\n struct DIEM phaiduoi;\n} hcn1;\n...\nhcn1.traitren.x = 2912;\nhcn1.traitren.y = 1706;",
"diagram_text": "Ví dụ minh họa struct HINHCHUNHAT gồm hai struct DIEM lồng bên trong.",
"has_diagram": false,
"image_path": "images/slide_struct_7_complex.png",
"page_number": 17,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_8_array_struct",
"topic": "Mảng cấu trúc",
"type": "text",
"content_for_embedding": "Mảng cấu trúc là mảng mà mỗi phần tử là một biến cấu trúc. Chúng được khai báo và sử dụng tương tự như mảng của các kiểu dữ liệu cơ sở. Ví dụ: struct DIEM gồm hai thành phần x và y; DIEM mang1[20]; DIEM mang2[10] = {{3,2}, {4,4}, {2,7}}.",
"metadata": {
"raw_text": "Tương tự như mảng với kiểu dữ liệu cơ sở (char, int, float,...)\nVí dụ:\nstruct DIEM {\n int x;\n int y;\n};\n\nDIEM mang1[20];\nDIEM mang2[10] = {{3,2}, {4,4}, {2,7}};",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_struct_8_array_struct.png",
"page_number": 18,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_struct_9_pass_to_function",
"topic": "Truyền cấu trúc cho hàm",
"type": "code",
"content_for_embedding": "Cấu trúc có thể được truyền vào hàm giống như các kiểu dữ liệu cơ sở. Có ba cách: truyền tham trị, truyền tham chiếu và truyền con trỏ. Ví dụ hàm Nhap(PhanSo &PS) thay đổi trực tiếp dữ liệu thông qua tham chiếu, còn hàm GiaTriPS(PhanSo PS) truyền tham trị và không thay đổi biến gốc.",
"metadata": {
"raw_text": "Giống như truyền kiểu dữ liệu cơ sở:\n- Tham trị (không thay đổi sau khi kết thúc hàm)\n- Tham chiếu\n- Con trỏ\n\nVí dụ:\nvoid Nhap(PhanSo &PS)\n{\n cout << \"Nhap Tu So: \";\n cin >> PS.TuSo;\n cout << \"Nhap Mau So: \";\n cin >> PS.MauSo;\n}\n\ndouble GiaTriPS(PhanSo PS)\n{\n double x;\n x = (double)PS.TuSo / PS.MauSo;\n return x;\n}",
"diagram_text": "Bảng minh họa hai hàm: Nhap truyền tham chiếu, GiaTriPS truyền tham trị.",
"has_diagram": true,
"image_path": "images/slide_struct_9_pass_to_function.png",
"page_number": 19,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Kiểu cấu trúc"
},
{
"id": "slide_pointer_1_title",
"topic": "Con trỏ",
"type": "title",
"content_for_embedding": "Giới thiệu chương con trỏ trong C++ bao gồm khái niệm, khai báo, toán tử địa chỉ và dereference, cách sử dụng và ứng dụng trong hàm và cấu trúc dữ liệu.",
"metadata": {
"raw_text": "Con trỏ",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_1_title.png",
"page_number": 20,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_2_intro_questions",
"topic": "Con trỏ – Nỗi sợ và câu hỏi mở đầu",
"type": "text",
"content_for_embedding": "Giới thiệu về chủ đề con trỏ thông qua các câu hỏi gợi mở: Con trỏ là gì mà khiến nhiều người lo lắng khi học lập trình? Con trỏ có ăn được không? Slide giúp tạo sự tò mò trước khi vào nội dung định nghĩa và cách sử dụng con trỏ.",
"metadata": {
"raw_text": "Con trỏ ?? – Nỗi sợ ??\n1. Con trỏ là gì mà khiến nhiều người sợ hãi khi nhắc tới nó vậy kìa =( \n2. Con trỏ có ăn được không ??",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_2_intro_questions.png",
"page_number": 21,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_3_definition",
"topic": "Con trỏ – Khái niệm con trỏ là gì",
"type": "text",
"content_for_embedding": "Con trỏ là một biến đặc biệt có giá trị là địa chỉ của một ô nhớ. Về bản chất, con trỏ cũng giống biến bình thường: có tên, giá trị và địa chỉ, nhưng khác ở chỗ nó có thể trỏ đến nhiều ô nhớ khác nhau. Kiểu dữ liệu của con trỏ không phải kiểu dữ liệu của chính nó mà là kiểu dữ liệu của vùng nhớ mà nó trỏ đến.",
"metadata": {
"raw_text": "1. Con trỏ là gì?\n- Con trỏ là một biến bình thường nhưng có thể trỏ đi lung tung trong bộ nhớ. Và giá trị của con trỏ là địa chỉ.\n- Về bản chất con trỏ cũng như một biến bình thường: nó cũng có tên biến, giá trị của biến, địa chỉ của biến. Nhưng có điểm khác là:\n + Những biến bình thường thì nó chỉ nằm cố định trong 1 ô nhớ, còn biến con trỏ thì nó còn có thể trỏ đến các ô nhớ khác nhau.\n + <Kiểu dữ liệu> khi khai báo cho con trỏ không phải là kiểu dữ liệu của nó, mà là kiểu dữ liệu của vùng nhớ mà nó đang trỏ đến.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_3_definition.png",
"page_number": 22,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_4_example_same_address",
"topic": "Con trỏ – Minh họa con trỏ trỏ đến cùng vùng nhớ",
"type": "text",
"content_for_embedding": "Ví dụ minh họa ba con trỏ a, b, c trỏ đến cùng một vùng nhớ có địa chỉ 0x0099 chứa giá trị 69. Mỗi con trỏ bản thân nó có địa chỉ riêng: a ở 0x0022, b ở 0x0800, c ở 0x0006. Điều này cho thấy con trỏ là biến chứa địa chỉ và có thể trỏ đến cùng một ô nhớ.",
"metadata": {
"raw_text": "Ta có 3 biến con trỏ a, b, c có địa chỉ lần lượt là 0x0022, 0x0800, 0x0006 trỏ đến vùng nhớ có địa chỉ 0x0099 lưu giá trị 69.",
"diagram_text": "Sơ đồ minh họa: ba con trỏ a, b, c giữ cùng giá trị 0x0099 và trỏ đến ô nhớ chứa 69.",
"has_diagram": true,
"image_path": "images/slide_pointer_4_example_same_address.png",
"page_number": 23,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_5_why_use_pointer",
"topic": "Con trỏ – Tại sao lại có con trỏ? Dùng để làm gì?",
"type": "text",
"content_for_embedding": "Con trỏ giúp sử dụng bộ nhớ linh hoạt vì có thể trỏ đi nhiều vị trí khác nhau. Con trỏ đặc biệt quan trọng trong việc quản lý mảng động, cho phép cấp phát bộ nhớ theo nhu cầu thực tế thay vì cố định như mảng tĩnh. Điều này tránh lãng phí bộ nhớ và tăng tính hiệu quả.",
"metadata": {
"raw_text": "2. Tại sao lại có con trỏ? Sử dụng để làm gì?\n- Vì biến con trỏ có thể trỏ đi lung tung trong bộ nhớ nên việc sử dụng bộ nhớ sẽ linh hoạt hơn.\n- Áp dụng cho mảng động. Có nghĩa là khi chúng ta sử dụng mảng tĩnh với số lượng phần tử của mảng là cố định, chẳng hạn như mảng có 100 phần tử, thì dù chúng ta chỉ sử dụng 5–10 phần tử để thao tác tính toán thôi, thì bộ nhớ cũng sẽ cấp phát 100 ô nhớ, từ đó mà sẽ gây ra lãng phí bộ nhớ không đáng có. Còn khi chúng ta sử dụng mảng động dùng con trỏ thì chúng ta sử dụng 5 thì bộ nhớ cấp phát 5 ô nhớ, sử dụng 10 thì bộ nhớ cấp phát 10 ô nhớ.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_5_why_use_pointer.png",
"page_number": 24,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_6_declare_pointer",
"topic": "Con trỏ – Cách khai báo con trỏ",
"type": "text",
"content_for_embedding": "Con trỏ được khai báo bằng cú pháp <kiểu dữ liệu>* <tên con trỏ>. Kiểu dữ liệu cho biết loại dữ liệu mà vùng nhớ được trỏ tới. Dấu * thể hiện đây là một biến con trỏ. Tên con trỏ tuân theo quy tắc đặt tên biến.",
"metadata": {
"raw_text": "3. Cách khai báo con trỏ\n- Cú pháp:\n<Kiểu dữ liệu> *<Tên của con trỏ>;\n\n– Trong đó:\n<Kiểu dữ liệu>: Bao gồm các kiểu dữ liệu có sẵn (int, float, double, char, void) và kiểu dữ liệu do người dùng tự định nghĩa (Book, HocSinh, PhanSo,...)\nDấu *: biểu thị đây là biến con trỏ.\n<Tên của con trỏ>: Tuân theo quy tắc đặt tên biến trong lập trình.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_6_declare_pointer.png",
"page_number": 25,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_7_dereference_address_rules",
"topic": "Con trỏ – Toán tử *, toán tử & và quy tắc kiểu dữ liệu",
"type": "text",
"content_for_embedding": "Các con trỏ cùng kiểu có thể gán cho nhau. Toán tử * dùng để lấy giá trị tại địa chỉ mà con trỏ trỏ đến, còn toán tử & dùng để lấy địa chỉ của biến. Kiểu dữ liệu của con trỏ quyết định kiểu của vùng nhớ mà nó được phép trỏ tới: con trỏ int chỉ trỏ tới vùng nhớ kiểu int, con trỏ float chỉ trỏ tới vùng nhớ kiểu float. Việc trỏ sai kiểu sẽ gây lỗi.",
"metadata": {
"raw_text": "- Các con trỏ cùng kiểu có thể gán cho nhau.\n- Dùng toán tử * để lấy giá trị tại địa chỉ mà con trỏ trỏ đến (và toán tử * cũng thể hiện cho một biến là con trỏ, nên cần phân biệt khi nào *p là con trỏ p, khi nào *p là giá trị mà con trỏ p trỏ đến).\n- Dùng toán tử & để lấy địa chỉ của một biến.\n- Con trỏ khai báo kiểu int thì chỉ trỏ đến ô nhớ kiểu int, con trỏ khai báo kiểu float thì chỉ trỏ được đến ô nhớ kiểu float,… Nếu con trỏ kiểu int mà trỏ đến ô nhớ kiểu float hoặc ngược lại thì sẽ lỗi.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_7_dereference_address_rules.png",
"page_number": 26,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_8_example_wrong_type",
"topic": "Con trỏ – Ví dụ khai báo, gán địa chỉ và lỗi sai kiểu dữ liệu",
"type": "code",
"content_for_embedding": "Ví dụ minh họa cách khai báo con trỏ int và float, cách gán địa chỉ biến cho con trỏ đúng kiểu, và lỗi khi gán sai kiểu. Con trỏ c kiểu int có thể nhận &y nếu y là int, con trỏ px có thể nhận &x. Tuy nhiên con trỏ float t không thể gán &y vì địa chỉ của biến int không phù hợp với con trỏ kiểu float.",
"metadata": {
"raw_text": "Ví dụ: Cho các khai báo\nint x, y, *px, *c; // khai báo 2 biến x, y kiểu int và 2 con trỏ px, c kiểu int\nfloat *t, *d; // khai báo 2 con trỏ t, d kiểu float.\n\nc = &y; // gán địa chỉ biến y cho con trỏ c\npx = &x; // gán địa chỉ biến x cho con trỏ px\n\ntương tự, ta hiểu câu lệnh t = &y là gì?\n!!!!!! Đây là câu lệnh sai vì t là con trỏ kiểu float, nó chỉ có thể chứa địa chỉ của biến float.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_8_example_wrong_type.png",
"page_number": 27,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_9_rules_use_pointer_name",
"topic": "Quy tắc khi dùng con trỏ – Dùng tên con trỏ",
"type": "text",
"content_for_embedding": "Giá trị của biến con trỏ là địa chỉ. Khi gán giá trị cho con trỏ phải dùng toán tử & để lấy địa chỉ một biến. Con trỏ cũng có thể thay đổi giá trị như các biến khác, ví dụ p = p + 1 sẽ làm con trỏ trỏ sang phần tử tiếp theo của mảng.",
"metadata": {
"raw_text": "Cách 1: Dùng tên con trỏ\n- Lưu ý: Giá trị của biến con trỏ là địa chỉ! Vì vậy, khi muốn gán giá trị cho con trỏ phải dùng toán tử & để lấy địa chỉ.\n- Ví dụ:\nfloat a, *p, *q;\np = &a;\nq = p;\n- Sau khi thực hiện xong, biến q sẽ chứa giá trị là địa chỉ của biến a.\n- Cũng giống các biến khác, giá trị con trỏ cũng có thể thay đổi. Chẳng hạn: nếu con trỏ p chứa địa chỉ của mảng a[i] (p = a) thì khi thực hiện p = p + 1 nó sẽ chứa địa chỉ của phần tử a[i+1]",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_9_rules_use_pointer_name.png",
"page_number": 28,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_10_rules_dereference_operator",
"topic": "Quy tắc khi dùng con trỏ – Dùng dạng khai báo của con trỏ",
"type": "text",
"content_for_embedding": "Khi muốn lấy giá trị mà con trỏ trỏ đến, phải dùng toán tử *. Ví dụ p = &a; thì *p tương đương a trong mọi ngữ cảnh. Sau khi gán p trỏ đến a, câu lệnh cout << *p; sẽ in ra giá trị 5.",
"metadata": {
"raw_text": "Cách 2: Dùng dạng khai báo của con trỏ\n- Lưu ý: Giá trị của biến con trỏ là địa chỉ! Khi muốn lấy giá trị của biến con trỏ được trỏ đến, ta dùng toán tử *.\n- Ví dụ:\nfloat a = 5, *p;\np = &a;\ncout << *p;\n- Sau khi thực hiện xong, chương trình in ra giá trị 5.\n- Điều này được hiểu là *p và a là tương đương nhau trong mọi ngữ cảnh.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_10_rules_dereference_operator.png",
"page_number": 29,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_11_function_with_pointer_param",
"topic": "Hàm có đối số là con trỏ",
"type": "code",
"content_for_embedding": "Ví dụ minh họa lỗi khi truyền con trỏ vào hàm và gán sai kiểu. Trong hàm hoanvi(int *x, int *y), giá trị của *x và *y là kiểu int, nhưng biến y trong lời gọi hàm lại là địa chỉ nên không thể gán *x = y. Lỗi biên dịch xuất hiện do sai kiểu. Cách đúng là gán *x = *y để hoán đổi giá trị.",
"metadata": {
"raw_text": "Hàm có đối số là con trỏ:\nvoid hoanvi(int *x, int *y) {\n float z = *x;\n *x = y;\n *y = z;\n}\n\nint main() {\n int x = 5, y = 7;\n hoanvi(&x, &y);\n cout << x << \"\\t\" << y;\n}\n\nKết quả sau khi thực hiện???\n- Chương trình báo lỗi biên dịch.\n- Lý do:\n Giá trị của *x có kiểu là int\n Giá trị của y là địa chỉ\n ⇒ Không thể thực hiện phép gán *x = y.\n ⇒ Sửa thành: *x = *y;",
"diagram_text": "Sơ đồ giải thích lỗi do gán giá trị sai kiểu: *x là int nhưng y là địa chỉ.",
"has_diagram": true,
"image_path": "images/slide_pointer_11_function_with_pointer_param.png",
"page_number": 30,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_12_function_pointer_vs_reference",
"topic": "Hàm có đối số là con trỏ – So sánh truyền con trỏ và tham chiếu",
"type": "code",
"content_for_embedding": "So sánh hai cách truyền đối số để thay đổi giá trị biến gốc: dùng con trỏ và dùng tham chiếu. Cả hai đều cho phép thay đổi trực tiếp giá trị của biến truyền vào. Với con trỏ, ta truyền địa chỉ và dereference để truy cập giá trị. Với tham chiếu, cú pháp đơn giản hơn và không cần toán tử dereference.",
"metadata": {
"raw_text": "Hàm có đối số là con trỏ (cách 1):\nvoid hoanvi(int *x, int *y) {\n float z = *x;\n *x = *y;\n *y = z;\n}\nint main() {\n int x = 5, y = 7;\n hoanvi(&x, &y);\n cout << x << \"\\t\" << y;\n}\n\nHàm có đối số là tham chiếu (cách 2):\nvoid hoanvi(int &x, int &y) {\n float z = x;\n x = y;\n y = z;\n}\nint main() {\n int x = 5, y = 7;\n hoanvi(x, y);\n cout << x << \"\\t\" << y;\n}",
"diagram_text": "Hai cột mã minh họa cách hoán vị bằng con trỏ và bằng tham chiếu.",
"has_diagram": true,
"image_path": "images/slide_pointer_12_function_pointer_vs_reference.png",
"page_number": 31,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_13_pointer_arithmetic",
"topic": "Các phép toán số học của con trỏ",
"type": "text",
"content_for_embedding": "Phép toán số học trên con trỏ cho phép tính khoảng cách giữa hai con trỏ cùng kiểu và thao tác so sánh địa chỉ. p1 - p2 cho biết số phần tử cách nhau. Có thể so sánh địa chỉ con trỏ bằng các toán tử ==, !=, >, <, >=, <= nhưng không thể nhân hoặc chia con trỏ.",
"metadata": {
"raw_text": "Các phép toán số học con trỏ:\nPhép toán tính khoảng cách giữa 2 con trỏ:\n<kiểu dữ liệu> *p1, *p2;\np1 - p2 cho ta khoảng cách (theo số phần tử) giữa hai con trỏ (cùng kiểu).\n\nCác phép toán so sánh:\nSo sánh địa chỉ giữa hai con trỏ (thứ tự ô nhớ):\n==, !=, >, >=, <, <=\n\nKhông thể thực hiện các phép toán: * / %",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_13_pointer_arithmetic.png",
"page_number": 32,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_14_pointer_and_array",
"topic": "Con trỏ và mảng 1 chiều",
"type": "text",
"content_for_embedding": "Trong C/C++, con trỏ và mảng có mối quan hệ chặt chẽ: tên mảng là hằng địa chỉ, tương đương con trỏ trỏ đến phần tử đầu tiên. Biểu thức a[i] tương đương *(a + i). Các phép toán &a[i] hoặc a + i trả về địa chỉ phần tử thứ i.",
"metadata": {
"raw_text": "Con trỏ & mảng 1 chiều:\n- Trong C/C++ có mối quan hệ chặt chẽ giữa con trỏ & mảng, các phần tử của mảng có thể xác định nhờ chỉ số (a[i]) hoặc con trỏ (*(p+i)).\n- Giả sử ta có khai báo: double a[20]\n- Khi đó, phép toán &a[i] (hoặc a+i) với i trong đoạn [0,19] cho giá trị là địa chỉ của phần tử a[i].\n- Các lệnh có ý nghĩa tương đương:\n a tương đương với &a[0]\n a+i tương đương với &a[i]\n *(a+i) tương đương với a[i]",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_14_pointer_and_array.png",
"page_number": 33,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_pointer_15_pointer_array_example",
"topic": "Con trỏ và mảng 1 chiều – ví dụ minh họa",
"type": "diagram",
"content_for_embedding": "Ví dụ minh họa quan hệ giữa con trỏ và mảng: p = ch nghĩa là con trỏ p trỏ vào phần tử đầu tiên của mảng ký tự ch. Khi p tăng lên như p+1, p+2,... nó sẽ trỏ đến các phần tử tiếp theo ch[1], ch[2], ... tương ứng.",
"metadata": {
"raw_text": "Ví dụ:\nchar ch[10], *p;\np = ch;\nSơ đồ minh họa:\np trỏ đến ch[0], p+1 trỏ đến ch[1], p+2 trỏ đến ch[2], ..., p+9 trỏ đến ch[9].",
"diagram_text": "Biểu diễn hình ảnh các vị trí p, p+1, p+2,... trên mảng ch[10].",
"has_diagram": true,
"image_path": "images/slide_pointer_15_pointer_array_example.png",
"page_number": 34,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_memory_01_static_vs_dynamic_allocation",
"topic": "Cấp phát bộ nhớ tĩnh và động",
"type": "text",
"content_for_embedding": "Cấp phát bộ nhớ tĩnh yêu cầu biết trước kích thước và không thể thay đổi khi chạy. Cấp phát động cho phép xin bao nhiêu dùng bấy nhiêu và có thể giải phóng khi không cần dùng. Đây là nền tảng của lập trình sử dụng con trỏ với malloc, free hoặc new, delete.",
"metadata": {
"raw_text": "- Cấp phát bộ nhớ tĩnh: khai báo biến, cấu trúc, mảng; cần biết trước kích thước; bộ nhớ cố định.\n- Cấp phát động: cần bao nhiêu cấp phát bấy nhiêu; có thể giải phóng khi không sử dụng.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_memory_01_static_vs_dynamic_allocation.png",
"page_number": 35,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Cấp phát động"
},
{
"id": "slide_memory_02_new_operator",
"topic": "Cấp phát động bằng toán tử new",
"type": "text",
"content_for_embedding": "Toán tử new trong C++ dùng để cấp phát động bộ nhớ và trả về địa chỉ của vùng nhớ vừa cấp phát. Con trỏ trỏ tới vùng nhớ đó và có thể thao tác lên giá trị thông qua dereference (*ptr). Biến được tạo bằng new là biến 'không tên'.",
"metadata": {
"raw_text": "Có thể cấp phát động cho biến con trỏ bằng toán tử new.\nToán tử new tạo ra biến 'không tên' cho con trỏ trỏ tới.\nCú pháp: <type> *<pointerName> = new <type>;\nVí dụ: int *ptr = new int;\nTạo ra một biến 'không tên' và gán ptr trỏ tới nó. Có thể làm việc với biến 'không tên' thông qua *ptr.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_memory_02_new_operator.png",
"page_number": 36,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Cấp phát động"
},
{
"id": "slide_memory_03_delete_and_dangling_pointer",
"topic": "Toán tử delete và con trỏ lạc",
"type": "text",
"content_for_embedding": "Toán tử delete giải phóng vùng nhớ cấp phát bằng new. Sau khi delete, con trỏ vẫn giữ địa chỉ cũ, gọi là con trỏ lạc và rất nguy hiểm. Cách an toàn là gán con trỏ về NULL sau khi delete.",
"metadata": {
"raw_text": "Toán tử delete dùng để giải phóng vùng nhớ do con trỏ trỏ tới.\nCú pháp: delete <pointerName>;\nGhi chú: Sau khi gọi delete, con trỏ vẫn trỏ tới vùng nhớ trước khi giải phóng. Đây gọi là con trỏ lạc. Có thể gọi tham chiếu nhưng kết quả không lường trước và nguy hiểm.\nNên gán con trỏ bằng NULL sau khi delete.\nVí dụ:\ndelete pointer;\npointer = NULL;",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_memory_03_delete_and_dangling_pointer.png",
"page_number": 37,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Cấp phát động"
},
{
"id": "slide_memory_04_static_vs_dynamic_array",
"topic": "So sánh mảng tĩnh và mảng cấp phát động",
"type": "code",
"content_for_embedding": "Mảng tĩnh được cấp phát tại thời điểm biên dịch với kích thước cố định. Mảng động được cấp phát bằng toán tử new, cho phép thay đổi kích thước khi chạy chương trình.",
"metadata": {
"raw_text": "int main() {\n int arr[10];\n return 0;\n}\n\nint main() {\n int *arr;\n arr = new int[10];\n return 0;\n}",
"diagram_text": "Hai đoạn mã minh họa sự khác biệt giữa mảng tĩnh và mảng động.",
"has_diagram": true,
"image_path": "images/slide_memory_04_static_vs_dynamic_array.png",
"page_number": 38,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Cấp phát động"
},
{
"id": "slide_pointer_string_01_gets_issue",
"topic": "Mảng, con trỏ và xâu ký tự – vấn đề với gets() khi chưa cấp phát",
"type": "code",
"content_for_embedding": "Con trỏ ký tự phải trỏ đến vùng nhớ hợp lệ trước khi dùng để nhập chuỗi. Lỗi xảy ra khi gọi gets(st) nhưng st chưa trỏ đến vùng nhớ nào. Cách khắc phục: cấp phát động như st = new char[size];",
"metadata": {
"raw_text": "char *st;\ngets(st);\ncout << st;\nInput: 'Ban hoc tap'\nChương trình báo lỗi biên dịch.\nLý do: gets(st) đúng cú pháp nhưng không thể thực hiện do vùng nhớ mà st trỏ tới chưa được xác định.\nCách khắc phục: st = new char(); (hoặc new char[n]).",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_string_01_gets_issue.png",
"page_number": 39,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Con trỏ & chuỗi"
},
{
"id": "slide_pointer_string_02_array_vs_pointer_string_assignment",
"topic": "Mảng, con trỏ và xâu ký tự – gán chuỗi và sao chép chuỗi",
"type": "code",
"content_for_embedding": "Không thể gán trực tiếp một chuỗi ký tự vào một mảng char như t = \"Ban hoc tap\"; vì mảng không thể nhận phép gán. Cách đúng là dùng strcpy. Tuy nhiên, con trỏ char* có thể gán trực tiếp cho hằng chuỗi vì hằng chuỗi nằm trong vùng nhớ tĩnh và st sẽ trỏ đến đó.",
"metadata": {
"raw_text": "Ví dụ sai:\nchar *st, t[15];\nt = \"Ban hoc tap\"; // sai\ncout << t;\n\nCách sửa đúng:\nchar *st, t[15];\nst = t;\nstrcpy(st, \"Ban hoc tap\");\ncout << t;\n\nVí dụ hợp lệ:\nchar *st, t[15];\nst = \"Ban hoc tap\";\ncout << st;",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_string_02_array_vs_pointer_string_assignment.png",
"page_number": 40,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Con trỏ & chuỗi"
},
{
"id": "slide_pointer_string_03_pointer_string_indexing",
"topic": "Con trỏ và xâu ký tự – truy cập phần tử bằng con trỏ",
"type": "code",
"content_for_embedding": "Với char* st trỏ đến hằng chuỗi, st tương đương st+0, st+1 là địa chỉ của ký tự thứ 1. Biểu thức st[1] tương đương *(st+1). In ra st in toàn bộ chuỗi, còn in ra st+1 in chuỗi từ ký tự thứ 1 trở đi.",
"metadata": {
"raw_text": "char *st;\nst = \"Ban hoc tap\";\ncout << st; // in toàn chuỗi\ncout << st+1; // bỏ qua ký tự đầu tiên\ncout << st[1]; // ký tự thứ 1\ncout << *(st+1); // ký tự thứ 1\n\nGhi chú:\nst ~ st+0\nst[1] ~ *(st+1)\nst+1 sẽ bỏ qua phần tử thứ 0",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_pointer_string_03_pointer_string_indexing.png",
"page_number": 41,
"knowledge_type": [
"Tính chất"
]
},
"chapter": "Con trỏ & chuỗi"
},
{
"id": "slide_pointer_04_pass_pointer_vs_reference_to_pointer",
"topic": "Truyền con trỏ theo kiểu tham trị và tham chiếu",
"type": "code",
"content_for_embedding": "Khi truyền con trỏ bằng tham trị (int* a), bên trong hàm thay đổi a sẽ không ảnh hưởng đến biến con trỏ gốc. Khi truyền bằng tham chiếu (int*& a), thay đổi a bên trong hàm sẽ thay đổi luôn con trỏ bên ngoài.",
"metadata": {
"raw_text": "Ví dụ 1 – truyền con trỏ bằng tham trị:\nvoid hamf(int* a) {\n a = new int[5];\n for (int i = 0; i < 5; i++)\n a[i] = i + 1;\n}\n\nvoid main() {\n int n = 5;\n int* a = &n;\n cout << *a;\n hamf(a);\n cout << *a; // giá trị vẫn là 5\n}\n\nVí dụ 2 – truyền con trỏ bằng tham chiếu:\nvoid hamf(int*& a) {\n a = new int[5];\n for (int i = 0; i < 5; i++)\n a[i] = i + 1;\n}\n\nvoid main() {\n int n = 5;\n int* a = &n;\n cout << *a;\n hamf(a);\n cout << *a; // giá trị là 1 vì a trỏ đến mảng mới\n}",
"diagram_text": "So sánh kết quả trước và sau khi gọi hàm giữa tham trị (không đổi con trỏ) và tham chiếu (con trỏ thay đổi).",
"has_diagram": true,
"image_path": "images/slide_pointer_04_pass_pointer_vs_reference_to_pointer.png",
"page_number": 42,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Con trỏ"
},
{
"id": "slide_string_00_title",
"topic": "Xâu kí tự",
"type": "text",
"content_for_embedding": "Tiêu đề giới thiệu chương học về xâu ký tự trong C/C++, bao gồm khai báo, xử lý và thao tác trên chuỗi ký tự.",
"metadata": {
"raw_text": "Xâu kí tự",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_string_00_title.png",
"page_number": 43,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Xâu ký tự"
},
{
"id": "slide_string_01_declare_string",
"topic": "Cách khai báo xâu ký tự",
"type": "text",
"content_for_embedding": "Trong C/C++, xâu ký tự có thể khai báo bằng con trỏ char* hoặc bằng mảng char[]. char* dùng để trỏ đến chuỗi ký tự, còn char[name][size] tạo ra vùng nhớ cố định để chứa chuỗi.",
"metadata": {
"raw_text": "1. Cách khai báo xâu kí tự\nCú pháp:\n char* <Tên của xâu>;\n char <Tên của xâu>[số_phần_tử];\nTrong đó:\n- Dấu * : biểu thị biến con trỏ.\n- <Tên của xâu>: tuân theo quy tắc đặt tên biến trong lập trình.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_string_01_declare_string.png",
"page_number": 44,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Xâu ký tự"
},
{
"id": "slide_string_02_valid_string_declaration",
"topic": "Các cách khai báo xâu ký tự – đúng và sai",
"type": "text",
"content_for_embedding": "Một số cách khai báo chuỗi ký tự là hợp lệ hoặc không hợp lệ tùy thuộc vào việc có đủ kích thước chứa ký tự kết thúc '\\0'. char* str = \"BHT\" hợp lệ. char str[3] = \"BHT\" lỗi vì thiếu bộ nhớ cho ký tự kết thúc. char str = \"B\" sai vì str không phải mảng. char str[1] = \"\" hợp lệ nhưng chỉ chứa được chuỗi rỗng. char s[3] = {'B','H','T'} hợp lệ nhưng không phải chuỗi vì thiếu '\\0'.",
"metadata": {
"raw_text": "Các khai báo:\nchar* str = \"BHT\"; // hợp lệ\nchar str[3] = \"BHT\"; // sai, thiếu '\\0'\nchar str = \"B\"; // sai, không phải mảng/ký tự\nchar str[1] = \"\"; // hợp lệ, chứa chuỗi rỗng\nchar s[3] = { 'B', 'H', 'T' }; // hợp lệ nhưng không phải chuỗi vì thiếu '\\0'\n\nCâu hỏi: Có bao nhiêu cách khai báo hợp lệ?",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_string_02_valid_string_declaration.png",
"page_number": 45,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Xâu ký tự"
},
{
"id": "slide_string_03_null_terminated_string",
"topic": "Khái niệm xâu ký tự và ký tự null '\\0'",
"type": "text",
"content_for_embedding": "Chuỗi trong C/C++ là một mảng ký tự được kết thúc bằng ký tự '\\0'. Hằng chuỗi được đặt trong dấu nháy kép. Khi khai báo mảng để chứa chuỗi cần dành thêm một ký tự cho '\\0'. Ví dụ: chuỗi dài 20 ký tự cần mảng char str[21].",
"metadata": {
"raw_text": "Chuỗi là một mảng ký tự được kết thúc bằng ký tự null ('\\0').\nKý tự null ('\\0') là ký tự dùng để kết thúc Chuỗi.\nHằng Chuỗi là Chuỗi được bao quanh bởi cặp dấu nháy đôi.\nVí dụ: \"Hello\".\nVí dụ: để khai báo một mảng str chứa chuỗi có độ dài 20 ký tự, ta khai báo:\nchar str[21];",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_string_03_null_terminated_string.png",
"page_number": 46,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Xâu ký tự"
},
{
"id": "slide_string_04_input_functions",
"topic": "Nhập xâu ký tự – xử lý khoảng trắng",
"type": "text",
"content_for_embedding": "Khi nhập chuỗi có khoảng trắng, cin sẽ dừng tại dấu cách. Do đó cần dùng các hàm như gets, gets_s hoặc getline để nhập cả dòng. Ví dụ chuỗi 'Ban hoc tap KH&KTTT' cần dùng getline để lấy toàn bộ.",
"metadata": {
"raw_text": "Ví dụ xâu ký tự: \"Ban hoc tap KH&KTTT\".\nNhập bằng cin sẽ dừng ở dấu cách. Để nhập cả xâu có khoảng trắng, dùng các hàm:\n- gets(xâu_kí_tự);\n- gets_s(xâu_kí_tự, số_phần_tử);\n- getline(cin, xâu_kí_tự);",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_string_04_input_functions.png",
"page_number": 47,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Xâu ký tự"
},
{
"id": "slide_string_05_stringh_functions",
"topic": "Các hàm xử lý chuỗi trong thư viện <string.h>",
"type": "text",
"content_for_embedding": "Các hàm thao tác chuỗi cơ bản trong C bao gồm strlen, strcpy, strlwr, strupr, strcmp, stricmp, strcat, và strstr. Đây là những hàm quan trọng để đo độ dài, sao chép chuỗi, chuyển chữ thường/hoa, so sánh và tìm chuỗi con.",
"metadata": {
"raw_text": "Một số hàm thuộc thư viện <string.h>:\n• strlen: hàm tính độ dài chuỗi ký tự\n• strcpy: hàm sao chép chuỗi ký tự\n• strlwr/strupr: chuyển chuỗi thành chữ thường / chữ hoa\n• strcmp: so sánh 2 chuỗi có phân biệt hoa thường\n• stricmp: so sánh 2 chuỗi không phân biệt hoa thường\n• strcat: nối 2 chuỗi\n• strstr: tìm chuỗi trong chuỗi",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/slide_string_05_stringh_functions.png",
"page_number": 48,
"knowledge_type": [
"Khái niệm"
]
},
"chapter": "Xâu ký tự"
},
{
"id": "slide_giai_pt_bac_2_c",
"topic": "Giải phương trình bậc 2 trong C",
"type": "exercise",
"content_for_embedding": "Bài tập yêu cầu viết chương trình C giải phương trình bậc hai dạng ax^2 + bx + c = 0. Chương trình sử dụng công thức delta để xét số nghiệm, dùng hàm sqrt để tính căn bậc hai và scanf để nhập dữ liệu từ bàn phím. Xử lý đầy đủ các trường hợp phương trình bậc nhất, hai nghiệm phân biệt, nghiệm kép và vô nghiệm.",
"metadata": {
"raw_text": "Giải phương trình bậc 2 trong C\n\nĐề bài\nViết chương trình giải phương trình bậc 2 trong C. Phương trình bậc 2 có dạng:\n\nAX2 + BX + C = 0\n\nLời giải\nLời giải sử dụng hàm sqrt() để tính căn bậc 2 trong C và hàm scanf() để nhập số thực từ bàn phím.\n\n#include <stdio.h>\n\n/**\n * giai phuong trinh bac 2: ax2 + bx + c = 0\n * \n * @param a: he so bac 2\n * @param b: he so bac 1\n * @param c: so hang tu do\n */\nvoid giaiPTBac2(float a, float b, float c) {\n if (a == 0) {\n if (b == 0) {\n printf(\"Phuong trinh vo nghiem!\");\n } else {\n printf(\"Phuong trinh co mot nghiem: x = %f\", (-c / b));\n }\n return;\n }\n\n float delta = b*b - 4*a*c;\n float x1, x2;\n\n if (delta > 0) {\n x1 = (-b + sqrt(delta)) / (2*a);\n x2 = (-b - sqrt(delta)) / (2*a);\n printf(\"Phuong trinh co 2 nghiem la: x1 = %f va x2 = %f\", x1, x2);\n } else if (delta == 0) {\n x1 = -b / (2*a);\n printf(\"Phong trinh co nghiem kep: x1 = x2 = %f\", x1);\n } else {\n printf(\"Phuong trinh vo nghiem!\");\n }\n}\n\nint main() {\n float a, b, c;\n printf(\"Nhap he so bac 2, a = \");\n scanf(\"%f\", &a);\n printf(\"Nhap he so bac 1, b = \");\n scanf(\"%f\", &b);\n printf(\"Nhap so hang tu do, c = \");\n scanf(\"%f\", &c);\n giaiPTBac2(a, b, c);\n return 1;\n}\n\nKet qua:\nNhap he so bac 2, a = 2\nNhap he so bac 1, b = 3\nNhap so hang tu do, c = 1\nPhuong trinh co 2 nghiem la: x1 = -0.500000 va x2 = -1.000000",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/giai_pt_bac_2_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C cơ bản"
},
{
"id": "slide_uscln_bscnn_c",
"topic": "Tìm ước số chung lớn nhất (USCLN) và bội số chung nhỏ nhất (BSCNN)",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C tìm ước số chung lớn nhất và bội số chung nhỏ nhất của hai số nguyên dương a và b. Lời giải sử dụng giải thuật Euclid để tính USCLN dựa trên phép chia dư, sau đó áp dụng công thức BSCNN(a, b) = (a * b) / USCLN(a, b). Phương pháp này hiệu quả và thường được dùng trong lập trình.",
"metadata": {
"raw_text": "Tìm ước số chung lớn nhất (USCLN) và bội số chung nhỏ nhất (BSCNN) của 2 số\n\nĐề bài\nViết chương trình C tìm ước số chung lớn nhất (USCLN) và bội số chung nhỏ nhất (BSCNN) của hai số nguyên dương a và b.\n\nĐịnh nghĩa\nUSCLN của 2 số nguyên dương a và b là một số k lớn nhất sao cho a và b đều chia hết cho k.\n\nBSCNN của 2 số nguyên dương a và b là một số h nhỏ nhất sao cho h chia hết cho cả a và b.\n\nLời giải\nMột cách đơn giản để tìm USCLN là duyệt từ số nhỏ hơn trong hai số a và b xuống 1. Tuy nhiên cách này chưa hiệu quả.\n\nGiải thuật Euclid do nhà toán học Euclid phát minh cho phép tính USCLN hiệu quả dựa trên công thức:\nUSCLN(a, b) = USCLN(b, a mod b).\n\nSau khi tìm được USCLN, BSCNN được tính theo công thức:\nBSCNN(a, b) = (a * b) / USCLN(a, b).\n\nVí dụ sử dụng giải thuật Euclid trong C:\n\n#include <stdio.h>\n\nint USCLN(int a, int b) {\n if (b == 0) return a;\n return USCLN(b, a % b);\n}\n\nint BSCNN(int a, int b) {\n return (a * b) / USCLN(a, b);\n}\n\nint main() {\n int a, b;\n printf(\"Nhap so nguyen duong a = \");\n scanf(\"%d\", &a);\n printf(\"Nhap so nguyen duong b = \");\n scanf(\"%d\", &b);\n printf(\"USCLN cua %d va %d la: %d\", a, b, USCLN(a, b));\n printf(\"BSCNN cua %d va %d la: %d\", a, b, BSCNN(a, b));\n}\n\nKet qua:\nNhap so nguyen duong a = 4\nNhap so nguyen duong b = 6\nUSCLN cua 4 va 6 la: 2, BSCNN cua 4 va 6 la: 12",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/uscln_bscnn_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C cơ bản"
},
{
"id": "slide_prime_less_than_n_c",
"topic": "Liệt kê tất cả các số nguyên tố nhỏ hơn n trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C liệt kê tất cả các số nguyên tố nhỏ hơn n. Lời giải sử dụng hàm kiểm tra số nguyên tố bằng cách thử chia từ 2 đến căn bậc hai của n. Chương trình tối ưu bằng cách chỉ xét các số lẻ và loại trừ các trường hợp n nhỏ hơn 2.",
"metadata": {
"raw_text": "Liệt kê tất cả các số nguyên tố nhỏ hơn n trong C\n\nĐề bài\nViết chương trình liệt kê tất cả các số nguyên tố nhỏ hơn n.\n\nĐịnh nghĩa\nSố nguyên tố là số lớn hơn 1 và chỉ chia hết cho 1 và chính nó.\nVí dụ: 2, 3, 5, 7, 11, 13, 17, … là những số nguyên tố.\n\nChú ý:\n- Số 0 và 1 không phải là số nguyên tố.\n- Chỉ có số 2 là số nguyên tố chẵn.\n- Các số chẵn khác đều không phải là số nguyên tố vì chia hết cho 2.\n\nLời giải\n\n#include <stdio.h>\n#include <math.h>\n\nint isPrimeNumber(int n) {\n if (n < 2) {\n return 0;\n }\n int i;\n int squareRoot = (int) sqrt(n);\n for (i = 2; i <= squareRoot; i++) {\n if (n % i == 0) {\n return 0;\n }\n }\n return 1;\n}\n\nint main() {\n int i, n;\n printf(\"Nhap n = \");\n scanf(\"%d\", &n);\n printf(\"Tat ca cac so nguyen to nho hon %d la: \\n\", n);\n if (n >= 2) {\n printf(\"%d \", 2);\n }\n for (i = 3; i < n; i += 2) {\n if (isPrimeNumber(i) == 1) {\n printf(\"%d \", i);\n }\n }\n}\n\nKet qua:\nNhap n = 100\nTat ca cac so nguyen to nho hon 100 la:\n2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/prime_less_than_n_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Lập trình C – Vòng lặp và hàm"
},
{
"id": "slide_first_n_primes_c",
"topic": "Liệt kê n số nguyên tố đầu tiên trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C liệt kê n số nguyên tố đầu tiên. Lời giải sử dụng hàm kiểm tra số nguyên tố bằng cách thử chia từ 2 đến căn bậc hai của số đang xét. Chương trình dùng vòng lặp while để tìm lần lượt các số nguyên tố bắt đầu từ 2 cho đến khi đủ n số.",
"metadata": {
"raw_text": "Liệt kê n số nguyên tố đầu tiên trong C\n\nĐề bài\nViết chương trình C liệt kê n số nguyên tố đầu tiên.\n\nĐịnh nghĩa\nSố nguyên tố là số lớn hơn 1 và chỉ chia hết cho 1 và chính nó.\nVí dụ: 2, 3, 5, 7, 11, 13, 17, … là những số nguyên tố.\n\nChú ý:\n- Số 0 và 1 không phải là số nguyên tố.\n- Chỉ có số 2 là số nguyên tố chẵn.\n- Các số chẵn khác đều không phải là số nguyên tố vì chia hết cho 2.\n\nLời giải\n\n#include <stdio.h>\n#include <math.h>\n\nint isPrimeNumber(int n) {\n if (n < 2) {\n return 0;\n }\n int i;\n int squareRoot = sqrt(n);\n for (i = 2; i <= squareRoot; i++) {\n if (n % i == 0) {\n return 0;\n }\n }\n return 1;\n}\n\nint main() {\n int n;\n printf(\"Nhap n = \");\n scanf(\"%d\", &n);\n printf(\"%d so nguyen to dau tien la: \\n\", n);\n int dem = 0;\n int i = 2;\n while (dem < n) {\n if (isPrimeNumber(i)) {\n printf(\"%d \", i);\n dem++;\n }\n i++;\n }\n}\n\nKet qua:\nNhap n = 10\n10 so nguyen to dau tien la:\n2 3 5 7 11 13 17 19 23 29",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/first_n_primes_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Lập trình C – Vòng lặp và hàm"
},
{
"id": "slide_prime_5_digits_c",
"topic": "Liệt kê tất cả số nguyên tố có 5 chữ số trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C liệt kê tất cả các số nguyên tố có 5 chữ số. Lời giải sử dụng hàm kiểm tra số nguyên tố bằng cách thử chia từ 2 đến căn bậc hai của số đang xét. Chương trình chỉ duyệt các số lẻ trong khoảng từ 10001 đến 99999 để tối ưu tốc độ và đếm tổng số lượng số nguyên tố thỏa mãn.",
"metadata": {
"raw_text": "Liệt kê tất cả số nguyên tố có 5 chữ số trong C\n\nĐề bài\nViết chương trình C liệt kê tất cả số nguyên tố có 5 chữ số.\n\nĐịnh nghĩa\nSố nguyên tố là số lớn hơn 1 và chỉ chia hết cho 1 và chính nó.\nVí dụ: 2, 3, 5, 7, 11, 13, 17, … là những số nguyên tố.\n\nChú ý:\n- Số 0 và 1 không phải là số nguyên tố.\n- Chỉ có số 2 là số nguyên tố chẵn.\n- Các số chẵn khác đều không phải là số nguyên tố vì chia hết cho 2.\n\nLời giải\n\n#include <stdio.h>\n#include <math.h>\n\nint isPrimeNumber(int n) {\n if (n < 2) {\n return 0;\n }\n int i;\n int squareRoot = (int) sqrt(n);\n for (i = 2; i <= squareRoot; i++) {\n if (n % i == 0) {\n return 0;\n }\n }\n return 1;\n}\n\nint main() {\n int count = 0;\n int i;\n printf(\"Liet ke tat ca cac so co 5 chu so:\\n\");\n for (i = 10001; i < 99999; i += 2) {\n if (isPrimeNumber(i)) {\n printf(\"%d\\n\", i);\n count++;\n }\n }\n printf(\"Tong cac so nguyen to co 5 chu so la: %d\", count);\n}\n\nKet qua:\nLiet ke tat ca cac so co 5 chu so:\n10007\n10009\n10037\n...\n99971\n99989\n99991\nTong cac so nguyen to co 5 chu so la: 8363",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/prime_5_digits_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C cơ bản"
},
{
"id": "slide_prime_factorization_c",
"topic": "Phân tích số nguyên n thành tích các số nguyên tố trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C phân tích một số nguyên dương n thành tích các thừa số nguyên tố. Lời giải sử dụng phương pháp chia liên tiếp bắt đầu từ 2, mỗi lần nếu n chia hết cho i thì ghi nhận i là một thừa số và tiếp tục chia cho đến khi không còn chia được. Thuật toán kết thúc khi n bằng 1.",
"metadata": {
"raw_text": "Phân tích số nguyên n thành tích các số nguyên tố trong C\n\nĐề bài\nViết chương trình C phân tích số nguyên n thành các thừa số nguyên tố.\nVí dụ:\n12 = 2 x 2 x 3\n100 = 2 x 2 x 5 x 5\n\nLời giải\n\n#include <stdio.h>\n\nvoid phanTichSoNguyen(int n) {\n int i = 2;\n int dem = 0;\n int a[100];\n while (n > 1) {\n if (n % i == 0) {\n n = n / i;\n a[dem++] = i;\n } else {\n i++;\n }\n }\n if (dem == 0) {\n a[dem++] = n;\n }\n for (i = 0; i < dem - 1; i++) {\n printf(\"%d x \", a[i]);\n }\n printf(\"%d\", a[dem - 1]);\n}\n\nint main() {\n int n;\n printf(\"Nhap so nguyen duong n = \");\n scanf(\"%d\", &n);\n phanTichSoNguyen(n);\n}\n\nKet qua:\nNhap so nguyen duong n = 120\n2 x 2 x 2 x 3 x 5",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/prime_factorization_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C cơ bản"
},
{
"id": "slide_sum_digits_c",
"topic": "Tính tổng các chữ số của một số nguyên n trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C tính tổng các chữ số của một số nguyên dương n. Lời giải sử dụng phép chia dư cho 10 để tách từng chữ số và phép chia nguyên để loại bỏ chữ số cuối cùng. Quá trình lặp lại cho đến khi n bằng 0.",
"metadata": {
"raw_text": "Tính tổng của các chữ số của một số nguyên n trong C\n\nĐề bài\nViết chương trình C tính tổng các chữ số của một số nguyên n.\nVí dụ:\n1234 = 1 + 2 + 3 + 4 = 10\n\nLời giải\n\n#include <stdio.h>\n\nconst int DEC_10 = 10;\n\nint totalDigitsOfNumber(int n) {\n int total = 0;\n do {\n total = total + n % DEC_10;\n n = n / DEC_10;\n } while (n > 0);\n return total;\n}\n\nint main() {\n int n;\n printf(\"Nhap so nguyen duong n = \");\n scanf(\"%d\", &n);\n printf(\"Tong cac chu so cua %d la: %d\", n, totalDigitsOfNumber(n));\n}\n\nKet qua:\nNhap so nguyen duong n = 1234\nTong cac chu so cua 1234 la: 10",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/sum_digits_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Lập trình C – Vòng lặp và toán học"
},
{
"id": "slide_palindrome_6_digits_c",
"topic": "Tìm số thuận nghịch có 6 chữ số trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C liệt kê tất cả các số thuận nghịch có 6 chữ số. Một số thuận nghịch là số đọc từ trái sang phải hay từ phải sang trái đều giống nhau. Lời giải sử dụng phương pháp duyệt các số trong khoảng từ 100000 đến 999999, sau đó tách từng chữ số và so sánh các chữ số đối xứng để kiểm tra tính thuận nghịch.",
"metadata": {
"raw_text": "Tìm số thuận nghịch trong C\n\nĐề bài\nViết chương trình C tìm các số thuận nghịch có 6 chữ số.\n\nMột số được gọi là số thuận nghịch nếu đọc từ trái sang phải hay từ phải sang trái đều cho cùng một giá trị.\nVí dụ:\n123321 -> True\n123451 -> False\n\nLời giải\nCách 1: Duyệt các số từ 100000 đến 999999, sau đó phân tách số hiện tại thành các chữ số để kiểm tra tính thuận nghịch.\n\n#include <stdio.h>\n\nconst int DEC_10 = 10;\n\nint isThuanNghich(int n) {\n int a[20];\n int dem = 0, i;\n do {\n a[dem++] = n % DEC_10;\n n = n / DEC_10;\n } while (n > 0);\n\n for (i = 0; i < dem / 2; i++) {\n if (a[i] != a[dem - i - 1]) {\n return 0;\n }\n }\n return 1;\n}\n\nint main() {\n int count = 0, i;\n for (i = 100000; i < 1000000; i++) {\n if (isThuanNghich(i)) {\n printf(\"%d\\n\", i);\n count++;\n }\n }\n printf(\"Tong cac so thuan nghich co 6 chu so la: %d\", count);\n}\n\nKet qua:\n100001\n101101\n102201\n...\n997799\n998899\n999999\nTong cac so thuan nghich co 6 chu so la: 900",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/palindrome_6_digits_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C cơ bản"
},
{
"id": "slide_fibonacci_prime_less_than_n_c",
"topic": "Liệt kê số Fibonacci nhỏ hơn n và là số nguyên tố trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C liệt kê các số Fibonacci nhỏ hơn n đồng thời là số nguyên tố. Lời giải sử dụng hàm đệ quy để tính số Fibonacci theo chỉ số và kết hợp hàm kiểm tra số nguyên tố bằng cách thử chia đến căn bậc hai. Chương trình duyệt các số Fibonacci theo thứ tự tăng dần và in ra những số thỏa mãn cả hai điều kiện.",
"metadata": {
"raw_text": "Liệt kê số Fibonacci nhỏ hơn n và là số nguyên tố trong C\n\nĐề bài\nViết chương trình C liệt kê các số Fibonacci nhỏ hơn n là số nguyên tố.\nSố tự nhiên n được nhập từ bàn phím.\n\nLời giải\n\n#include <stdio.h>\n#include <math.h>\n\nint fibonacci(int n) {\n if (n < 0) {\n return -1;\n } else if (n == 0 || n == 1) {\n return n;\n } else {\n return fibonacci(n - 1) + fibonacci(n - 2);\n }\n}\n\nint isPrimeNumber(int n) {\n if (n < 2) {\n return 0;\n }\n int i;\n int squareRoot = sqrt(n);\n for (i = 2; i <= squareRoot; i++) {\n if (n % i == 0) {\n return 0;\n }\n }\n return 1;\n}\n\nint main() {\n int n;\n printf(\"Nhap so nguyen duong = \");\n scanf(\"%d\", &n);\n printf(\"Cac so fibonacci nho hon %d va la so nguyen to: \", n);\n int i = 0;\n while (fibonacci(i) < n) {\n int fi = fibonacci(i);\n if (isPrimeNumber(fi)) {\n printf(\"%d \", fi);\n }\n i++;\n }\n}\n\nKet qua:\nNhap so nguyen duong = 100\nCac so fibonacci nho hon 100 va la so nguyen to: 2 3 5 13 89",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/fibonacci_prime_less_than_n_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C cơ bản"
},
{
"id": "slide_loop_exercises_overview_c",
"topic": "Bài tập vòng lặp trong C",
"type": "text",
"content_for_embedding": "Tổng hợp các bài tập vòng lặp trong C giúp người học làm quen với cú pháp và cách sử dụng các vòng lặp cơ bản như for, while, do-while và vòng lặp lồng nhau. Nội dung bao gồm các bài tập in dãy số tăng giảm, in bảng số, bảng nhân, bảng cửu chương, in số chẵn và số lẻ, từ đó rèn luyện tư duy lặp và điều kiện trong lập trình C.",
"metadata": {
"raw_text": "Bài tập vòng lặp trong C\n\nBài này tổng hợp các bài tập vòng lặp trong C giúp bạn làm quen cú pháp và cách sử dụng của các vòng lặp C cơ bản: vòng lặp for, vòng lặp while, vòng lặp do-while và vòng lặp lồng nhau.\n\nCác bài tập bao gồm:\n\n1. In các số từ 1 đến 10 theo thứ tự tăng dần bằng vòng lặp for.\n\n2. In các số từ 1 đến 10 theo thứ tự giảm dần bằng vòng lặp for.\n\n3. In bảng số từ 1 đến 100 với 10 hàng và 10 cột, sử dụng vòng lặp lồng nhau.\n\n4. In bảng nhân của một số bất kỳ với các số từ 1 đến 10.\n\n5. In bảng cửu chương rút gọn từ 2 đến 10 bằng vòng lặp lồng nhau.\n\n6. In các số chẵn trong dãy từ 1 đến 10 bằng cách kết hợp vòng lặp và câu lệnh if.\n\n7. In các số lẻ trong dãy từ 1 đến 10 bằng cách kết hợp vòng lặp và câu lệnh if.\n\nCác bài tập này giúp người học nắm vững cách sử dụng vòng lặp, điều kiện rẽ nhánh và lồng vòng lặp trong lập trình C.",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/loop_exercises_overview_c.png",
"page_number": null,
"knowledge_type": [
"Khái niệm",
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập vòng lặp"
},
{
"id": "slide_draw_equilateral_triangle_c",
"topic": "Vẽ tam giác đều trong C",
"type": "exercise",
"content_for_embedding": "Bài tập yêu cầu viết chương trình C sử dụng ký tự sao để vẽ tam giác đều. Lời giải sử dụng các vòng lặp lồng nhau, trong đó một vòng lặp điều khiển số hàng, một vòng lặp in khoảng trắng để căn chỉnh hình và một vòng lặp in dấu sao. Có hai dạng tam giác: tam giác có đỉnh hướng lên trên và tam giác có đỉnh hướng xuống dưới.",
"metadata": {
"raw_text": "Vẽ tam giác đều trong C\n\nBài tập: vẽ tam giác đều trong C (1)\n\nĐề bài\nViết chương trình C sử dụng ký tự * để vẽ tam giác đều sao cho:\n- Các cạnh bằng nhau\n- Một đỉnh nằm phía trên màn hình, cạnh đối diện nằm phía dưới\n\nLời giải\nSử dụng ba vòng lặp lồng nhau: một vòng lặp điều khiển số hàng, một vòng lặp in khoảng trắng và một vòng lặp in dấu sao.\n\n#include <stdio.h>\n\nint main() {\n int n, i, j;\n n = 6;\n printf(\"Ve tam giac sao deu:\\n\");\n for(i = 1; i <= n; i++) {\n for(j = 1; j <= n - i; j++)\n printf(\" \");\n for(j = 1; j <= i; j++)\n printf(\"* \");\n printf(\"\\n\");\n }\n return 1;\n}\n\n---\n\nBài tập: vẽ tam giác đều trong C (2)\n\nĐề bài\nViết chương trình C sử dụng ký tự * để vẽ tam giác đều sao cho:\n- Các cạnh bằng nhau\n- Một đỉnh nằm phía dưới màn hình, cạnh đối diện nằm phía trên\n\nLời giải\nCũng sử dụng ba vòng lặp lồng nhau, thay đổi cách in khoảng trắng và dấu sao.\n\n#include <stdio.h>\n\nint main() {\n int n, i, j;\n n = 6;\n printf(\"Ve tam giac sao deu:\\n\");\n for(i = 1; i <= n; i++) {\n for(j = 1; j < i; j++)\n printf(\" \");\n for(j = i; j <= n; j++)\n printf(\"* \");\n printf(\"\\n\");\n }\n return 1;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/draw_equilateral_triangle_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập vòng lặp"
},
{
"id": "slide_draw_right_isosceles_triangle_c",
"topic": "Vẽ tam giác vuông cân trong C",
"type": "exercise",
"content_for_embedding": "Bài tập yêu cầu viết chương trình C sử dụng ký tự sao để vẽ tam giác vuông cân. Lời giải sử dụng các vòng lặp lồng nhau, trong đó vòng lặp ngoài điều khiển số hàng và vòng lặp trong in dấu sao hoặc khoảng trắng để tạo hình. Có nhiều biến thể của tam giác vuông cân tùy theo vị trí cạnh góc vuông và cạnh huyền.",
"metadata": {
"raw_text": "Vẽ tam giác vuông cân trong C\n\nBài tập: vẽ tam giác vuông cân trong C (1)\n\nĐề bài\nVẽ tam giác sao vuông cân sao cho:\n- Cạnh góc vuông nằm cạnh trái màn hình\n- Cạnh góc vuông còn lại nằm phía dưới màn hình\n- Đỉnh nằm phía trên màn hình\n\nLời giải\nSử dụng hai vòng lặp lồng nhau, vòng lặp ngoài điều khiển số hàng, vòng lặp trong in dấu sao.\n\n#include <stdio.h>\n\nint main() {\n int n, i, j;\n n = 6;\n printf(\"Ve tam giac sao vuong can:\\n\");\n for(i = 1; i <= n; i++) {\n for(j = 1; j <= i; j++)\n printf(\"* \");\n printf(\"\\n\");\n }\n return 0;\n}\n\n---\n\nBài tập: vẽ tam giác vuông cân trong C (2)\n\nĐề bài\nVẽ tam giác sao vuông cân sao cho:\n- Cạnh huyền nằm về phía trái màn hình\n\nLời giải\nSử dụng hai vòng lặp lồng nhau, một vòng in khoảng trắng, một vòng in dấu sao.\n\n#include <stdio.h>\n\nint main() {\n int n, i, j;\n n = 6;\n printf(\"Ve tam giac sao vuong can:\\n\");\n for(i = 0; i < n; i++) {\n for(j = 0; j < i; j++)\n printf(\" \");\n for(j = i; j < n; j++)\n printf(\" *\");\n printf(\"\\n\");\n }\n return 0;\n}\n\n---\n\nBài tập: vẽ tam giác vuông cân trong C (3)\n\nĐề bài\nVẽ tam giác sao vuông cân sao cho:\n- Một cạnh góc vuông nằm cạnh trái màn hình\n- Cạnh góc vuông còn lại nằm phía trên màn hình\n\nLời giải\nSử dụng hai vòng lặp lồng nhau để in số lượng dấu sao giảm dần theo từng hàng.\n\n#include <stdio.h>\n\nint main() {\n int n, i, j;\n n = 6;\n printf(\"Ve tam giac sao vuong can:\\n\");\n for(i = n; i >= 1; i--) {\n for(j = 1; j <= i; j++)\n printf(\"* \");\n printf(\"\\n\");\n }\n return 0;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/draw_right_isosceles_triangle_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập vòng lặp"
},
{
"id": "slide_draw_floyd_triangle_c",
"topic": "Vẽ tam giác Floyd trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C vẽ tam giác Floyd, là một dạng tam giác vuông được tạo từ các số tự nhiên tăng dần liên tiếp. Lời giải sử dụng hai vòng lặp lồng nhau, trong đó vòng lặp ngoài điều khiển số hàng của tam giác và vòng lặp trong in ra các số tăng dần theo từng hàng.",
"metadata": {
"raw_text": "Vẽ tam giác Floyd trong C\n\nBài tập\nViết chương trình C vẽ tam giác Floyd trong C.\n\nTam giác Floyd là một tam giác vuông được tạo từ các số tự nhiên. Các số trong tam giác Floyd có giá trị tăng dần.\n\nLời giải\nSử dụng hai vòng lặp lồng nhau. Vòng lặp bên ngoài điều khiển số hàng, vòng lặp bên trong in ra các số tự nhiên tăng dần.\n\n#include <stdio.h>\n\nint main() {\n int n, i, j, k = 1;\n n = 6;\n printf(\"Ve tam giac Floyd:\\n\");\n for (i = 1; i <= n; i++) {\n for (j = 1; j <= i; j++)\n printf(\"%3d\", k++);\n printf(\"\\n\");\n }\n return 0;\n}\n\nKet qua:\nBai tap C - Ve tam giac Floyd trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/draw_floyd_triangle_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập vòng lặp"
},
{
"id": "slide_draw_pascal_triangle_c",
"topic": "Vẽ tam giác Pascal trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C vẽ tam giác Pascal. Tam giác Pascal được xây dựng dựa trên quy tắc mỗi phần tử bằng tổng của hai phần tử liền kề ở hàng trước đó. Lời giải sử dụng ba vòng lặp lồng nhau để căn chỉnh khoảng trắng và in ra các hệ số tổ hợp C(n, k), trong đó giá trị tổ hợp được tính thông qua hàm giai thừa.",
"metadata": {
"raw_text": "Vẽ tam giác Pascal trong C\n\nBài tập\nViết chương trình C vẽ tam giác Pascal trong C.\n\nTam giác Pascal có quy tắc sau:\n- Các giá trị bên ngoài tam giác được xem như là 0.\n- Hàng đầu tiên là 0 1 0, trong đó chỉ có giá trị 1 được hiển thị.\n- Các hàng tiếp theo được tạo bằng cách cộng hai số liên tiếp nhau của hàng trước đó.\n\nVí dụ:\nHàng thứ ba được tạo từ hàng thứ hai bằng cách cộng (0 + 1), (1 + 1), (1 + 0).\n\nLời giải\nSử dụng ba vòng lặp lồng nhau: một vòng lặp điều khiển số hàng, một vòng lặp in khoảng trống và một vòng lặp in các giá trị của tam giác Pascal.\n\n#include <stdio.h>\n\nint factorial(int n) {\n int f;\n for (f = 1; n > 1; n--)\n f *= n;\n return f;\n}\n\nint ncr(int n, int r) {\n return factorial(n) / (factorial(n - r) * factorial(r));\n}\n\nint main() {\n int n, i, j;\n n = 6;\n printf(\"Ve tam giac Pascal:\\n\");\n for (i = 0; i <= n; i++) {\n for (j = 0; j <= n - i; j++)\n printf(\" \");\n for (j = 0; j <= i; j++)\n printf(\" %3d\", ncr(i, j));\n printf(\"\\n\");\n }\n return 0;\n}\n\nKet qua:\nBai tap C - Ve tam giac Pascal trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/draw_pascal_triangle_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập vòng lặp"
},
{
"id": "slide_print_array_1d_c",
"topic": "In các phần tử của một mảng trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để in các phần tử của một mảng một chiều ra màn hình. Lời giải sử dụng vòng lặp for để duyệt mảng từ phần tử đầu tiên đến phần tử cuối cùng, đồng thời có thể duyệt ngược mảng bằng cách lặp từ chỉ số cuối về chỉ số đầu.",
"metadata": {
"raw_text": "In các phần tử của một mảng trong C\n\nĐề bài\nViết chương trình C in các phần tử của một mảng ra màn hình.\n\nChương trình C để in mảng\nKhai báo và định nghĩa một mảng, sau đó sử dụng vòng lặp để duyệt và in các phần tử từ đầu đến cuối mảng.\n\n#include <stdio.h>\n\nint main() {\n int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int i;\n int size = sizeof arr / sizeof arr[0];\n printf(\"In tat ca phan tu cua mang: \\n\");\n for(i = 0; i < size; i++) {\n printf(\"%d \", arr[i]);\n }\n return 0;\n}\n\n---\n\nChương trình C để in mảng theo chiều ngược lại\nSử dụng vòng lặp for duyệt mảng từ phần tử cuối cùng về phần tử đầu tiên.\n\n#include <stdio.h>\n\nint main() {\n int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int i;\n int size = sizeof arr / sizeof arr[0];\n printf(\"In tat ca phan tu cua mang theo chieu nguoc: \\n\");\n for(i = size - 1; i >= 0; i--) {\n printf(\"%d \", arr[i]);\n }\n return 0;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/print_array_1d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_input_array_1d_c",
"topic": "Nhập mảng từ bàn phím trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C nhập một mảng số nguyên từ bàn phím. Lời giải sử dụng vòng lặp for để lần lượt nhập từng phần tử của mảng dựa trên số lượng phần tử do người dùng nhập, sau đó duyệt lại mảng để in các phần tử ra màn hình.",
"metadata": {
"raw_text": "Nhập mảng từ bàn phím trong C\n\nBài tập C: Nhập mảng từ bàn phím trong C\n\nĐề bài\nViết chương trình C nhập một mảng số nguyên từ bàn phím.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int i, number;\n printf(\"Nhap so phan tu cua mang: \");\n scanf(\"%d\", &number);\n int arr[number];\n printf(\"Nhap cac phan tu cua mang: \\n\");\n for (i = 0; i < number; i++) {\n printf(\"a[%d] = \", i);\n scanf(\"%d\", &arr[i]);\n }\n printf(\"Cac phan tu cua mang: \\n\");\n for (i = 0; i < number; i++) {\n printf(\"%d \", arr[i]);\n }\n return 0;\n}\n\nKet qua:\nBai tap C - Nhap mang trong C tu ban phim",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/input_array_1d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_sum_array_1d_c",
"topic": "Tính tổng giá trị của một mảng trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C tính tổng các phần tử của một mảng một chiều. Lời giải sử dụng vòng lặp for để duyệt lần lượt từng phần tử của mảng và cộng dồn giá trị của chúng vào một biến tổng.",
"metadata": {
"raw_text": "Tính tổng giá trị của một mảng trong C\n\nBài tập C: Tính tổng giá trị của một mảng trong C\n\nĐề bài\nViết chương trình C tính tổng giá trị của một mảng.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int i, total = 0;\n int size = sizeof arr / sizeof arr[0];\n for (i = 0; i < size; i++) {\n total = total + arr[i];\n }\n printf(\"Tong cac gia tri cua mang la: %d \", total);\n return 0;\n}\n\nKet qua:\nBai tap C - Tinh tong gia tri cua mot mang trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/sum_array_1d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_average_array_1d_c",
"topic": "Tính giá trị trung bình của một mảng trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C tính giá trị trung bình của một mảng một chiều. Lời giải sử dụng vòng lặp để duyệt mảng và tính tổng các phần tử, sau đó chia tổng này cho số lượng phần tử trong mảng. Khi tính trung bình, cần ép kiểu sang số thực để đảm bảo kết quả chính xác.",
"metadata": {
"raw_text": "Tính giá trị trung bình của một mảng trong C\n\nBài tập C: Tính giá trị trung bình của mảng\n\nĐề bài\nViết chương trình C tính giá trị trung bình của mảng.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int i, total = 0;\n int size = sizeof arr / sizeof arr[0];\n\n printf(\"In tat ca phan tu cua mang: \\n\");\n for (i = 0; i < size; i++) {\n printf(\"%d \", arr[i]);\n }\n\n for (i = 0; i < size; i++) {\n total = total + arr[i];\n }\n\n printf(\"\\nGia tri trung binh cua mang la: %f\", (float) total / size);\n return 0;\n}\n\nKet qua:\nTinh gia tri trung binh cua mot mang trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/average_array_1d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_copy_array_1d_c",
"topic": "Sao chép các giá trị của mảng này sang mảng khác trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C sao chép các phần tử của một mảng một chiều sang mảng khác. Lời giải sử dụng vòng lặp for để duyệt từng phần tử của mảng ban đầu và gán giá trị tương ứng cho mảng sao chép. Ngoài ra, có thể sao chép mảng theo thứ tự đảo chiều bằng cách thay đổi chỉ số khi gán phần tử.",
"metadata": {
"raw_text": "Sao chép các giá trị của mảng này sang mảng khác trong C\n\nĐề bài\nViết chương trình C sao chép các giá trị của mảng này sang mảng khác.\n\nMảng sao chép phải có cùng độ dài với mảng ban đầu. Sử dụng vòng lặp để duyệt qua từng phần tử và sao chép giá trị tương ứng.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int arr_copy[10];\n int i;\n for (i = 0; i < 10; i++) {\n arr_copy[i] = arr[i];\n }\n printf(\"Sao chep mang trong C:\\n\\n\");\n printf(\"Mang ban dau -> Mang sao chep \\n\");\n for (i = 0; i < 10; i++) {\n printf(\" %2d %2d\\n\", arr[i], arr_copy[i]);\n }\n return 0;\n}\n\n---\n\nBài tập C: sao chép mảng theo thứ tự đảo chiều\n\nĐề bài\nViết chương trình C sao chép các giá trị của mảng này sang mảng khác theo thứ tự đảo chiều.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int arr_copy[10];\n int i;\n for (i = 0; i < 10; i++) {\n arr_copy[9 - i] = arr[i];\n }\n printf(\"Sao chep mang trong C:\\n\\n\");\n printf(\"Mang ban dau -> Mang sao chep \\n\");\n for (i = 0; i < 10; i++) {\n printf(\" %2d %2d\\n\", arr[i], arr_copy[i]);\n }\n return 0;\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/copy_array_1d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_split_array_even_odd_c",
"topic": "Chia một mảng thành hai mảng chẵn và lẻ trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C chia một mảng một chiều thành hai mảng riêng biệt: mảng chứa các số chẵn và mảng chứa các số lẻ. Lời giải sử dụng vòng lặp để duyệt từng phần tử của mảng ban đầu và toán tử chia dư để xác định tính chẵn lẻ, sau đó lưu giá trị vào mảng tương ứng.",
"metadata": {
"raw_text": "Chia một mảng thành hai mảng trong C\n\nĐề bài\nViết chương trình C để chia một mảng thành hai mảng khác nhau. Nếu phần tử là số chẵn thì lưu vào mảng chẵn (even), nếu là số lẻ thì lưu vào mảng lẻ (odd).\n\nLời giải\nSử dụng vòng lặp for để duyệt mảng và toán tử % để kiểm tra số chẵn hay lẻ.\n\n#include <stdio.h>\n\nint main() {\n int arr[11] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};\n int even[11], odd[11];\n int i, e, d;\n e = d = 0;\n\n for (i = 0; i < 11; i++) {\n if (arr[i] % 2 == 0) {\n even[e] = arr[i];\n e++;\n } else {\n odd[d] = arr[i];\n d++;\n }\n }\n\n printf(\"Chia mot mang thanh hai mang trong C:\\n\\n\");\n printf(\"Mang ban dau -> \");\n for (i = 0; i < 11; i++) {\n printf(\" %d\", arr[i]);\n }\n\n printf(\"\\nMang chan -> \");\n for (i = 0; i < e; i++) {\n printf(\" %d\", even[i]);\n }\n\n printf(\"\\nMang le -> \");\n for (i = 0; i < d; i++) {\n printf(\" %d\", odd[i]);\n }\n\n return 0;\n}\n\nKet qua:\nChia mot mang thanh hai mang trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/split_array_even_odd_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_merge_two_arrays_1d_c",
"topic": "Trộn hai mảng thành một mảng trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để trộn hai mảng một chiều thành một mảng duy nhất. Lời giải sử dụng một mảng mới có kích thước bằng tổng kích thước hai mảng ban đầu, sau đó dùng vòng lặp để lần lượt sao chép các phần tử của từng mảng vào mảng mới theo thứ tự.",
"metadata": {
"raw_text": "Trộn hai mảng thành một mảng trong C\n\nĐề bài\nViết chương trình C để trộn (ghép, nối) hai mảng thành một mảng duy nhất.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int even[5] = {0, 2, 4, 6, 8};\n int odd[6] = {1, 3, 5, 7, 9, 11};\n\n int i, index;\n int eSize = 5;\n int oSize = 6;\n\n int arr[eSize + oSize];\n index = 0;\n\n for (i = 0; i < eSize; i++) {\n arr[index] = even[i];\n index++;\n }\n\n for (i = 0; i < oSize; i++) {\n arr[index] = odd[i];\n index++;\n }\n\n printf(\"Tron hai mang thanh mot mang:\\n\\n\");\n\n printf(\"Mang chan: \");\n for (i = 0; i < eSize; i++)\n printf(\" %d\", even[i]);\n\n printf(\"\\nMang le: \");\n for (i = 0; i < oSize; i++)\n printf(\" %d\", odd[i]);\n\n printf(\"\\nMang sau khi tron: \");\n for (i = 0; i < eSize + oSize; i++)\n printf(\" %d\", arr[i]);\n\n return 0;\n}\n\nKet qua:\nTron hai mang thanh mot mang trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/merge_two_arrays_1d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 1 chiều"
},
{
"id": "slide_input_matrix_2d_c",
"topic": "Nhập ma trận từ bàn phím trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C nhập một ma trận (mảng hai chiều) từ bàn phím. Lời giải sử dụng hai vòng lặp lồng nhau để lần lượt nhập các phần tử theo hàng và cột, sau đó duyệt lại ma trận để in các giá trị ra màn hình.",
"metadata": {
"raw_text": "Nhập ma trận từ bàn phím trong C\n\nĐề bài\nViết chương trình C để nhập một ma trận (mảng 2 chiều) từ bàn phím.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int i, j;\n int col, row;\n\n printf(\"Nhap so cot cua ma tran: \");\n scanf(\"%d\", &col);\n printf(\"Nhap so hang cua ma tran: \");\n scanf(\"%d\", &row);\n\n int matrix[col][row];\n\n printf(\"Nhap cac phan tu cua ma tran: \\n\");\n for (i = 0; i < row; i++) {\n for (j = 0; j < col; j++) {\n printf(\"matrix[%d][%d] = \", i, j);\n scanf(\"%d\", &matrix[i][j]);\n }\n }\n\n printf(\"Cac phan tu cua ma tran: \\n\");\n for (i = 0; i < row; i++) {\n for (j = 0; j < col; j++) {\n printf(\"%d \", matrix[i][j]);\n }\n printf(\"\\n\");\n }\n\n return 0;\n}\n\nKet qua:\nNhap ma tran tu ban phim trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/input_matrix_2d_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 2 chiều"
},
{
"id": "slide_subtract_two_matrices_c",
"topic": "Trừ hai ma trận trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C thực hiện phép trừ hai ma trận. Hai ma trận chỉ có thể trừ được khi chúng có cùng số hàng và số cột. Lời giải sử dụng mảng hai chiều để lưu trữ các ma trận, kiểm tra điều kiện kích thước và dùng hai vòng lặp lồng nhau để trừ các phần tử tương ứng.",
"metadata": {
"raw_text": "Trừ hai ma trận trong C\n\nĐề bài\nViết chương trình C để trừ hai ma trận. Hai ma trận chỉ có thể thực hiện phép trừ khi chúng có cùng kích thước.\n\nLời giải\n\n#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n int i, j;\n int matrix1[100][100], matrix2[100][100], matrix3[100][100];\n int row1, col1, row2, col2;\n\n printf(\"Tru hai ma tran trong C:\\n\\n\");\n printf(\"Nhap so hang cua matrix1: \");\n scanf(\"%d\", &row1);\n printf(\"Nhap so cot cua matrix1: \");\n scanf(\"%d\", &col1);\n\n printf(\"Nhap so hang cua matrix2: \");\n scanf(\"%d\", &row2);\n printf(\"Nhap so cot cua matrix2: \");\n scanf(\"%d\", &col2);\n\n if (row1 != row2 || col1 != col2) {\n printf(\"\\nHai ma tran khong cung kich co!\");\n exit(0);\n }\n\n printf(\"\\nNhap ma tran 1\\n\");\n for (i = 0; i < row1; i++) {\n for (j = 0; j < col1; j++) {\n printf(\"Nhap phan tu matrix1[%d][%d]: \", i, j);\n scanf(\"%d\", &matrix1[i][j]);\n }\n }\n\n printf(\"\\nNhap ma tran 2\\n\");\n for (i = 0; i < row2; i++) {\n for (j = 0; j < col2; j++) {\n printf(\"Nhap phan tu matrix2[%d][%d]: \", i, j);\n scanf(\"%d\", &matrix2[i][j]);\n }\n }\n\n for (i = 0; i < row1; i++) {\n for (j = 0; j < col1; j++) {\n matrix3[i][j] = matrix1[i][j] - matrix2[i][j];\n }\n }\n\n printf(\"\\nKet qua cua phep tru hai ma tran la:\\n\");\n for (i = 0; i < row1; i++) {\n for (j = 0; j < col1; j++) {\n printf(\"%d\\t\", matrix3[i][j]);\n }\n printf(\"\\n\");\n }\n\n return 0;\n}\n\nKet qua:\n- Truong hop hai ma tran khong cung kich co: hien thong bao loi\n- Truong hop hai ma tran cung kich co: hien thi ma tran ket qua",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/subtract_two_matrices_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 2 chiều"
},
{
"id": "slide_add_two_matrices_c",
"topic": "Cộng hai ma trận trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C thực hiện phép cộng hai ma trận. Hai ma trận chỉ có thể cộng được khi chúng có cùng số hàng và số cột. Lời giải sử dụng mảng hai chiều để lưu trữ dữ liệu, kiểm tra điều kiện kích thước và dùng hai vòng lặp lồng nhau để cộng các phần tử tương ứng.",
"metadata": {
"raw_text": "Cộng hai ma trận trong C\n\nĐề bài\nViết chương trình C để cộng hai ma trận. Hai ma trận chỉ có thể thực hiện phép cộng khi chúng có cùng kích thước.\n\nLời giải\n\n#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n int i, j;\n int matrix1[100][100], matrix2[100][100], matrix3[100][100];\n int row1, col1, row2, col2;\n\n printf(\"Cong hai ma tran trong C:\\n\\n\");\n printf(\"Nhap so hang cua matrix1: \");\n scanf(\"%d\", &row1);\n printf(\"Nhap so cot cua matrix1: \");\n scanf(\"%d\", &col1);\n\n printf(\"Nhap so hang cua matrix2: \");\n scanf(\"%d\", &row2);\n printf(\"Nhap so cot cua matrix2: \");\n scanf(\"%d\", &col2);\n\n if (row1 != row2 || col1 != col2) {\n printf(\"\\nHai ma tran khong cung kich co!\");\n exit(0);\n }\n\n printf(\"\\nNhap ma tran 1\\n\");\n for (i = 0; i < row1; i++) {\n for (j = 0; j < col1; j++) {\n printf(\"Nhap phan tu matrix1[%d][%d]: \", i, j);\n scanf(\"%d\", &matrix1[i][j]);\n }\n }\n\n printf(\"\\nNhap ma tran 2\\n\");\n for (i = 0; i < row2; i++) {\n for (j = 0; j < col2; j++) {\n printf(\"Nhap phan tu matrix2[%d][%d]: \", i, j);\n scanf(\"%d\", &matrix2[i][j]);\n }\n }\n\n for (i = 0; i < row1; i++) {\n for (j = 0; j < col1; j++) {\n matrix3[i][j] = matrix1[i][j] + matrix2[i][j];\n }\n }\n\n printf(\"\\nKet qua cua phep cong hai ma tran la:\\n\");\n for (i = 0; i < row1; i++) {\n for (j = 0; j < col1; j++) {\n printf(\"%d\\t\", matrix3[i][j]);\n }\n printf(\"\\n\");\n }\n\n return 0;\n}\n\nKet qua:\n- Truong hop hai ma tran khong cung kich co: hien thong bao loi\n- Truong hop hai ma tran cung kich co: hien thi ma tran ket qua",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/add_two_matrices_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 2 chiều"
},
{
"id": "slide_sum_matrix_elements_c",
"topic": "Tính tổng tất cả các phần tử của ma trận trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để tính tổng tất cả các phần tử của một ma trận. Lời giải sử dụng mảng hai chiều để lưu trữ ma trận và hai vòng lặp lồng nhau để duyệt qua từng phần tử theo hàng và cột, sau đó cộng dồn các giá trị vào một biến tổng.",
"metadata": {
"raw_text": "Tính tổng tất cả các phần tử của ma trận trong C\n\nĐề bài\nViết chương trình C để tính tổng tất cả các phần tử của ma trận.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n int i, j, matrix[100][100], row, col;\n int sum = 0;\n\n printf(\"Chuong trinh tinh tong cac phan tu cua ma tran.\\n\\n\");\n printf(\"Nhap so hang cua ma tran: \");\n scanf(\"%d\", &row);\n\n printf(\"Nhap so cot cua ma tran: \");\n scanf(\"%d\", &col);\n\n printf(\"Nhap ma tran: \\n\");\n for (i = 0; i < row; i++) {\n for (j = 0; j < col; j++) {\n printf(\"Nhap phan tu matrix[%d][%d] : \", i, j);\n scanf(\"%d\", &matrix[i][j]);\n }\n }\n\n for (i = 0; i < row; i++) {\n for (j = 0; j < col; j++) {\n sum = sum + matrix[i][j];\n }\n }\n\n printf(\"Tong tat ca cac phan tu cua ma tran la: %d\", sum);\n return 0;\n}\n\nKet qua:\nTinh tong tat ca cac phan tu cua ma tran trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/sum_matrix_elements_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập mảng 2 chiều"
},
{
"id": "slide_input_string_c",
"topic": "Nhập chuỗi từ bàn phím trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C nhập một chuỗi từ bàn phím và in chuỗi đó ra màn hình. Lời giải sử dụng hàm gets() để đọc chuỗi ký tự và hàm puts() để hiển thị chuỗi. Qua bài tập này, người học làm quen với cách xử lý chuỗi ký tự trong C.",
"metadata": {
"raw_text": "Nhập chuỗi từ bàn phím trong C\n\nĐề bài\nViết chương trình C nhập một chuỗi từ bàn phím và in chuỗi đó ra màn hình.\n\nHàm gets() được sử dụng để đọc chuỗi từ bàn phím trong C và hàm puts() được sử dụng để in chuỗi ra màn hình. Hai hàm này được định nghĩa trong thư viện stdio.h.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n char name[50];\n printf(\"Enter your name: \");\n gets(name);\n printf(\"Your name is: \");\n puts(name);\n return 0;\n}\n\nKet qua:\nEnter your name: Tran Van Vinh\nYour name is: Tran Van Vinh",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/input_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_print_string_c",
"topic": "In chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để in chuỗi ra màn hình. Lời giải minh họa hai trường hợp: in một chuỗi được khai báo sẵn và in một chuỗi được nhập từ bàn phím. Qua đó, người học làm quen với cách sử dụng printf(), gets() và định dạng chuỗi trong C.",
"metadata": {
"raw_text": "In chuỗi trong C\n\nĐề bài\nViết chương trình C để in một chuỗi ra màn hình.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n char str[] = \"Hello World\";\n printf(\"%s\\n\", str);\n return 0;\n}\n\n---\n\nBài tập C: In chuỗi nhập từ bàn phím trong C\n\nĐề bài\nViết chương trình C để in một chuỗi được nhập từ bàn phím ra màn hình.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n char name[50];\n printf(\"Nhap chuoi: \");\n gets(name);\n printf(\"Chuoi ban nhap la: %s\", name);\n return 0;\n}\n\nKet qua:\nIn chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/print_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_string_length_c",
"topic": "Tìm độ dài chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để tìm độ dài của một chuỗi ký tự. Lời giải minh họa hai cách tiếp cận: cách thứ nhất duyệt từng ký tự trong chuỗi cho đến khi gặp ký tự kết thúc '\\0'; cách thứ hai sử dụng hàm strlen() có sẵn trong thư viện string.h để xác định độ dài chuỗi.",
"metadata": {
"raw_text": "Tìm độ dài chuỗi trong C\n\nĐề bài\nViết chương trình C để tìm độ dài của một chuỗi.\n\nLời giải (không sử dụng hàm)\n\n#include <stdio.h>\n\nint main() {\n char s1[] = \"hiepsiit.com\";\n int i = 0;\n while (s1[i] != '\\0') {\n i++;\n }\n printf(\"Do dai cua chuoi '%s' la: %d\", s1, i);\n return 0;\n}\n\nKet qua:\nDo dai cua chuoi 'hiepsiit.com' la: 12\n\n---\n\nLời giải (sử dụng hàm strlen)\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char str[100];\n int len;\n printf(\"\\nNhap mot chuoi bat ky: \");\n gets(str);\n len = strlen(str);\n printf(\"\\nDo dai cua chuoi la: %d\", len);\n return 0;\n}\n\nKet qua:\nTim do dai chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/string_length_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_count_char_in_string_c",
"topic": "Tìm số lần xuất hiện của một ký tự trong một chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C đếm số lần xuất hiện của một ký tự trong một chuỗi. Lời giải sử dụng vòng lặp để duyệt từng ký tự trong chuỗi cho đến ký tự kết thúc '\\0', so sánh từng ký tự với ký tự cần tìm và tăng biến đếm khi trùng khớp.",
"metadata": {
"raw_text": "Tìm số lần xuất hiện của một ký tự trong một chuỗi trong C\n\nĐề bài\nViết chương trình C tìm số lần xuất hiện của một ký tự trong một chuỗi.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n char s[] = \"hiepsiit.com\";\n char ch = 't';\n int i = 0;\n int count = 0;\n\n while (s[i] != '\\0') {\n if (s[i] == ch)\n count++;\n i++;\n }\n\n if (count > 0) {\n printf(\"Ky tu %c xuat hien %d lan trong chuoi '%s'\", ch, count, s);\n } else {\n printf(\"Ky tu %c khong co mat trong chuoi %s\", ch, s);\n }\n return 0;\n}\n\nKet qua:\nKy tu t xuat hien 1 lan trong chuoi 'hiepsiit.com'",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/count_char_in_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_sort_characters_in_string_c",
"topic": "Sắp xếp các ký tự của chuỗi theo thứ tự bảng chữ cái trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C sắp xếp các ký tự trong một chuỗi theo thứ tự bảng chữ cái. Lời giải sử dụng hàm strlen() để xác định độ dài chuỗi và hai vòng lặp lồng nhau để so sánh, hoán đổi các ký tự dựa trên giá trị ASCII, từ đó sắp xếp chuỗi theo thứ tự tăng dần.",
"metadata": {
"raw_text": "Sắp xếp các ký tự của chuỗi theo thứ tự bảng chữ cái trong C\n\nĐề bài\nViết chương trình C sắp xếp các ký tự của chuỗi theo thứ tự bảng chữ cái.\n\nLời giải\nSử dụng hàm strlen() để lấy độ dài chuỗi, sau đó dùng hai vòng lặp lồng nhau để sắp xếp các ký tự theo thứ tự ASCII.\n\n#include <stdio.h>\n#include <string.h>\n\nint main(void) {\n char string[] = \"hiepsiit.com\";\n char temp;\n int i, j;\n int size = strlen(string);\n\n printf(\"Chuoi truoc khi sap xep: %s \\n\", string);\n\n for (i = 0; i < size - 1; i++) {\n for (j = i + 1; j < size; j++) {\n if (string[i] > string[j]) {\n temp = string[i];\n string[i] = string[j];\n string[j] = temp;\n }\n }\n }\n\n printf(\"\\nChuoi sau khi sap xep %s \\n\", string);\n return 0;\n}\n\nKet qua:\nSap xep cac ky tu cua chuoi theo thu tu bang chu cai trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/sort_characters_in_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_copy_string_c",
"topic": "Sao chép chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C sao chép nội dung của một chuỗi sang một chuỗi khác. Lời giải minh họa hai cách tiếp cận: cách thứ nhất sử dụng vòng lặp để sao chép từng ký tự cho đến ký tự kết thúc '\\0'; cách thứ hai sử dụng hàm strcpy() trong thư viện string.h để sao chép chuỗi một cách trực tiếp.",
"metadata": {
"raw_text": "Sao chép chuỗi trong C\n\nĐề bài\nViết chương trình C để sao chép chuỗi.\n\nLời giải (không sử dụng hàm)\n\n#include <stdio.h>\n\nint main() {\n char s1[] = \"hiepsiit.com\";\n char s2[10];\n int length = 0;\n\n while (s1[length] != '\\0') {\n s2[length] = s1[length];\n length++;\n }\n\n s2[length] = '\\0';\n\n printf(\"Chuoi s1 = %s \\n\", s1);\n printf(\"Chuoi s2 = %s \\n\", s2);\n return 0;\n}\n\n---\n\nLời giải (sử dụng hàm strcpy)\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char str1[100];\n char str2[100];\n printf(\"Nhap chuoi str1: \");\n gets(str1);\n strcpy(str2, str1);\n printf(\"\\nChuoi sao chep la: %s\", str2);\n return 0;\n}\n\nKet qua:\nSao chep chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/copy_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_reverse_string_c",
"topic": "Đảo ngược chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để đảo ngược một chuỗi ký tự. Lời giải sử dụng vòng lặp để xác định độ dài chuỗi, sau đó duyệt ngược từ ký tự cuối cùng về ký tự đầu tiên nhằm in chuỗi đảo ngược và lưu kết quả vào một chuỗi đích.",
"metadata": {
"raw_text": "Đảo ngược chuỗi trong C\n\nĐề bài\nViết chương trình C để đảo ngược chuỗi.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n char s1[] = \"Hiepsiit.Com\";\n char s2[8];\n int length = 0;\n int i = 0;\n\n while (s1[length] != '\\0') {\n length++;\n }\n\n printf(\"\\nChuoi ban dau: %s\", s1);\n\n printf(\"\\nChuoi theo chieu dao nguoc: \");\n for (i = length - 1; i >= 0; i--) {\n printf(\"%c\", s1[i]);\n }\n\n i = 0;\n printf(\"\\nLuu giu chuoi nay trong chuoi dao nguoc: \");\n while (length >= 0) {\n s2[length] = s1[i];\n length--;\n i++;\n }\n\n s2[i] = '\\0';\n printf(\"%s\\n\", s2);\n\n return 0;\n}\n\nKet qua:\nDao nguoc chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/reverse_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_search_substring_c",
"topic": "Tìm kiếm chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C tìm kiếm một chuỗi con trong một chuỗi cho trước và đếm số lần chuỗi con đó xuất hiện. Lời giải sử dụng vòng lặp để duyệt từng ký tự của chuỗi gốc, so sánh lần lượt với chuỗi con, kiểm tra điều kiện kết thúc '\\0' và tăng biến đếm khi tìm thấy chuỗi con hợp lệ.",
"metadata": {
"raw_text": "Tìm kiếm chuỗi trong C\n\nĐề bài\nViết chương trình C để tìm kiếm chuỗi con trong một chuỗi và đếm số lần chuỗi con đó xuất hiện.\n\nLời giải\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char s1[] = \"Hiepsiit hoc lap trinh online, hoc c, hoc c++, hoc java, ...\";\n char s2[] = \"hoc\";\n\n int n = 0;\n int m = 0;\n int times = 0;\n int len = strlen(s2);\n\n while (s1[n] != '\\0') {\n if (s1[n] == s2[m]) {\n while (s1[n] == s2[m] && s1[n] != '\\0') {\n n++;\n m++;\n }\n if (m == len && (s1[n] == ' ' || s1[n] == '\\0')) {\n times++;\n }\n } else {\n while (s1[n] != ' ') {\n n++;\n if (s1[n] == '\\0') break;\n }\n }\n n++;\n m = 0;\n }\n\n if (times > 0) {\n printf(\"Chuoi '%s' xuat hien %d lan\\n\", s2, times);\n } else {\n printf(\"Chuoi '%s' khong xuat hien trong cau.\\n\", s2);\n }\n return 0;\n}\n\nKet qua:\nTim kiem chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/search_substring_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_compare_two_strings_c",
"topic": "So sánh hai chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để so sánh hai chuỗi ký tự và xác định xem chúng có giống nhau hay không. Lời giải sử dụng vòng lặp để duyệt từng ký tự tương ứng của hai chuỗi, so sánh từng cặp ký tự theo chỉ mục và đưa ra kết luận khi phát hiện sự khác nhau hoặc khi kết thúc chuỗi.",
"metadata": {
"raw_text": "So sánh hai chuỗi trong C\n\nĐề bài\nViết chương trình C để so sánh hai chuỗi và xác định xem chúng có giống nhau hay không.\n\nLời giải\n\n#include <stdio.h>\n\nint main() {\n char s1[50];\n char s2[50];\n int n = 0;\n short flag = 1;\n\n printf(\"Nhap chuoi s1: \");\n gets(s1);\n printf(\"Nhap chuoi s2: \");\n gets(s2);\n\n while (s1[n] != '\\0') {\n if (s1[n] != s2[n]) {\n flag = 0;\n break;\n }\n n++;\n }\n\n if (flag == 1) {\n printf(\"Chuoi %s va chuoi %s la giong nhau.\", s1, s2);\n } else {\n printf(\"Chuoi %s va chuoi %s la khac nhau.\", s1, s2);\n }\n return 0;\n}\n\nKet qua:\nSo sanh hai chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/compare_two_strings_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_concat_string_c",
"topic": "Nối chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để nối hai chuỗi ký tự thành một chuỗi duy nhất. Lời giải minh họa hai cách tiếp cận: cách thứ nhất sử dụng vòng lặp và hàm strlen() để nối thủ công từng ký tự; cách thứ hai sử dụng các hàm chuẩn strcpy() và strcat() trong thư viện string.h để thực hiện nối chuỗi một cách trực tiếp.",
"metadata": {
"raw_text": "Nối chuỗi trong C\n\nĐề bài\nViết chương trình C để nối hai chuỗi ký tự thành một chuỗi duy nhất.\n\nLời giải (không sử dụng hàm)\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char s1[10] = \"hiepsiit\";\n char s2[] = \".com\";\n int i, j, n1, n2;\n\n n1 = strlen(s1);\n n2 = strlen(s2);\n\n j = 0;\n for (i = n1; i < n1 + n2; i++) {\n s1[i] = s2[j];\n j++;\n }\n s1[i] = '\\0';\n\n printf(\"\\nKet qua sau khi noi chuoi la:\\n\");\n printf(\"%s\", s1);\n return 0;\n}\n\nKet qua:\nhiepsiit.com\n\n---\n\nLời giải (sử dụng hàm)\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char str1[100];\n char str2[100];\n char str3[100];\n\n printf(\"Nhap chuoi 1: \");\n gets(str1);\n printf(\"Nhap chuoi 2: \");\n gets(str2);\n\n strcpy(str3, str1);\n strcat(str3, str2);\n\n printf(\"\\nNoi chuoi: %s\", str3);\n return 0;\n}\n\nKet qua:\nNoi chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/concat_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_reverse_each_word_in_string_c",
"topic": "Đảo ngược các ký tự của từng từ trong chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C đảo ngược các ký tự của từng từ trong một chuỗi, trong khi vẫn giữ nguyên thứ tự các từ. Lời giải sử dụng các hàm tự xây dựng để tính độ dài chuỗi và đảo ngược chuỗi, kết hợp với vòng lặp để tách từng từ, đảo ngược và ghép lại thành chuỗi kết quả.",
"metadata": {
"raw_text": "Đảo ngược các ký tự của từng từ của một chuỗi trong C\n\nĐề bài\nViết chương trình C để đảo ngược các ký tự của từng từ trong một chuỗi.\n\nVí dụ:\nChuỗi ban đầu: Toi Yeu Lap Trinh\nChuỗi sau khi xử lý: ioT ueY paL hnirT\n\nLời giải\n\n#include <stdio.h>\n#include <string.h>\n\nint string_length(char s[]) {\n int i = 0;\n while (s[i] != '\\0')\n i++;\n return i;\n}\n\nvoid string_reverse(char str[]) {\n int i = 0;\n int j = string_length(str) - 1;\n char ch;\n while (i < j) {\n ch = str[j];\n str[j] = str[i];\n str[i] = ch;\n i++;\n j--;\n }\n}\n\nint main(void) {\n char s1[] = \"Toi Yeu Lap Trinh\";\n char reverse[100] = \"\";\n char temp[50];\n int i, j, n;\n\n n = string_length(s1);\n\n for (i = 0; i < n; i++) {\n for (j = 0; i < n && s1[i] != ' '; ++i, ++j) {\n temp[j] = s1[i];\n }\n temp[j] = '\\0';\n string_reverse(temp);\n strcat(reverse, temp);\n strcat(reverse, \" \");\n }\n\n printf(\"Chuoi ban dau:\\n %s\", s1);\n printf(\"\\nChuoi sau khi da dao nguoc:\\n %s\", reverse);\n return 0;\n}\n\nKet qua:\nDao nguoc cac ky tu cua tung tu trong chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/reverse_each_word_in_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_reverse_word_order_in_string_c",
"topic": "Đảo ngược thứ tự từ của một chuỗi trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để đảo ngược thứ tự các từ trong một chuỗi, trong khi vẫn giữ nguyên thứ tự các ký tự trong từng từ. Lời giải sử dụng vòng lặp duyệt chuỗi từ cuối về đầu, tách từng từ, đảo ngược lại từ đó để đúng chiều và ghép vào chuỗi kết quả.",
"metadata": {
"raw_text": "Đảo ngược thứ tự từ của một chuỗi trong C\n\nĐề bài\nViết chương trình C để đảo ngược thứ tự các từ trong một chuỗi.\n\nVí dụ:\nChuỗi ban đầu: Toi Yeu Lap Trinh\nChuỗi sau khi xử lý: Trinh Lap Yeu Toi\n\nLời giải\n\n#include <stdio.h>\n#include <string.h>\n\nint string_length(char s[]) {\n int i = 0;\n while (s[i] != '\\0')\n i++;\n return i;\n}\n\nvoid string_reverse(char str[]) {\n int i = 0;\n int j = string_length(str) - 1;\n char ch;\n while (i < j) {\n ch = str[j];\n str[j] = str[i];\n str[i] = ch;\n i++;\n j--;\n }\n}\n\nint main(void) {\n char s1[] = \"Toi Yeu Lap Trinh\";\n char reverse[100] = \"\";\n char temp[50];\n int i, j, n;\n\n n = string_length(s1);\n\n for (i = n - 1; i >= 0; --i) {\n for (j = 0; i >= 0 && s1[i] != ' '; --i, ++j)\n temp[j] = s1[i];\n\n temp[j] = '\\0';\n string_reverse(temp);\n strcat(reverse, temp);\n strcat(reverse, \" \");\n }\n\n printf(\"Chuoi ban dau:\\n %s\", s1);\n printf(\"\\nChuoi sau khi da duoc dao nguoc:\\n %s\", reverse);\n return 0;\n}\n\nKet qua:\nDao nguoc thu tu tu cua mot chuoi trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/reverse_word_order_in_string_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_sort_strings_alphabetically_c",
"topic": "Sắp xếp các chuỗi theo thứ tự chữ cái trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C sắp xếp một danh sách các chuỗi theo thứ tự chữ cái. Lời giải sử dụng hàm strcmp() để so sánh hai chuỗi theo thứ tự từ điển và dùng các vòng lặp lồng nhau kết hợp với hàm strcpy() để hoán đổi vị trí các chuỗi khi cần thiết.",
"metadata": {
"raw_text": "Sắp xếp các chuỗi theo thứ tự chữ cái trong C\n\nĐề bài\nViết chương trình C để sắp xếp các chuỗi theo thứ tự chữ cái.\n\nLời giải\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char s[4][20];\n char t[20];\n int i, j;\n int size = 4;\n\n printf(\"\\nNhap 4 chuoi bat ky: \\n\");\n for (i = 0; i < size; i++) {\n scanf(\"%s\", s[i]);\n }\n\n for (i = 1; i < size; i++) {\n for (j = 1; j < size; j++) {\n if (strcmp(s[j - 1], s[j]) > 0) {\n strcpy(t, s[j - 1]);\n strcpy(s[j - 1], s[j]);\n strcpy(s[j], t);\n }\n }\n }\n\n printf(\"\\nSap xep thu tu cua cac chuoi:\");\n for (i = 0; i < size; i++) {\n printf(\"\\n%s\", s[i]);\n }\n return 0;\n}\n\nKet qua:\nSap xep cac chuoi theo thu tu chu cai trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/sort_strings_alphabetically_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_string_to_integer_c",
"topic": "Chuyển đổi chuỗi thành số nguyên trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C chuyển đổi một chuỗi ký tự sang số nguyên. Lời giải sử dụng hàm atoi() trong thư viện stdlib.h, hàm này đọc các ký tự số liên tiếp ở đầu chuỗi và chuyển chúng thành giá trị số nguyên tương ứng, bỏ qua các ký tự không phải số theo sau.",
"metadata": {
"raw_text": "Chuyển đổi chuỗi thành số nguyên trong C\n\nĐề bài\nViết chương trình C để chuyển đổi chuỗi thành số nguyên. Ví dụ: nhập chuỗi '20ab100' thì kết quả nhận được là 20.\n\nLời giải\nSử dụng hàm atoi() để chuyển đổi chuỗi sang số nguyên. Hàm atoi() sẽ đọc các ký tự số liên tiếp ở đầu chuỗi và trả về giá trị số nguyên tương ứng.\n\n#include <stdio.h>\n#include <stdlib.h>\n\nint main() {\n int num;\n char str_age[3];\n\n printf(\"Nhap tuoi: \");\n scanf(\"%s\", str_age);\n\n num = atoi(str_age);\n printf(\"\\nTuoi vua nhap: %d\", num);\n\n return 0;\n}\n\nKet qua:\nChuyen doi chuoi thanh so nguyen trong C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/string_to_integer_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_string_to_uppercase_c",
"topic": "Biến đổi chuỗi thành chữ hoa trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để chuyển đổi toàn bộ ký tự chữ cái trong một chuỗi sang dạng chữ hoa. Lời giải sử dụng hàm strupr() trong thư viện string.h để biến đổi trực tiếp chuỗi đầu vào thành chữ hoa, trong khi vẫn giữ nguyên các ký tự không phải chữ cái.",
"metadata": {
"raw_text": "Biến đổi chuỗi thành chữ hoa trong C\n\nĐề bài\nViết chương trình C để biến đổi chuỗi thành chữ hoa. Ví dụ: nhập chuỗi \"Hoc Lap Trinh C - hiepsiit.com\" thì kết quả là \"HOC LAP TRINH C - HIEPSIIT.COM\".\n\nLời giải\nSử dụng hàm strupr() để chuyển đổi tất cả các ký tự chữ cái trong chuỗi thành chữ hoa. Hàm này được định nghĩa trong thư viện string.h.\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char string[100];\n printf(\"Nhap chuoi bat ky: \");\n gets(string);\n strupr(string);\n printf(\"Chuoi chu hoa la: %s\", string);\n return 0;\n}\n\nKet qua:\nNhap chuoi bat ky: hiepsiit.com\nChuoi chu hoa la: HIEPSIIT.COM",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/string_to_uppercase_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_string_to_lowercase_c",
"topic": "Biến đổi chuỗi thành chữ thường trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để chuyển đổi toàn bộ ký tự chữ cái trong một chuỗi sang dạng chữ thường. Lời giải sử dụng hàm strlwr() trong thư viện string.h để biến đổi trực tiếp chuỗi đầu vào thành chữ thường, trong khi vẫn giữ nguyên các ký tự không phải chữ cái.",
"metadata": {
"raw_text": "Biến đổi chuỗi thành chữ thường trong C\n\nĐề bài\nViết chương trình C để biến đổi chuỗi thành chữ thường. Ví dụ: nhập chuỗi \"Hoc Lap Trinh C - HiepSiIt.Com\" thì kết quả là \"hoc lap trinh c - hiepsiit.com\".\n\nLời giải\nSử dụng hàm strlwr() để chuyển đổi tất cả các ký tự chữ cái trong chuỗi thành chữ thường. Hàm này được định nghĩa trong thư viện string.h.\n\n#include <stdio.h>\n#include <string.h>\n\nint main() {\n char string[100];\n printf(\"Nhap chuoi bat ky: \");\n gets(string);\n strlwr(string);\n printf(\"Chuoi chu thuong la: %s\", string);\n return 0;\n}\n\nKet qua:\nNhap chuoi bat ky: Hoc Lap Trinh C - HiepSiIt.Com\nChuoi chu thuong la: hoc lap trinh c - hiepsiit.com",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/string_to_lowercase_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập chuỗi"
},
{
"id": "slide_fibonacci_c",
"topic": "Dãy số Fibonacci trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để in ra n số Fibonacci đầu tiên. Dãy Fibonacci được định nghĩa với hai số đầu tiên là 0 và 1, mỗi số tiếp theo bằng tổng hai số đứng trước. Bài toán được giải bằng hai cách: không sử dụng đệ quy (vòng lặp) và sử dụng đệ quy.",
"metadata": {
"raw_text": "Dãy số Fibonacci trong C\n\nĐề bài\nViết chương trình C tìm n số Fibonacci đầu tiên. Quy luật: số tiếp theo bằng tổng của hai số trước, với hai số đầu tiên là 0 và 1. Ví dụ: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...\n\nLời giải\nCó hai cách cài đặt dãy Fibonacci trong C:\n\n1. Không sử dụng đệ quy\nSử dụng vòng lặp để tính dần các giá trị Fibonacci.\n\n#include <stdio.h>\n\nint fibonacci(int n) {\n int f0 = 0;\n int f1 = 1;\n int fn = 1;\n int i;\n if (n < 0) return -1;\n else if (n == 0 || n == 1) return n;\n else {\n for (i = 2; i < n; i++) {\n f0 = f1;\n f1 = fn;\n fn = f0 + f1;\n }\n }\n return fn;\n}\n\nint main() {\n int i;\n printf(\"10 so dau tien cua day Fibonacci:\\n\");\n for (i = 0; i < 10; i++) {\n printf(\"%d \", fibonacci(i));\n }\n}\n\n2. Sử dụng phương pháp đệ quy\nCài đặt trực tiếp theo công thức truy hồi của dãy Fibonacci.\n\n#include <stdio.h>\n\nint fibonacci(int n) {\n if (n < 0) return -1;\n else if (n == 0 || n == 1) return n;\n else return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nint main() {\n int i;\n printf(\"10 so dau tien cua day Fibonacci:\\n\");\n for (i = 0; i < 10; i++) {\n printf(\"%d \", fibonacci(i));\n }\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/fibonacci_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C kinh điển"
},
{
"id": "slide_prime_number_check_c",
"topic": "Kiểm tra số nguyên tố trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để kiểm tra một số nguyên đã cho có phải là số nguyên tố hay không. Số nguyên tố là số lớn hơn 1 và chỉ chia hết cho 1 và chính nó. Lời giải sử dụng vòng lặp kiểm tra các ước từ 2 đến căn bậc hai của số cần kiểm tra để tối ưu hiệu năng.",
"metadata": {
"raw_text": "Kiểm tra số nguyên tố trong C\n\nĐề bài\nViết chương trình C kiểm tra số đã cho có phải là số nguyên tố hay không.\n\nĐịnh nghĩa\nSố nguyên tố là số lớn hơn 1 và chỉ chia hết cho 1 và chính nó. Các số 0 và 1 không phải là số nguyên tố. Số 2 là số nguyên tố chẵn duy nhất.\n\nVí dụ chương trình kiểm tra số nguyên tố trong C:\n\n#include <stdio.h>\n#include <math.h>\n\nint isPrimeNumber(int n) {\n if (n < 2) {\n return 0;\n }\n int squareRoot = (int) sqrt(n);\n int i;\n for (i = 2; i <= squareRoot; i++) {\n if (n % i == 0) {\n return 0;\n }\n }\n return 1;\n}\n\nint main() {\n int i;\n printf(\"Cac so nguyen to nho hon 100 la:\\n\");\n for (i = 0; i < 100; i++) {\n if (isPrimeNumber(i)) {\n printf(\"%d \", i);\n }\n }\n}\n\nKet qua:\n2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/prime_number_check_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C kinh điển"
},
{
"id": "slide_factorial_c",
"topic": "Tính giai thừa trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để tính giai thừa của một số nguyên dương. Giai thừa của n là tích các số từ 1 đến n, với trường hợp đặc biệt 0! = 1 và 1! = 1. Bài toán được giải bằng hai cách: không sử dụng đệ quy (vòng lặp) và sử dụng đệ quy.",
"metadata": {
"raw_text": "Tính giai thừa trong C\n\nĐề bài\nViết chương trình C tính giai thừa của một số nguyên dương. Giai thừa của n là tích các số liên tiếp từ 1 đến n. Trường hợp đặc biệt, giai thừa của 0 và 1 đều bằng 1.\n\nLời giải\nCó hai cách cài đặt chương trình tính giai thừa trong C:\n\n1. Không sử dụng đệ quy\nSử dụng vòng lặp để nhân dần các số từ 1 đến n.\n\n#include <stdio.h>\n\nlong tinhGiaithua(int n) {\n int i;\n long giai_thua = 1;\n if (n == 0 || n == 1) {\n return giai_thua;\n } else {\n for (i = 2; i <= n; i++) {\n giai_thua *= i;\n }\n return giai_thua;\n }\n}\n\nint main() {\n int a = 5;\n int b = 0;\n int c = 10;\n printf(\"Giai thua cua %d la: %ld\\n\", a, tinhGiaithua(a));\n printf(\"Giai thua cua %d la: %ld\\n\", b, tinhGiaithua(b));\n printf(\"Giai thua cua %d la: %ld\", c, tinhGiaithua(c));\n}\n\n2. Sử dụng phương pháp đệ quy\nCài đặt trực tiếp theo định nghĩa toán học của giai thừa.\n\n#include <stdio.h>\n\nlong tinhGiaithua(int n) {\n if (n > 0) {\n return n * tinhGiaithua(n - 1);\n } else {\n return 1;\n }\n}\n\nint main() {\n int a = 5;\n int b = 0;\n int c = 10;\n printf(\"Giai thua cua %d la: %ld\\n\", a, tinhGiaithua(a));\n printf(\"Giai thua cua %d la: %ld\\n\", b, tinhGiaithua(b));\n printf(\"Giai thua cua %d la: %ld\", c, tinhGiaithua(c));\n}",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/factorial_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C kinh điển"
},
{
"id": "slide_base_conversion_c",
"topic": "Chuyển đổi hệ cơ số trong C",
"type": "exercise",
"content_for_embedding": "Bài toán yêu cầu viết chương trình C để chuyển đổi số nguyên giữa các hệ cơ số. Cụ thể: chuyển số nguyên từ hệ cơ số 10 sang hệ cơ số bất kỳ (2 ≤ B ≤ 16) và hiểu nguyên lý chuyển đổi từ hệ nhị phân sang hệ cơ số 10. Lời giải sử dụng phép chia lấy dư kết hợp mảng ký tự và bảng mã ASCII để biểu diễn các chữ số từ 0 đến F.",
"metadata": {
"raw_text": "Chuyển đổi hệ cơ số trong C\n\nĐề bài\nViết chương trình C chuyển đổi hệ cơ số:\n1. Chuyển đổi số nguyên N từ hệ cơ số 10 sang hệ cơ số B bất kỳ (2 ≤ B ≤ 16).\n2. Hiểu nguyên lý chuyển đổi từ hệ nhị phân sang hệ cơ số 10.\n\nLời giải\nNguyên lý chuyển đổi từ hệ cơ số 10 sang hệ cơ số B:\n- Lấy phần dư của phép chia N cho B.\n- Lưu phần dư vào mảng (hoặc stack).\n- Chia N cho B.\n- Lặp lại cho đến khi N = 0.\n- Đảo ngược mảng phần dư để được kết quả.\n\nCác chữ số từ 10 đến 15 trong hệ cơ số lớn hơn 10 được biểu diễn lần lượt bằng A, B, C, D, E, F.\n\n#include <stdio.h>\n\nconst char CHAR_55 = 55; // 'A' - 10\nconst char CHAR_48 = 48; // '0'\n\nint convertNumber(int n, int b) {\n if (n < 0 || b < 2 || b > 16) {\n printf(\"He co so hoac gia tri chuyen doi khong hop le!\");\n return 0;\n }\n char arr[20];\n int count = 0;\n int m;\n int remainder = n;\n\n while (remainder > 0) {\n m = remainder % b;\n if (m >= 10) {\n arr[count++] = (char)(m + CHAR_55);\n } else {\n arr[count++] = (char)(m + CHAR_48);\n }\n remainder = remainder / b;\n }\n\n for (int i = count - 1; i >= 0; i--) {\n printf(\"%c\", arr[i]);\n }\n return 1;\n}\n\nint main() {\n int n = 12;\n printf(\"So %d trong he co so 2 = \", n);\n convertNumber(n, 2);\n printf(\"\\nSo %d trong he co so 16 = \", n);\n convertNumber(n, 16);\n return 0;\n}\n\nKet qua:\nSo 12 trong he co so 2 = 1100\nSo 12 trong he co so 16 = C",
"diagram_text": null,
"has_diagram": false,
"image_path": "images/base_conversion_c.png",
"page_number": null,
"knowledge_type": [
"Dạng bài + phương pháp giải"
]
},
"chapter": "Bài tập C kinh điển"
}
]