Professional Documents
Culture Documents
• Ví dụ: họ hàng shell script, Tcl, Python,… • Ví dụ: C, C++, C#, Java,…
• Có thể chạy trực tiếp mà không cần biên • Cần phải biên dịch để có thể thực thi chương
dịch. trình.
• Cần có môi trường để chạy (ví dụ Python • Quá trình biên dịch sẽ dịch mã nguồn gốc về
shell, Tcl shell,… hợp ngữ (Assembly) để có thể chạy được
trên máy.
• Phần 2: Cấu trúc rẽ nhánh – Câu lệnh điều kiện if..else ; switch..case.
• Phần 5: Hàm.
Lưu ý: Bỏ qua nội dung “Con trỏ” (Pointer), “Cấu trúc” (Struct), thao tác tệp (File), hướng đối tượng (C++).
Tống Ngọc Quyền 3
Phần 1: Làm quen với ngôn ngữ lập trình C
• Cấu trúc chương trình C cơ bản
• Kiểu dữ liệu
• Toán tử
• Các hàm nhập xuất dữ liệu
#include <stdio.h>
• Giá trị trả về (trong ví dụ là 0) được xem là mã thoát
void main() {
(EXIT CODE) của chương trình. HĐH sử dụng để xác printf("Hello lớp học thầy Quyền!!!");
}
định chương trình kết thúc thành công hoặc có lỗi.
• #include: Được dùng để chèn thêm code từ một file vào source code hiện tại.
→Thường được dùng để khai báo thư viện, hoặc nạp thêm các code thành phần vào code chính.
#include <stdio.h>
#include "controlMotors.h"
• #define: Được dùng để định nghĩa macro, biểu thị một hằng số hoặc một hàm giả.
→ Giúp code trở nên tường minh hơn mà không sử dụng các biến, hàm gây tốn bộ nhớ trên RAM.
– Định nghĩa hằng số: #define PI 3.1415926
– Định nghĩa hàm giả: #define SQUARE(x) ((x) * (x))
• Chú thích không phải một phần của chương #include <stdio.h>
trình, và không được biên dịch. void main() {
// In ra màn hình
// Biên dịch là quá trình dịch từ ngôn ngữ
printf("Hello lớp học thầy Quyền!!!");
bậc cao sang ngôn ngữ máy để máy tính hiểu
}
được và thực thi.
– Tránh tràn số (overflow): Tránh việc giá trị của phép tính vượt quá khả năng biểu diễn của biến.
– Tránh thiếu số (underflow): Một giá trị rất gần, tiệm cận 0, vượt quá giới hạn khả năng của float sẽ bị
làm tròn thành 0 → Cần ép về double để lưu giá trị này.
– Tối ưu bộ nhớ/tốc độ tính toán: RAM có hạn, tính số nhỏ thì dễ hơn số lớn.
• Kết quả trả về giá trị số học như tính toán số STT Toán tử Tác dụng
học thông thường.
1 + Cộng
int a = 3 + 2; // a = 5
float b = 1.0 / 2; // b = 0.5 2 - Trừ
int c = 2; // c = 2 Số
3 * Nhân
học
int d = a % c; // d = 1
4 / Chia
int e = a / c; // e = 2
float f = b / a; // f = 0.1 5 % Chia lấy dư
• Kết quả trả về giá trị Boolean là true/false. STT Toán tử Tác dụng
• Cú pháp: (Điều kiện) ? <Giá trị nếu đúng> : <Giá trị nếu sai>
• Thường dùng để đơn giản hóa một phép gán giá trị thay cho câu lệnh if..else.
int max = (a > b) ? a : b; // Nếu a lớn hơn thì max được gán bằng a, ngược lại thì b
• Dùng để thao tác trực tiếp với các bit của giá
STT Biểu diễn Tác dụng
trị số. → Tăng tốc độ tính toán và xử lý với
các thanh ghi, ngoại vi nhiều lần. 1 & (AND)
• Lấy địa chỉ của biến ở trên bộ nhớ, bằng toán tử &
int b;
scanf ("%d", &b); // Đưa số vừa nhập vào đến địa chỉ ô nhớ của b
• Lấy/Tác động đến giá trị tại ô nhớ mà “con trỏ” trỏ đến, bằng toán tử *
int *a ; // Khai báo con trỏ a (địa chỉ ô nhớ, không phải biến)
• Tương tự toán học thông thường, phép tính có độ ưu tiên trước sau:
– Trong dấu ngoặc tròn ()
– Toán tử số học + -
• Đặc biệt, với toán tử tiếp tục, thứ tự phép tính phụ thuộc vị trí của toán tử, ví dụ:
int a = 10;
// b được gán bằng a trước rồi tăng giá trị biến a sau
int b = a++; // b = a = 10; a = a + 1 = 11;
// a được tăng giá trị trước rồi c mới được gán bằng a
int c = ++a; // a = a + 1 = 12; c = a = 12;
• Hàm được khai báo trong thư viện stdio.h, printf("%s sinh nam %d", "QuyenTN", 2004);
do đó cần khai báo thư viện mới có thể sử → QuyenTN sinh nam 2004
dụng được.
#include <stdio.h>
• Chú thích: Trong nhiều loại giao tiếp, thông điệp có dạng
“DATA\r\n”, trong đó \r\n chỉ dẫn kết thúc dòng/ thông điệp.
(Khi nhấn Enter thì máy tính sẽ tự chèn thêm ký tự đặc biệt phía cuối chuỗi)
%.<X>f Lấy ‘X’ ký tự sau dấu chấm printf("%.3f" , 1.0 ); ---> "1.000"
#define PI 3.14159265
int main() {
printf("Gia tri cua PI la: %f\n", PI);
return 0;
}
? Giá trị của biến a sau khi thực hiện chương trình trên là gì?
? Giá trị của biến a và b sau khi thực hiện chương trình trên là gì?
1. Giải phương trình bậc nhất ax + b = 0. Với a và b được nhập từ bàn phím, in ra màn hình
nghiệm của phương trình.
3. In bảng cửu chương từ 1 đến 10, sử dụng format string ngay ngắn thẳng hàng.
Notes: AI có thể hoàn thành bài tập trên dễ dàng, nhưng bạn muốn là kẻ theo sau AI hay là người
không thể bị AI thay thế?
Tống Ngọc Quyền 28
7/ Giải bài tập
Giải phương trình bậc nhất ax + b = 0
#include <stdio.h>
int main() {
int a, b;
scanf("%d%d",&a,&b);
printf("x = %.2f", (float)(-b)/a);
return 0;
}
printf(stringFormat, "1 x 1 = 1" , "2 x 1 = 2" , "3 x 1 = 3" , "4 x 1 = 4" , " 5 x 1 = 5" );
printf(stringFormat, "1 x 2 = 2" , "2 x 2 = 4" , "3 x 2 = 6" , "4 x 2 = 8" , " 5 x 2 = 10" );
printf(stringFormat, "1 x 3 = 3" , "2 x 3 = 6" , "3 x 3 = 9" , "4 x 3 = 12", " 5 x 3 = 15" );
printf(stringFormat, "1 x 4 = 4" , "2 x 4 = 8" , "3 x 4 = 12", "4 x 4 = 16", " 5 x 4 = 20" );
printf(stringFormat, "1 x 5 = 5" , "2 x 5 = 10", "3 x 5 = 15", "4 x 5 = 20", " 5 x 5 = 25" );
printf(stringFormat, "1 x 6 = 6" , "2 x 6 = 12", "3 x 6 = 18", "4 x 6 = 24", " 5 x 6 = 20" );
printf(stringFormat, "1 x 7 = 7" , "2 x 7 = 14", "3 x 7 = 21", "4 x 7 = 28", " 5 x 7 = 35" );
printf(stringFormat, "1 x 8 = 8" , "2 x 8 = 16", "3 x 8 = 24", "4 x 8 = 32", " 5 x 8 = 40" );
printf(stringFormat, "1 x 9 = 9" , "2 x 9 = 18", "3 x 9 = 27", "4 x 9 = 36", " 5 x 9 = 45" );
printf(stringFormat, "1 x 10 = 10", "2 x 10 = 20", "3 x 10 = 30", "4 x 10 = 40", " 5 x 10 = 50" );
printf("\n");
printf(stringFormat, "6 x 1 = 6 ", "7 x 1 = 7" , "8 x 1 = 8" , "9 x 1 = 9" , "10 x 1 = 10" );
printf(stringFormat, "6 x 2 = 12", "7 x 2 = 14", "8 x 2 = 16", "9 x 2 = 18", "10 x 2 = 20" );
printf(stringFormat, "6 x 3 = 18", "7 x 3 = 21", "8 x 3 = 24", "9 x 3 = 27", "10 x 3 = 30" );
printf(stringFormat, "6 x 4 = 24", "7 x 4 = 28", "8 x 4 = 32", "9 x 4 = 36", "10 x 4 = 40" );
printf(stringFormat, "6 x 5 = 30", "7 x 5 = 35", "8 x 5 = 40", "9 x 5 = 46", "10 x 5 = 50" );
printf(stringFormat, "6 x 6 = 36", "7 x 6 = 42", "8 x 6 = 48", "9 x 6 = 54", "10 x 6 = 60" );
printf(stringFormat, "6 x 7 = 42", "7 x 7 = 49", "8 x 7 = 56", "9 x 7 = 64", "10 x 7 = 70" );
printf(stringFormat, "6 x 8 = 48", "7 x 8 = 56", "8 x 8 = 64", "9 x 8 = 72", "10 x 8 = 80" );
printf(stringFormat, "6 x 9 = 54", "7 x 9 = 63", "8 x 9 = 72", "9 x 9 = 81", "10 x 9 = 90" );
printf(stringFormat, "6 x 10 = 60", "7 x 10 = 70", "8 x 10 = 80", "9 x 10 = 90", "10 x 10 = 100");
• Ví dụ:
Công việc 1
int number = 5;
if (number > 0) {
Sai
printf("Number is positive.\n");
• Điều kiện đúng thực hiện khối lệnh 1, sai thực hiện khối
lệnh 2. Điều kiện?
if (<điều kiện>) {
// Khối lệnh thực thi khi điều kiện đúng Đúng
Sai
} else {
// Khối lệnh thực thi khi điều kiện sai
}
Công việc 1 Công việc 2
• Ví dụ:
int number = 5;
if (number > 0) {
printf("Number is positive.\n");
} else {
printf("Number is not positive.\n");
}
Tống Ngọc Quyền 35
2/ Câu lệnh switch..case
Cấu trúc
• So sánh bằng của biểu thức thay vì kiểm tra tính đúng biểu thức == giá trị 1? Đúng Khối lệnh 1
case value1:
Sai
// Khối lệnh cho giá trị value1
break; biểu thức == giá trị 2? Đúng Khối lệnh 2
case value2:
// Khối lệnh cho giá trị value2
Sai break? Đúng
break;
...
default: Khối lệnh 3 Sai
➢2005
➢2005 la so le.
➢2
➢Mua xuan.
1. Nhập lương gộp (lương trên hợp đồng – gloss salary) (đơn vị: đồng, KHÔNG phải “triệu
đồng”). Tính bảo hiểm, thu nhập tính thuế, thuế thu nhập cá nhân, lương ròng (thực nhận –
net salary), biết:
– Lương ròng = Lương gộp – Bảo hiểm – Thuế TNCN.
– Bảo hiểm bắt buộc (BHXH 8% + BHYT 1.5% + BHTN 1%) = 10.5% lương gộp.
– Các khoản giảm trừ miễn thuế:
– Miễn trừ gia cảnh bản thân: 11 triệu/tháng (tương đương 132 triệu/năm) (Lương này thuế TNCN = 0 đó!).
– Mỗi người phụ thuộc là 4.4 triệu/tháng (Trong bài 1 thì cho là không có người phụ thuộc).
– Các khoản đóng bảo hiểm, đóng góp từ thiện (cho là không làm). TNPCT (triệu VND) Thuế suất (%)
– Thu nhập phải chịu thuế = Lương gộp – Các khoản miễn thuế. 0+ đến 5 5
5+ đến 10 10
– Thuế thu nhập cá nhân (đơn giản) = TNPCT x Thuế suất.
10+ đến 18 15
2. Giống bài 1, nhưng xét 10 năm tới, lương tăng 20%/năm. 18+ đến 32 20
Biết cả cha và mẹ sau 3 năm trở thành người phụ thuộc. 32+ đến 52 25
52+ đến 80 30
80+ 35
#include <stdio.h>
int main(){
float lr, lg, bh, t, bhbb, tncn, tnpct;
printf("Luong Gop (VND): ");
scanf("%f", &lg); if (lg < 0) return 0;
bhbb = lg * 0.105;
tnpct = lg - bhbb - 11000000;
if (tnpct < 5000000) {tncn = tnpct * 0.05;}
else if (tnpct < 10000000) {tncn = tnpct * 0.10;}
else if (tnpct < 18000000) {tncn = tnpct * 0.15;}
else if (tnpct < 32000000) {tncn = tnpct * 0.20;}
else if (tnpct < 52000000) {tncn = tnpct * 0.25;}
else if (tnpct < 80000000) {tncn = tnpct * 0.30;}
else {tncn = tnpct * 0.35;}
lr = lg - bhbb - tncn;
printf("Thu nhap chiu thue: %d\n", (int)tnpct );
printf("Bao hiem: %d\n", (int)bhbb );
printf("Thue TNCN: %d\n", (int)tncn );
printf("Luong rong: %d\n", (int)lr );
return 0;
}
• Kết thúc khi không thỏa mãn điều kiện, hoặc gặp lệnh break.
Điều kiện Sai
• Phân loại:
– Vòng lặp for. Đúng
– Vòng lặp while / do..while.
– Vòng lặp vô hạn.
Khối lệnh
• Vòng lặp thực hiện kiểm tra điều kiện trước, mới thực hiện khối
lệnh nếu đúng.
Điều kiện Sai
• Cú pháp:
while (<điều kiện>) {
Đúng
// Khối lệnh
}
• Ví dụ: Tìm số lớn nhất chia hết cho 7 trong khoảng 0..100. Khối lệnh
int i = 0, k = 0;;
while (i <= 100) { // i là biến đếm
// k là số chia hết cho 7 lớn nhất
if (i % 7 == 0) {k = i;} i++;
}
• Tương tự vòng lặp while, nhưng làm trước rồi hỏi sau.
do {
// Khối lệnh
} while (<điều kiện>); Khối lệnh
Đúng
• Thường dùng trong trường hợp cần có input trước.
• Chỉ dừng lại khi có một sự kiện ngoại lệ (lệnh break, hoặc tác động
Khối lệnh
khác (thường là ngắt – interrupt) ).
Sai
while (true) {
// Khối lệnh
}
break?
• “true” có thể thay thế bởi các toán tử điều kiện, hoặc các giá trị số Tác động khác?
tương đương với true (như 1, 2, -2,…).
• Thông thường, vòng lặp vô hạn là trường hợp không mong muốn xảy
Đúng
ra, do lỗi lập trình, cần tránh.
– Khóa/treo chương trình: thường khi gặp lỗi không mong muốn.
• break
– Kết thúc vòng lặp ngay lập tức.
– Thường dùng khi đạt được mục đích của lệnh Các câu lệnh Các câu lệnh
vòng lặp.
break? Đúng continue? Sai
• continue
Sai Đúng
– Bỏ qua phần còn lại của vòng lặp và chuyển Các câu lệnh Các câu lệnh
➢2005
➢Ban da nhap so: 2005
1. In bảng cửu chương từ 1 đến X, với X nhập từ bàn phím. Sử dụng format string ngay ngắn
thẳng hàng.
2. Nhập vào số tự nhiên X, điều kiện 1 < X < 9999999, nếu sai nhập lại (gợi ý: dùng do..while).
Tìm các ước của X. Nếu X chỉ có 2 ước, in ra dòng chữ: “X la so nguyen to!”
5. Nhập 2 số tự nhiên X và Y. Tìm ước chung lớn nhất (ƯCLN) theo phương pháp bài 4.
6. Nhập 3 số tự nhiên X, Y và Z. Tìm bội chung nhỏ nhất (BCNN) theo phương pháp bài 4.
7. Nhập 2 số tự nhiên X và Y. Kiểm tra chúng có phải 2 số nguyên tố cùng nhau không.
* *
* * * *
* * * *
* * * *
* * * *
* * * * * * * *
* * * * * *
* * * * * *
* * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * *
Vẽ hình với N lẻ
0 A(N-1; 0) j
*
−1 ; 1 𝑙à 𝑣𝑒𝑐𝑡𝑜𝑟 𝑐ℎỉ 𝑝ℎươ𝑛𝑔 𝑐ủ𝑎 𝑑1 𝑣à 𝑑4 * *
Ta có ቊ vì d1//d4 và d2//d5
1 ; 1 𝑙à 𝑣𝑒𝑐𝑡𝑜𝑟 𝑐ℎỉ 𝑝ℎươ𝑛𝑔 𝑐ủ𝑎 𝑑2 𝑣à 𝑑5 * *
* *
Tương tự với bài trước, ta có các phương trình đường thẳng:
𝑑1: 𝑦 = −𝑥+𝑁−1 d6
* *
𝑑2: 𝑦 = 𝑥+𝑁−1
y=(N-1)/2
* * * * * *
d3: 𝑦 = 𝑁−1
d4: 𝑦 = −𝑥+2𝑁−2
* * * *
d5: 𝑦 = 𝑥 * * * *
𝑁−1
d6: 𝑦 = 2 * * * *
Các giới hạn không được vẽ cho đường d4 và d5: d3
* * * *
𝑁−1 3 𝑁−1 * * * * * * * * *C(2*N-2;
B(0; N-1)
* * N-1)
𝑥< ℎ𝑜ặ𝑐 𝑥 > D(N-1; N-1)
2 2 i
ቐ 𝑁−1
𝑦< 2
Đường d6 đánh dấu * có thể đánh ở cả cột chẵn và lẻ, phụ thuộc giá trị của (N-1)/2 là chẵn hay lẻ
Vẽ hình
#include <stdio.h> 0 A(N-1; 0) j
*
int main() {
while (1) {
* *
int n; do {scanf("%d", &n);} while (n%2 != 1 || n <= 0); * *
int in = 0; int half_odd = ((n-1)/2)%2 ; * *
d6 chỉ đánh dấu * ở cột chẵn hay
int i, j; // bien dem
lẻ phụ thuộc vào giá trị (N-1)/2 d6
* *
for (i = 0; i < n; i++) {
y=(N-1)/2
* * * * * *
for (j = 0; j < 2*n-1; j++) {
* * * *
if (j == i+n-1 || j == -i+n-1 || (i == n-1 && j%2 == 0) ) {in = 1;}
if (i == j || i == -j +2*n - 2 || (i == (n-1)/2 && j%2 == half_odd) ) {in = 1;}
* * * *
if ( (j < (n-1)/2 || j > (3*n-3)/2) && i <= (n-1)/2 ) {in = 0;} * * * *
if (in) {printf("*");} else {printf(" ");}
d3
* * * *
in = 0; * * * * * * * * *C(2*N-2;
B(0; N-1)
* * N-1)
} D(N-1; N-1)
printf("\n"); // Xuong dong
i
}
}
}
• Cú pháp:
<kiểu dữ liệu> <tên mảng>[số phần tử];
int Arr[5];
• Nếu không khởi tạo, ban đầu giá trị ngẫu nhiên. int Arr[5]; // {12632347; 128739247;...} (Random)
• Gán giá trị cho phần tử: <tên mảng>[chỉ số] = <giá trị>;
• Chuỗi là mảng 1 chiều kiểu char, kết thúc bằng giá trị NULL (ký tự \0).
gets(<tên chuỗi>);
puts(<tên chuỗi>);
1. Tìm số lớn nhất trong mảng, với N phần tử nhập từ bàn phím.
inFibonaci(), emAnhQuyen(),…
• Cú pháp:
returnType functionName(parameter1Type parameter1, parameter2Type parameter2, ...) {
• Trong đó:
– returnType : kiểu dữ liệu trả về cho hàm.
Trong trường hợp không có dữ liệu trả về, ở đây đặt là void
– parameter1Type : kiểu dữ liệu cho tham số đầu vào. Các tham số cách nhau bởi dấu phẩy.
Trong trường hợp không có tham số đầu vào, ở đây bỏ trống, hoặc đặt là void
• Biến cục bộ: Chỉ có hiệu lực trong phạm vi của hàm.
• Là một hàm gọi lại chính nó. // Hàm tính giai thừa đệ quy
int giaiThua(int n) {
• Thường giải quyết các bài toán có cấu trúc đệ quy. // Điều kiện dừng
• Lưu ý khi sử dụng đệ quy: if (n == 0 || n == 1) {
return 1;
– Dùng bộ nhớ: Nếu đệ quy quá sâu → tràn bộ nhớ → Crash!
(hiện tượng này gọi là Stack Overflow). } else {
// Gọi đệ quy
– Điều kiện dừng hợp lý để tránh đệ quy vô hạn
return n * giaiThua(n-1);
– Hiệu suất: }
▪ Độ phức tạp thuật toán cao. }
▪ Máy tính cần sử dụng nhiều thao tác cho mỗi vòng đệ quy.
▪ Thời gian chạy lâu.
#include <stdio.h>
? Theo lời giảng, khi kết thúc hàm, tại vị trí đó, xuất hiện giá trị trả về (cũng như biến).
? Như vậy %d thứ hai trong hàm printf() để biểu thị giá trị trả về của hàm giaiThua?
} } }
? Liên kết với nội dung phần 1 để hiểu #include sẽ gom code thư viện vào code chính.
1. Viết khai báo hàm strlen() để tính độ dài của chuỗi. Chấp nhận ký tự đặc biệt ngoài NULL.
2. Lưu code khai báo hàm strlen() thành file “string.c.<your name>”. Lưu ý file này chỉ chứa khai
báo hàm trên, không include và không chứa hàm main().
3. Tạo 1 code mới trong cùng thư mục với file code trên, thêm dòng #include “<tên file trên>”.
Sau đó gọi hàm strlen() để sử dụng.
4. Khai báo hàm “control” không có kiểu dữ liệu trả về, có 1 tham số đầu vào “signal”. Hàm thực
hiện yêu cầu sau:
▪ Nếu biến signal là 0, in ra màn hình “Stop”.
▪ Nếu biến signal là 1, in ra màn hình “Forward”.
▪ Nếu biến signal là 2, in ra màn hình “Turn right”.
▪ Nếu biến signal là 3, in ra màn hình “Backward”.
▪ Nếu biến signal là 4, in ra màn hình “Turn left”.