Bài 5.4: Kỹ thuật tách chữ số bằng vòng lặp trong C++

Bài 5.4: Kỹ thuật tách chữ số bằng vòng lặp trong C++
Chào mừng các bạn quay trở lại với series học lập trình C++ cùng FullhouseDev!
Trong thế giới lập trình, chúng ta thường xuyên làm việc với các số nguyên. Đôi khi, chúng ta cần xử lý số nguyên đó như một toàn bộ, ví dụ như cộng, trừ, nhân, chia. Nhưng cũng có những lúc, bài toán đòi hỏi chúng ta phải "nhìn sâu" vào cấu trúc của số đó, làm việc với từng chữ số tạo nên nó.
Lấy ví dụ, bạn muốn tính tổng các chữ số của một số (ví dụ: 123 -> 1+2+3 = 6), kiểm tra xem một số có phải là số Palindrome (đọc xuôi ngược như nhau) hay không, đếm số lượng chữ số, hoặc thậm chí là đảo ngược một số. Tất cả những bài toán này đều yêu cầu chúng ta có khả năng "tách" rời các chữ số ra khỏi số nguyên ban đầu.
May mắn thay, C++ cung cấp cho chúng ta những công cụ cực kỳ mạnh mẽ và linh hoạt để làm điều này, và bí mật nằm ở việc kết hợp vòng lặp với hai phép toán số học cơ bản: phép chia lấy phần dư (%) và phép chia lấy phần nguyên (/).
Hãy cùng nhau khám phá kỹ thuật quan trọng này!
Nền Tảng: Hai Phép Toán "Ma Thuật"
Để tách chữ số từ một số nguyên, chúng ta sẽ tận dụng hệ thập phân (cơ số 10) mà chúng ta sử dụng hàng ngày. Mọi số nguyên đều có thể được biểu diễn bằng cách sử dụng các lũy thừa của 10.
Phép toán 1: Lấy chữ số cuối cùng
- Sử dụng toán tử modulo
%
với 10 (% 10
). - Kết quả của
số % 10
luôn là phần dư khi chia số đó cho 10. Trong hệ thập phân, phần dư này chính là chữ số hàng đơn vị của số đó. - Ví dụ:
123 % 10 = 3
45 % 10 = 5
7 % 10 = 7
- Sử dụng toán tử modulo
Phép toán 2: Loại bỏ chữ số cuối cùng
- Sử dụng phép chia lấy phần nguyên
/
với 10 (/ 10
). - Khi chúng ta chia một số nguyên cho 10 và chỉ lấy phần nguyên, chúng ta thực chất đang loại bỏ chữ số hàng đơn vị và dịch chuyển tất cả các chữ số còn lại sang phải một vị trí (tương đương với chia cho 10).
- Ví dụ:
123 / 10 = 12
(phần nguyên)45 / 10 = 4
(phần nguyên)7 / 10 = 0
(phần nguyên)
- Sử dụng phép chia lấy phần nguyên
Hãy nhìn kỹ: Với số 123
, 123 % 10
cho ta 3
(chữ số cuối cùng). Sau đó, 123 / 10
cho ta 12
. Nếu lặp lại quá trình này với 12
, 12 % 10
cho ta 2
, và 12 / 10
cho ta 1
. Lặp lại với 1
, 1 % 10
cho ta 1
, và 1 / 10
cho ta 0
.
Thấy điều kỳ diệu chưa? Chúng ta đã tách được lần lượt các chữ số 3
, 2
, 1
từ số 123
bằng cách lặp đi lặp lại hai phép toán đơn giản này cho đến khi số ban đầu trở thành 0
.
Kết Hợp Với Vòng Lặp while
Quá trình lặp đi lặp lại này chính là lúc vòng lặp phát huy sức mạnh của nó. Vòng lặp while
đặc biệt phù hợp vì chúng ta cần tiếp tục quá trình tách chữ số trong khi số ban đầu vẫn còn lớn hơn 0.
Cấu trúc cơ bản sẽ trông như thế này:
while (n > 0) {
// Lay chu so: cs = n % 10;
// Xu ly cs (in, cong, dem, ...)
// Bo cs: n /= 10;
}
Mỗi lần lặp, chúng ta lấy được một chữ số (bắt đầu từ chữ số hàng đơn vị, rồi đến hàng chục, hàng trăm,...). Quá trình dừng lại khi số nguyên trở thành 0, tức là tất cả các chữ số đã được xử lý.
Hãy cùng xem một vài ví dụ cụ thể để thấy rõ kỹ thuật này hoạt động như thế nào trong thực tế.
Ví Dụ Minh Họa
Chúng ta sẽ sử dụng thư viện iostream
để nhập/xuất dữ liệu.
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Nhap mot so nguyen duong: ";
cin >> n;
int n_goc = n;
if (n < 0) {
cout << "Chuong trinh chu yeu lam viec voi so duong. Vui long nhap so duong." << endl;
return 1;
}
cout << "---------------------------------" << endl;
cout << "Bat dau tach chu so cua so: " << n_goc << endl;
// Ví dụ 1: In ra cac chu so tu phai sang trai
cout << "\n**Vi du 1: In ra cac chu so tu phai sang trai**" << endl;
int tmp1 = n_goc;
cout << "Cac chu so (tu phai sang trai): ";
if (tmp1 == 0) {
cout << "0";
} else {
while (tmp1 > 0) {
int cs = tmp1 % 10;
cout << cs << " ";
tmp1 /= 10;
}
}
cout << endl;
cout << "---------------------------------" << endl;
// Ví dụ 2: Tinh tong cac chu so
cout << "\n**Vi du 2: Tinh tong cac chu so**" << endl;
int tmp2 = n_goc;
int tong = 0;
if (tmp2 == 0) {
tong = 0;
} else {
while (tmp2 > 0) {
int cs = tmp2 % 10;
tong += cs;
tmp2 /= 10;
}
}
cout << "Tong cac chu so cua " << n_goc << " la: " << tong << endl;
cout << "---------------------------------" << endl;
// Ví dụ 3: Dem so luong chu so
cout << "\n**Vi du 3: Dem so luong chu so**" << endl;
int tmp3 = n_goc;
int dem = 0;
if (tmp3 == 0) {
dem = 1;
} else {
while (tmp3 > 0) {
dem++;
tmp3 /= 10;
}
}
cout << "So luong chu so cua " << n_goc << " la: " << dem << endl;
cout << "---------------------------------" << endl;
// Ví dụ 4: Dao nguoc so
cout << "\n**Vi du 4: Dao nguoc so**" << endl;
int tmp4 = n_goc;
long long dao_nguoc = 0;
if (tmp4 == 0) {
dao_nguoc = 0;
} else {
while (tmp4 > 0) {
int cs = tmp4 % 10;
dao_nguoc = dao_nguoc * 10 + cs;
tmp4 /= 10;
}
}
cout << "So " << n_goc << " sau khi dao nguoc la: " << dao_nguoc << endl;
return 0;
}
Output (với input là 12345
):
Nhap mot so nguyen duong: 12345
---------------------------------
Bat dau tach chu so cua so: 12345
**Vi du 1: In ra cac chu so tu phai sang trai**
Cac chu so (tu phai sang trai): 5 4 3 2 1
---------------------------------
**Vi du 2: Tinh tong cac chu so**
Tong cac chu so cua 12345 la: 15
---------------------------------
**Vi du 3: Dem so luong chu so**
So luong chu so cua 12345 la: 5
---------------------------------
**Vi du 4: Dao nguoc so**
So 12345 sau khi dao nguoc la: 54321
Giải thích Code Minh Họa
Trong đoạn code trên:
- Chúng ta bắt đầu bằng cách khai báo một biến
n
để lưu trữ số nguyên do người dùng nhập vào. - Biến
n_goc
được dùng để lưu giữ giá trị ban đầu của số, phục vụ cho việc hiển thị kết quả sau này. - Có một phần kiểm tra đơn giản để yêu cầu người dùng nhập số dương, vì kỹ thuật
% 10
và/ 10
hoạt động trực tiếp hiệu quả nhất với số dương. - Chúng ta sử dụng một biến tạm (ví dụ:
tmp1
,tmp2
, v.v.) cho mỗi ví dụ. Điều này cực kỳ quan trọng! Nếu chúng ta sử dụng trực tiếp biếnn
hoặcn_goc
trong vòng lặpwhile
, giá trị của nó sẽ bị thay đổi (/= 10
), và chúng ta sẽ mất số ban đầu cho các phép tính hoặc hiển thị sau này. - Vòng lặp
while (tmp > 0)
: Đây là trái tim của kỹ thuật. Vòng lặp sẽ tiếp tục chạy miễn là biến tạm vẫn còn giá trị dương. int cs = tmp % 10;
: Dòng này thực hiện phép toán modulo 10 để lấy chữ số cuối cùng của số tạm hiện tại. Chữ số này được lưu vào biếncs
.tmp /= 10;
: Dòng này thực hiện phép chia lấy phần nguyên cho 10, cập nhật biến tạm bằng cách loại bỏ chữ số cuối cùng vừa được xử lý.- Phần "Xử lý chữ số": Đây là nơi chúng ta thực hiện các thao tác mong muốn với chữ số
cs
vừa tách được.- Ví dụ 1: Chỉ đơn giản là in chữ số đó ra màn hình. Lưu ý thứ tự in ra là từ phải sang trái (hàng đơn vị trước, hàng chục sau, v.v.).
- Ví dụ 2: Cộng chữ số đó vào biến
tong
để tính tổng. - Ví dụ 3: Chỉ đơn giản là tăng biến đếm
dem
mỗi khi tách được một chữ số. - Ví dụ 4: Xây dựng số đảo ngược bằng công thức
dao_nguoc = dao_nguoc * 10 + cs;
. Công thức này dịch chuyển các chữ số đã có củadao_nguoc
sang trái một hàng (nhân 10) và thêm chữ số mới vào hàng đơn vị.
- Các khối
if (tmp == 0)
được thêm vào để xử lý chính xác trường hợp số đầu vào là 0, vì vòng lặpwhile (tmp > 0)
sẽ không chạy nếutmp
ban đầu là 0.
Tóm Lại
Kỹ thuật tách chữ số bằng vòng lặp while
kết hợp với phép toán % 10
và / 10
là một công cụ vô cùng cơ bản nhưng cực kỳ mạnh mẽ trong lập trình C++. Nó cho phép chúng ta "mổ xẻ" một số nguyên để phân tích hoặc xử lý từng thành phần (chữ số) của nó.
Comments