Lab 01 cho người mới: mảng và vòng lặp giảng từng dòng
Giả định duy nhất: bạn đã đọc phần 0 (Java từ số 0) trong trang người mới. Mỗi bài dưới đây đi theo đúng 6 bước: đề nói gì, từ mới, ý tưởng, code giải thích từng dòng, chạy tay, bẫy.
Bài 1. Chao2 — chào theo tên gõ lúc chạy
Đề nói gì
Viết chương trình chào. Tên không viết cứng trong code mà gõ lúc chạy:
java Chao2 Nguyen Van An thì in Chao Nguyen Van An.
Chạy không gõ tên thì nhắc cách dùng rồi dừng.
Từ mới
- Tham số dòng lệnh: mấy chữ gõ sau tên lớp lúc chạy.
Java hứng vào mảng
args:args[0]là chữ đầu tiên. args.length: số chữ đã gõ. Không gõ thì bằng 0.
Ý tưởng
- Không có tên (
length == 0) thì in hướng dẫn, dừng. - Có tên thì nối các chữ lại, giữa hai chữ chèn 1 dấu cách.
- In câu chào.
Code giải thích từng dòng
public class Chao2 {
public static void main(String[] args) {
if (args.length == 0) { // bước 1: không gõ tên?
System.out.println("Cach dung: java Chao2 <ten>");
return; // dừng chương trình tại đây
}
String ten = ""; // hộp rỗng để hứng tên
for (int i = 0; i < args.length; i++) { // duyệt từng chữ đã gõ
ten += args[i]; // nối chữ thứ i vào
if (i < args.length - 1) // chưa phải chữ cuối?
ten += " "; // thì chèn 1 dấu cách
}
System.out.println("Chao " + ten); // bước 3: chào
}
}
ten += args[i] là viết gọn của ten = ten + args[i].
Điều kiện i < args.length - 1 (chữ cuối có i bằng length - 1)
để kết quả không thừa dấu cách ở đuôi.
Chạy tay
java Chao2 Nguyen Van An: args = ["Nguyen", "Van", "An"],
length = 3, khác 0 nên qua được bước 1.
Vòng lặp: i=0 → ten="Nguyen", 0 < 2 nên thêm cách;
i=1 → ten="Nguyen Van", thêm cách;
i=2 → ten="Nguyen Van An", 2 < 2 sai nên không thêm cách.
In ra Chao Nguyen Van An.
java Chao2 (không tên): length = 0 → in hướng dẫn, return dừng.
Không bao giờ chạm tới vòng lặp.
Bẫy hay gặp
- Quên kiểm tra
length == 0rồi dùngargs[0]ngay: chạy không tên là chết lỗiArrayIndexOutOfBoundsException. - Nối tên mà quên chèn cách: ra
Chao NguyenVanAn.
Tự luyện
- Sửa để chỉ chào từ đầu tiên (
args[0]), bỏ qua phần còn lại. - Sửa để nếu tên có đúng 1 chữ thì chào
Chao ban <ten>, nhiều chữ thì chào như cũ.
Bài 2. DocSo — đọc số 0–9 thành chữ
Đề nói gì
Nhập 1 số, in cách đọc: 7 → bay, 0 → khong.
Số ngoài 0–9 thì in Khong hop le.
Từ mới
switch (n): xemnbằng mấy rồi nhảy đúng nhánhcase.break: thoát khỏiswitch. Thiếu là rơi xuống nhánh dưới.default: nhánh gom mọi giá trị còn lại (ở đây gom số 9).||là "hoặc":n < 0 || n > 9đúng khi n nằm ngoài 0–9.
Ý tưởng
- Nhập
n. - Ngoài 0–9 → báo sai, xong.
- Trong 0–9 →
switchin chữ tương ứng.
Code giải thích từng dòng
Scanner sc = new Scanner(System.in);
System.out.print("Nhap mot chu so (0-9): ");
int n = sc.nextInt();
if (n < 0 || n > 9) { // bước 2: chặn số lạ trước
System.out.println("Khong hop le");
} else { // số sạch mới cho vào switch
switch (n) {
case 7: System.out.println("bay"); break; // n=7: in rồi THOÁT
default: System.out.println("chin"); break;
}
}
sc.close();
Vì chỉ viết case 0 đến case 8 nên số 9 không khớp nhánh nào,
rơi vào default in chin. if chặn ngoài giúp switch khỏi lo số lạ.
Chạy tay
Nhập 7: 7 < 0 sai, 7 > 9 sai → cả || sai → vào else,
switch(7) nhảy case 7, in bay, gặp break thoát.
Nhập 12: 12 > 9 đúng → in Khong hop le, bỏ qua switch.
Bẫy hay gặp
- Quên
break: nhập 7 inbayxong rơi tiếp in cảtam,chin. - Viết
if (n < 0 && n > 9): một số không thể vừa âm vừa lớn hơn 9, điều kiện chết, số lạ lọt hết vàoswitch.
Tự luyện
- Thêm
case 9tường minh,defaultbáoKhong hop le(chuyển nhiệm vụ chặn số lạ chodefault). - Đọc số 0–99: gợi ý dùng
n / 10(chục) vàn % 10(đơn vị).
Bài 3. HinhTron — kiểm tra rồi mới tính
Đề nói gì
Nhập bán kính r, in diện tích và chu vi làm tròn 2 chữ số.
r không dương thì báo Ban kinh phai duong rồi dừng.
Từ mới
double: kiểu số thực, bán kính có thể lẻ (2.5) nên không dùngint.Math.PI: số pi có sẵn của Java, khỏi tự gõ 3.14.returntrongmain: dừng chương trình ngay lập tức.
Ý tưởng
- Nhập
r. r <= 0→ báo lỗi, đóng Scanner, dừng.- Tính và in, làm tròn 2 chữ số.
Code giải thích từng dòng
double r = sc.nextDouble();
if (r <= 0) { // bước 2: số sai thì đuổi về
System.out.println("Ban kinh phai duong");
sc.close();
return; // không tính tiếp
}
double dienTich = Math.PI * r * r; // pi × r²
double chuVi = 2 * Math.PI * r; // 2 × pi × r
System.out.println("Dien tich: " + Math.round(dienTich * 100) / 100.0);
Mẹo Math.round(x * 100) / 100.0: với r = 3,
diện tích 28.2743... nhân 100 → 2827.43, làm tròn → 2827,
chia 100.0 → 28.27. Chia cho 100.0 (số thực) chứ không phải
100 (số nguyên) — chia nguyên là mất hết phần lẻ.
Chạy tay
r = 3: 3 <= 0 sai → tính tiếp.
Diện tích 28.2743 → 28.27, chu vi 18.8495 → 18.85.
Khớp output mẫu từng chữ số.
r = 0: 0 <= 0 đúng → báo lỗi, dừng, không có phép tính nào chạy.
Bẫy hay gặp
- Kiểm tra
r < 0(thiếu=):r = 0lọt qua, tính ra diện tích 0 mà đề không cho phép. - Quên
sc.close()trướcreturn: Scanner mở mà không đóng (trình biên dịch cảnh báo, bị trừ điểm phong cách).
Tự luyện
- In thêm đường kính (
2 * r). - Chỉ nhận
rtrong khoảng 0–1000, ngoài thì báo lỗi.
Bài 4. GiaiThua — int tràn số
Đề nói gì
Tính n! (n gõ lúc chạy). 5! = 120, 0! = 1, số âm báo lỗi.
13! phải ra 6227020800.
Từ mới
Integer.parseInt(args[0]): đổi chữ gõ lúc chạy thành số nguyên.long: hộp số nguyên lớn (tới 9e18),intchỉ tới ~2.1 tỉ.
Ý tưởng
- Không gõ
nthì nhắc cách dùng, dừng. - Đổi chữ thành số; âm thì báo lỗi, dừng.
- Nhân dồn từ 2 tới
n.
Code giải thích từng dòng
int n = Integer.parseInt(args[0]); // "5" thành số 5
if (n < 0) { System.out.println("n phai >= 0"); return; }
long kq = 1; // bắt đầu từ 1 (trung hòa phép nhân)
for (int i = 2; i <= n; i++) { // nhân 2, 3, ..., n
kq *= i; // kq = kq * i
}
System.out.println(n + "! = " + kq);
Bắt đầu từ 2 vì nhân thêm 0, 1 không đổi kết quả.
n = 0: vòng lặp 2 <= 0 sai ngay từ đầu, kq giữ 1 → 0! = 1. Đúng.
Chạy tay
n = 5: kq=1 → ×2=2 → ×3=6 → ×4=24 → ×5=120. In 5! = 120.
Vì sao 13! cần long? 12! = 479 triệu (vừa int),
13! = 6.2 tỉ (vượt 2.1 tỉ) → int tràn thành số âm linh tinh.
Bẫy hay gặp
- Khai báo
int kq:13!ra số âm, test13! = 6227020800rớt. kqkhởi đầu bằng 0: nhân gì cũng ra 0.
Tự luyện
- Tính tổng
1 + 2 + ... + n(khởi đầukqbằng mấy?). - In cả dãy
1! 2! ... n!trên một dòng.
Bài 5. NguyenToTrongMang — tách hàm kiểm tra
Đề nói gì
Nhập n rồi nhập n số, in ra các số nguyên tố và đếm có bao nhiêu cái.
Ví dụ 6 số 2 3 4 5 10 11 → nguyên tố là 2 3 5 11, có 4 số.
Từ mới
- Hàm (phương thức): khối code đặt tên, gọi là chạy.
laNguyenTogói logic kiểm tra đểmaingọi lại nhiều lần. static: hàm của lớp, gọi thẳng tên không cần đúc object.n % i == 0:nchia hết choi.
Ý tưởng
- Nhập
n, chặnn <= 0trước khi cấp phát mảng. - Nhập
nsố vào mảng. - Duyệt mảng, số nào qua được
laNguyenTothì in và đếm.
Code giải thích từng dòng
public static boolean laNguyenTo(int n) {
if (n < 2) return false; // 0, 1, số âm: loại ngay
for (int i = 2; i <= Math.sqrt(n); i++) // thử ước tới căn bậc hai
if (n % i == 0) return false; // có ước → kết luận luôn
return true; // hết ước mà sống → nguyên tố
}
Vì sao chỉ tới căn? Ước đi theo cặp (100 = 4 × 25),
ước nhỏ không bao giờ vượt căn. return false giữa vòng lặp
nghĩa là "biết đáp án rồi, khỏi kiểm tiếp".
Chạy tay
n = 11: thử i = 2 (11 % 2 = 1), i = 3 (11 % 3 = 2),
i <= 3.31 hết vòng → true.
n = 10: i = 2, 10 % 2 = 0 → false ngay.
Dãy 2 3 4 5 10 11 → giữ 2 3 5 11, dem = 4. Khớp output mẫu.
Bẫy hay gặp
- Quên
if (n < 2): số 1 lọt qua thành "nguyên tố". - Duyệt tới
nthay vì căn: đúng nhưng chậm; với số lớn bị trừ điểm tối ưu.
Tự luyện
- Đếm số không nguyên tố trong mảng.
- In ra số nguyên tố lớn nhất (gợi ý: giữ biến
max).
Bài 6. FibonacciTrongMang — sinh dãy để đối chiếu
Đề nói gì
Giống bài 5 nhưng lọc số thuộc dãy Fibonacci (0, 1, 1, 2, 3, 5, 8, 13...).
Ví dụ 1 2 4 5 8 13 20 → giữ 1 2 5 8 13.
Từ mới
- Dãy Fibonacci: số sau bằng tổng hai số trước (
5 = 2 + 3).
Ý tưởng
Hàm laFibonacci(x) sinh dãy từ đầu tới khi chạm/xuyên x,
trúng thì true. main nhập mảng rồi lọc y hệt bài 5.
Code giải thích từng dòng
public static boolean laFibonacci(int x) {
if (x < 0) return false;
int a = 0, b = 1; // hai số đầu dãy
while (a < x) { // chưa tới x thì bước tiếp
int tiep = a + b; // số mới = tổng hai số cũ
a = b; // trượt cửa sổ lên 1 nấc
b = tiep;
}
return a == x; // dừng vì bằng (trúng) hay vượt (trượt)
}
Chạy tay
x = 5: (0,1) → (1,1) → (1,2) → (2,3) → (3,5), a = 5 dừng,
5 == 5 → true. x = 4: ... → (3,5), a = 3 < 4?
3 < 4 đúng nên bước tiếp → (5,8), a = 5, dừng, 5 == 4 sai
→ false. Dãy mẫu giữ đúng 1 2 5 8 13.
Bẫy hay gặp
while (a <= x): vớixtrúng dãy thì bước thừa một nấc,avượt qua, trả về sai.- Số âm không chặn: vòng lặp không chạy,
0 == xsai →false, vẫn đúng tình cờ, nhưng nên chặn rõ ràng.
Tự luyện
- In 10 số Fibonacci đầu tiên.
- Đếm số vừa nguyên tố vừa Fibonacci trong mảng.
Bài 7. SapXepNgauNhien — sắp xếp nổi bọt
Đề nói gì
Sinh 10 số ngẫu nhiên 0–99, in ra, sắp xếp tăng dần, in lại.
Từ mới
Math.random(): số thực ngẫu nhiên từ 0 tới dưới 1. Nhân 100 rồi(int)cắt phần lẻ → nguyên 0–99.- Sắp xếp nổi bọt: đi từng cặp kề nhau, sai thứ tự thì đổi chỗ; sau mỗi lượt, một số lớn về đúng chỗ như bọt nổi lên.
Ý tưởng
- Sinh mảng.
- In mảng chưa sắp.
- Nổi bọt
n - 1lượt. - In mảng đã sắp.
Code giải thích từng dòng
for (int i = 0; i < n - 1; i++) { // lượt i: còn n-1-i cặp cần xét
for (int j = 0; j < n - 1 - i; j++) { // đi từng cặp kề nhau
if (a[j] > a[j + 1]) { // sai thứ tự?
int tmp = a[j]; // đổi chỗ qua biến tạm
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
Đổi chỗ cần tmp như đổi nước hai cốc cần cốc thứ ba.
j < n - 1 - i vì a[j+1] không được vượt mảng,
và i số cuối đã đúng chỗ khỏi xét lại.
Chạy tay (mảng 4 số cho gọn)
[3, 1, 2]: lượt 0: (3,1) đổi → [1, 3, 2], (3,2) đổi → [1, 2, 3];
lượt 1: (1,2) đúng, bỏ qua. Xong sau 2 lượt = n - 1.
Bẫy hay gặp
j < n - i:a[j+1]tràn mảng ở cặp cuối.- Quên
tmp, viếta[j] = a[j+1]; a[j+1] = a[j];: dòng 2 copy giá trị mới, mất số cũ (hai ô giống nhau).
Tự luyện
- Sắp giảm dần (đổi 1 dấu).
- Đếm số lần đổi chỗ đã xảy ra.
Phụ lục OOP: vì sao Lab 01 chưa có object
Bài nào cũng static — nghĩa là gì
Để ý 7 bài Lab 01: mọi hàm đều static, không có new ở đâu cả.
static nghĩa là "của lớp, không của object nào".
laNguyenTo(11) gọi thẳng tên hàm vì nó không đụng thuộc tính
của object nào — nó chỉ nhận số, trả đúng/sai.
Khi nào cần object
Quy tắc ngón tay cái: hàm nào không nhớ gì giữa các lần gọi
(nguyên tố, giai thừa, Fibonacci) thì static là đủ.
Khi dữ liệu cần sống lâu và đi cùng nhau (tử+mẫu của một phân số,
tên+điểm của một sinh viên), phải gói thành object — đó là Lab 02.
Lab 01 là nền: vòng lặp, mảng, hàm — gạch nền để Lab 02 xây nhà OOP lên.
Tham chiếu null là gì (đọc trước để khỏi sốc Lab 03)
Biến object không cầm object thật mà cầm địa chỉ (tham chiếu).
Khai báo PS p; mà chưa new thì p là null — tờ giấy ghi địa chỉ
trống. Gọi p.cong(q) lúc này là đi theo địa chỉ trống → nổ
NullPointerException. Mảng new SV[5] cũng vậy: 5 tờ giấy trống,
phải new từng bạn rồi mới gọi phương thức. Gặp lại ở Lab 03–05.