Bài viết này giới thiệu với bạn một số bài tập lập trình C từ cơ bản đến nâng cao để ôn tập những kiến thức về: Flowchart - sơ đồ thuật toán, biến và kiểu dữ liệu, toán tử và biểu thức, nhập xuất dữ liệu, điều kiện rẽ nhánh, vòng lặp - loop. Bạn chú ý áp dụng những kiến thức đã học để giải các bài toán sau.
Bài 1
Nhập vào số nguyên N (0 <= N <= 10). Tính N giai thừa (N!).
Phân tích bài toán
- N! được tính theo công thức là:
- Nếu N = 0 thì N! = 1
- Nếu N > 0 thì N! = N _ (N - 1) _ (N -2) *...1
- Do đó, nếu nhập N = 0 thì in ra luôn kết quả 0! = 1
- Trường hợp còn lại, sử dụng vòng lặp for từ N về 1 để tính dồn tích của các số để ra N!
Code
#include <stdio.h>
int main() {
int N, giaiThua, i;
printf("Nhap N: ");
scanf("%d", &N);
if (N < 0 || N > 10) {
printf("Ban da nhap sai");
}
else if (N == 0) {
printf("Ket qua 0! la: 1");
}
else {
giaiThua = 1;
for (i = N; i >= 1; i--) {
giaiThua *= i;
}
printf("Ket qua %d! la: %d", N, giaiThua);
}
return 0;
}
Bài 2
Nhập vào số tự nhiên N (N <= 1000000000). Kiểm tra xem N có phải là số chính phương hay không.
Phân tích bài toán
- Số chính phương là số tự nhiên có căn bậc hai là số tự nhiên, hay nói cách khác là nó được viết dưới dạng i^2 với i cũng là số tự nhiên.
- Do đó, để kiểm tra xem 1 số có phải là số chính phương hay không ta có thể sử dụng 1 vòng lặp for với i chạy từ 1 đến N để tính i^2.
- Nếu tồn tại số i thỏa mãn i^2 = N thì suy ra N là số chính phương
- Nếu không tồn tại số i thỏa mãn i^2 = N thì N không phải số chính phương
- Tuy nhiên, có một chú ý ở đây là ta không cần cho i chạy từ 1 đến N mà thực chất chỉ cần cho i chạy từ 1 đến giá trị mà i^2 > N là dừng lại. Vì lúc đó i^2 đã lớn hơn N rồi nên nếu i tiếp tục tăng, giá trị i^2 càng lớn hơn N.
Code
#include <stdio.h>
int main() {
int N, i, laSoChinhPhuong;
printf("Nhap N: ");
scanf("%d", &N);
if (N < 1 || N > 1000000000) {
printf("Ban da nhap sai");
} else {
laSoChinhPhuong = 0;
for (i = 1; i*i <= N; i++) {
if (i*i == N) {
laSoChinhPhuong = 1;
break;
}
}
if (laSoChinhPhuong)
printf("%d la so chinh phuong", N);
else
printf("%d khong la so chinh phuong", N);
}
return 0;
}
Bài 3
Nhập vào số tự nhiên N (N <= 100). Thực hiện các yêu cầu sau:
- In ra màn hình tất cả các ước số của N
- Tính tổng giá trị các ước số lẻ của N
- Đếm số lượng các ước số chẵn của N
Phân tích bài toán
- Số K được gọi là ước số của N nếu N chia hết cho K, hay nói cách khác là số dư của N cho K bằng 0
- Để in ra tất cả các ước số của N ta có thể sử dụng vòng lặp for với i chạy từ 1 đến N. Tại mỗi bước, kiểm tra số dư r của N cho i, nếu r = 0 thì i chính là ước số của N. Suy ra in ra i.
- Để tính tổng giá trị các ước số lẻ, ta cần kiểm tra thêm điều kiện i phải là số lẻ. Tương tự để đếm số lượng các ước số chẵn, ta cần thêm điều kiện i phải là số chẵn.
- Để kiểm tra 1 số i là số chẵn, ta kiểm tra số dư của i cho 2. Nếu số dư đó bằng 0 thì i là số chẵn, ngược lại i là số lẻ.
Code
#include <stdio.h>
int main() {
int N, i, tongUocLe = 0, soLuongUocChan = 0;
printf("Nhap N: ");
scanf("%d", &N);
if (N < 1 || N > 100) {
printf("Ban da nhap sai");
} else {
// In ra man hinh tat ca uoc so cua N
printf("Tat ca cac uoc so la: ");
for (i = 1; i <= N; i += 1) {
if (N % i == 0) printf("%d ", i);
}
printf("\n");
// Tinh tong gia tri cac uoc so le cua N
for (i = 1; i <= N; i += 1) {
if (N % i == 0 && i % 2 == 1) tongUocLe += i;
}
printf("Tong gia tri cac uoc so le la: %d\n", tongUocLe);
// Dem so luong gia tri cac uoc so chan cua N
for (i = 1; i <= N; i += 1) {
if (N % i == 0 && i % 2 == 0) soLuongUocChan += 1;
}
printf("So luong cac uoc so chan la: %d\n", soLuongUocChan);
}
return 0;
}
Bài 4
Nhập vào 2 số tự nhiên a và b (a, b <= 1000000). Tìm ước chung lớn nhất của 2 số a và b.
Phân tích bài toán
- Số K được gọi là ước số của N nếu N chia hết cho K, hay nói cách khác là số dư của N cho K bằng 0
- Ước số lớn nhất của 1 số là chính số đó. Vì vậy, để tìm ước số chung lớn nhất của 2 số ta có thể làm như sau:
- Kiểm tra và tìm ra số nhỏ hơn trong 2 số, giả sử là M
- Dùng vòng lặp for với i chạy từ M về 1 để kiểm tra đến khi nào gặp 1 số i mà cả 2 số a và b đều chia hết thì i chính là ước số chung lớn nhất của a và b.
Code
#include <stdio.h>
int main() {
int a, b, Min, i, USCLN;
printf("Nhap a: ");
scanf("%d", &a);
printf("Nhap b: ");
scanf("%d", &b);
if (a < 1 || a > 1000000 || b < 1 || b > 1000000) {
printf("Ban da nhap sai");
} else {
// Tim min cua 2 so
Min = a < b ? a : b;
// Tim USCLN
for (i = Min; i >= 1; i--) {
if (a % i == 0 && b % i == 0) {
USCLN = i;
break;
}
}
printf("USCLN cua %d va %d la: %d", a, b, USCLN);
}
return 0;
}
Bài 5
Nhập vào số tự nhiên N (N <= 50000), tính giá trị của biểu thức:
S(N) = 1^2 + 2^2 + ... + N^2
Chú ý:
- Toán tử ^ hiểu là toán tử mũ trong toán học, không phải toán tử XOR bit
- Sử dụng kiến thực lập trình đã học, không sử dụng hàm có sẵn, không dùng toán học để chuyển đổi về biểu thức rút gọn
Phân tích bài toán
- Để tính giá trị của biểu thức trên, ta chỉ cần dùng 1 vòng lặp for với i chạy từ 1 đến N, với mỗi giá trị của i ta tính i*i rồi cộng dồn vào giá trị tổng.
- Chỉ có 1 chú ý ở đây là N <= 50000, mà 50000*50000=2500000000. Do đó, ta không thể dùng biến kiểu int để lưu giá trị của tổng mà phải dùng kiểu long long int.
Code
#include <stdio.h>
int main() {
int i, N;
long long int tong = 0;
printf("Nhap N: ");
scanf("%d", &N);
if (N < 1 || N > 50000) {
printf("Ban da nhap sai");
} else {
for (i = 1; i <= N; i += 1) {
tong += i*i;
}
printf("Tong la: %lld", tong);
}
return 0;
}
Bài 6
Nhập vào số tự nhiên N (N <= 50000), tính giá trị của biểu thức:
S(N) = 1 + 1/3 + + 1/5 + ... + 1/(2N + 1)
Chú ý:
- Các phép chia bên trên được hiểu là phép chia toán học (lấy giá trị chính xác), không phải phép chia nguyên.
- Kết quả cuối cùng làm tròn đến 4 chữ số sau dấu phẩy
- Sử dụng kiến thực lập trình đã học, không sử dụng hàm có sẵn, không dùng toán học để chuyển đổi về biểu thức rút gọn
Phân tích bài toán
- Để tính giá trị biểu thức, ta dùng vòng lặp for với i chạy từ 0 đến N, với mỗi giá trị của i ta tính 1/(2*i + 1) rồi cộng dồn vào biến lưu kết quả.
- Chú ý:
- Trong toán học, 1/(2*i + 1) sẽ cho kết quả là 1 số thực
- Trong lập trình, 1/(2*i + 1) sẽ cho kết quả là 1 số nguyên. Vì vậy, ta cần phải ép kiểu tử số hoặc mẫu số của phép chia về số thực để thu được kết quả như mong muốn.
- Ngoài ra, để hiển thị kết quả làm tròn 4 chữ số thập phân, ta dùng format %.4f
Code
#include <stdio.h>
int main() {
int i, N;
float tong = 0;
printf("Nhap N: ");
scanf("%d", &N);
if (N < 1 || N > 50000) {
printf("Ban da nhap sai");
} else {
for (i = 0; i <= N; i += 1) {
tong += 1.0 / (2 * i + 1);
}
printf("Tong la: %.4f", tong);
}
return 0;
}
Bài 7
Nhập vào số tự nhiên N (N <= 10), tính giá trị của biểu thức:
S(N) = 2^1 + 2^2 + ... + 2^N
Chú ý:
- Toán tử ^ hiểu là toán tử mũ trong toán học, không phải toán tử XOR bit
- Sử dụng kiến thực lập trình đã học, không sử dụng hàm có sẵn, không dùng toán học để chuyển đổi về biểu thức rút gọn
Phân tích bài toán
- Để tính giá trị biểu thức, ta cần dùng 2 vòng lặp for lồng nhau
- Vòng lặp for bên ngoài sẽ có i chạy từ 1 đến N để cộng tổng các giá trị 2^j lại với nhau
- Vòng lặp for bên trong sẽ có j chạy từ 1 đến i để tính giá trị 2^j
Code
#include <stdio.h>
int main() {
int i, j, N, temp, tong = 0;
printf("Nhap N: ");
scanf("%d", &N);
if (N < 1 || N > 10) {
printf("Ban da nhap sai");
} else {
// Cong tong: 2^1 + 2^2 + ... + 2^N
for (i = 1; i <= N; i += 1) {
temp = 1;
// Tinh gia tri: 2^i
for (j = 1; j <= i; j += 1) {
temp *= 2;
}
tong += temp;
}
printf("Tong la: %d", tong);
}
return 0;
}
Bài 8
Viết chương trình máy tính đơn giản thỏa mãn những yêu cầu sau:
Ban đầu hiển thị ra menu:
Menu:
0. Thoat chuong trinh
1. Tinh tong 2 so thuc: a + b
2. Tinh hieu 2 so thuc: a - b
3. Tinh tich 2 so thuc: a * b
4. Tinh thuong 2 so thuc: a / b
Ban muon lam gi tiep theo:
Khi người dùng nhập vào số với giá trị khác số 0, 1, 2, 3, 4 thì hiển thị Ban da nhap sai rồi hiển thị Ban muon lam gi tiep theo: để yêu cầu người dùng nhập lại.
Khi người dùng nhập vào số 0 thì thoát chương trình.
Khi người dùng nhập vào 1 trong các số 1, 2, 3, 4 (giả sử là số t) thì hiển thị Nhap vao gia tri 2 so: để người dùng lần lượt nhập vào 2 số a và b.
- Nếu t = 1 thì tính tổng 2 số (giả sử là tong) rồi hiển thị Tong 2 so la: tong
- Nếu t = 2 thì tính hiệu 2 số (giả sử là hieu) rồi hiển thị Hieu 2 so la: hieu
- Nếu t = 3 thì tính tích 2 số (giả sử là tich) rồi hiển thị Tich 2 so la: tich
- Nếu t = 4 thì tính thương 2 số (giả sử là thuong) rồi hiển thị Thuong 2 so la: thuong. Chú ý: trong trường hợp này, nếu người dùng nhập vào giá trị của b = 0 thì hiển thị Thuong 2 so la: vo cung
Sau khi thực hiện mỗi lệnh thì lại hiển thị menu như ban đầu.
#include <stdio.h>
int main()
{
float a, b;
int lenh, inMenu = 1;
int nhapHopLe;
while (1) {
// In ra menu
if (inMenu == 1) {
printf("\nMenu:\n");
printf("0. Thoat chuong trinh\n");
printf("1. Tinh tong 2 so thuc: a + b\n");
printf("2. Tinh hieu 2 so thuc: a - b\n");
printf("3. Tinh tich 2 so thuc: a * b\n");
printf("4. Tinh thuong 2 so thuc: a / b\n");
}
printf("\nBan muon lam gi tiep theo: ");
// Nhap lenh
nhapHopLe = scanf("%d", &lenh);
if (nhapHopLe != 1) {
printf("\nBan da nhap sai");
inMenu = 0;
fflush(stdin);
continue;
}
// Nhap lenh va kiem tra lenh khong hop le
if (lenh != 0 && lenh != 1 && lenh != 2 && lenh != 3 && lenh != 4) {
printf("\nBan da nhap sai");
inMenu = 0;
continue;
}
// Kiem tra dieu kien thoat chuong trinh
if (lenh == 0) {
break;
}
printf("Nhap vao gia tri 2 so: ");
// Nhap va kiem tra a
nhapHopLe = scanf("%f", &a);
if (nhapHopLe != 1) {
printf("\nBan da nhap sai");
inMenu = 0;
fflush(stdin);
continue;
}
// Nhap va kiem tra b
nhapHopLe = scanf("%f", &b);
if (nhapHopLe != 1) {
printf("\nBan da nhap sai");
inMenu = 0;
fflush(stdin);
continue;
}
// Tinh ket qua
if (lenh == 1) {
printf("Tong 2 so la: %g", a + b);
} else if (lenh == 2) {
printf("Hieu 2 so la: %g", a - b);
} else if (lenh == 3) {
printf("Tich 2 so la: %g", a * b);
} else if (b == 0) {
printf("Thuong 2 so la: vo cung");
} else {
printf("Thuong 2 so la: %g", a / b);
}
printf("\n");
inMenu = 1;
}
return 0;
}