Mô tả bài toán
Nhập một chuỗi ký tự, xóa tất cả các nguyên âm (a, e, i, o, u - cả chữ hoa và thường), in chuỗi kết quả.
Thuật toán
- Đọc chuỗi từ bàn phím (dùng
fgetsđể đọc cả khoảng trắng) - Duyệt từng ký tự của chuỗi
- Nếu ký tự là nguyên âm → dịch chuyển các ký tự sau lên trước 1 vị trí
- Giảm độ dài chuỗi đi 1
- Lặp lại cho đến hết chuỗi
Chương trình C
#include <stdio.h>
#include <string.h>
int main() {
char str[100];
int len, i, j;
printf("Nhap chuoi: ");
fgets(str, sizeof(str), stdin);
// Xóa ký tự newline nếu có
len = strlen(str);
if (len > 0 && str[len - 1] == '\n') {
str[len - 1] = '\0';
len--;
}
// Xóa nguyên âm
for (i = 0; i < len; i++) {
char c = str[i];
// Kiểm tra nguyên âm (cả hoa và thường)
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
// Dịch chuyển các ký tự sau lên trước
for (j = i; j < len; j++) {
str[j] = str[j + 1];
}
len--; // Giảm độ dài
i--; // Kiểm tra lại vị trí hiện tại (vì đã dịch chuyển)
}
}
printf("Chuoi sau khi xoa nguyen am: %s\n", str);
return 0;
}
Kết quả
Nhap chuoi: TutorialsPoint
Chuoi sau khi xoa nguyen am: TtrlsPnt
Phân tích thuật toán
| Bước | i | Ký tự | Là nguyên âm? | Hành động |
|---|---|---|---|---|
| 1 | 0 | T | Không | Giữ lại |
| 2 | 1 | u | Có | Xóa, dịch chuyển, len--, i-- |
| 3 | 1 | t | Không | Giữ lại |
| 4 | 2 | o | Có | Xóa... |
| ... | ... | ... | ... | ... |
Cách tiếp cận tốt hơn: Tạo chuỗi mới
Thay vì dịch chuyển (O(n²)), tạo chuỗi mới chỉ chứa phụ âm (O(n)):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int laNguyenAm(char c) {
c = tolower(c);
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
}
int main() {
char str[100], ketQua[100];
int i, j = 0;
printf("Nhap chuoi: ");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = 0; // Xóa newline
for (i = 0; str[i] != '\0'; i++) {
if (!laNguyenAm(str[i])) {
ketQua[j++] = str[i];
}
}
ketQua[j] = '\0';
printf("Ket qua: %s\n", ketQua);
return 0;
}
So sánh 2 cách
| Tiêu chí | Xóa tại chỗ (In-place) | Tạo chuỗi mới |
|---|---|---|
| Độ phức tạp thời gian | O(n²) - dịch chuyển nhiều lần | O(n) - duyệt 1 lần |
| Bộ nhớ | O(1) - không thêm bộ nhớ | O(n) - cần mảng phụ |
| Code | Phức tạp hơn (i--, len--) | Đơn giản, dễ đọc |
| Phù hợp | Nhúng, bộ nhớ hạn chế | Ứng dụng chung, khuyến nghị |
Mở rộng
- Xóa ký tự số, ký tự đặc biệt
- Chỉ giữ lại chữ cái (isalpha)
- Chuẩn hóa chuỗi: viết hoa chữ cái đầu, xóa khoảng trắng thừa
- Đếm số nguyên âm/phụ âm
Bài toán này rèn luyện thao tác mảng ký tự, con trỏ, và tư duy tối ưu thuật toán.