Mảng 1 chiều trong C – Khai báo, nhập, xuất, duyệt mảng
Mảng một chiều là một trong những cấu trúc dữ liệu cơ bản và quan trọng nhất trong ngôn ngữ lập trình C. Dù bạn là người mới bắt đầu hay đã có kinh nghiệm với lập trình, hiểu rõ về mảng sẽ giúp bạn xây dựng các chương trình hiệu quả hơn. Trong bài viết này, chúng ta sẽ đi sâu vào mọi khía cạnh của mảng một chiều trong C, từ khai báo cơ bản đến các kỹ thuật xử lý nâng cao.
Mảng một chiều trong C là gì?
Mảng một chiều trong C là một cấu trúc dữ liệu tuyến tính được sử dụng để lưu trữ nhiều phần tử có cùng kiểu dữ liệu tại các vị trí bộ nhớ liền kề. Nó giống như một chuỗi các biến cùng loại được đặt cạnh nhau trong bộ nhớ.
Mảng giúp bạn quản lý nhiều giá trị cùng loại dưới một tên biến duy nhất, giúp code trở nên gọn gàng và dễ quản lý hơn.
Thay vì phải khai báo nhiều biến riêng lẻ như score1, score2, score3…, bạn có thể sử dụng một mảng scores[100] để lưu trữ đến 100 điểm số khác nhau. Điều này làm cho việc xử lý dữ liệu trở nên hiệu quả hơn rất nhiều.
Khai báo mảng một chiều trong C
Khai báo mảng trong C rất đơn giản. Cú pháp cơ bản như sau:
kiểu_dữ_liệu tên_mảng[kích_thước];
Trong đó:
- kiểu_dữ_liệu: Là kiểu dữ liệu của các phần tử trong mảng (int, float, char…)
- tên_mảng: Là tên bạn đặt cho mảng
- kích_thước: Là số lượng phần tử tối đa mà mảng có thể chứa
Ví dụ về khai báo mảng:
int numbers[5]; // Mảng số nguyên chứa 5 phần tử
float prices[100]; // Mảng số thực chứa 100 phần tử
char name[50]; // Mảng ký tự chứa 50 phần tử
Khởi tạo giá trị cho mảng ️
Có nhiều cách để khởi tạo giá trị cho mảng trong C:
1. Khởi tạo tại thời điểm khai báo:
int scores[5] = {85, 92, 78, 90, 88}; // Khởi tạo đầy đủ các phần tử
int numbers[10] = {1, 2, 3}; // Chỉ khởi tạo 3 phần tử đầu, các phần tử còn lại bằng 0
Nếu không chỉ định kích thước nhưng cung cấp giá trị khởi tạo, trình biên dịch sẽ tự xác định kích thước mảng:
int ages[] = {25, 30, 22, 27, 19}; // Mảng có kích thước 5
2. Khởi tạo trong quá trình thực thi (khởi tạo động):
int marks[5];
for (int i = 0; i < 5; i++) {
scanf("%d", &marks[i]); // Nhập giá trị từ người dùng
}
Truy cập phần tử trong mảng
Trong C, các phần tử mảng được đánh chỉ số bắt đầu từ 0 (không phải từ 1). Để truy cập một phần tử trong mảng, bạn sử dụng cú pháp:
mảng[chỉ_số]
Ví dụ:
int scores[5] = {85, 92, 78, 90, 88};
printf("Điểm số đầu tiên: %dn", scores[0]); // Hiển thị 85
printf("Điểm số thứ ba: %dn", scores[2]); // Hiển thị 78
// Thay đổi giá trị phần tử
scores[1] = 95; // Thay đổi phần tử thứ hai thành 95
Lưu ý quan trọng: Việc truy cập vào chỉ số nằm ngoài phạm vi của mảng (ví dụ: scores[10] khi mảng chỉ có 5 phần tử) có thể dẫn đến hành vi không xác định và các lỗi nghiêm trọng trong chương trình.
Nhập xuất mảng trong C
Nhập mảng từ bàn phím
Để nhập các giá trị cho mảng từ bàn phím, chúng ta thường sử dụng vòng lặp kết hợp với hàm scanf():
#include <stdio.h>
int main() {
int n;
int arr[100]; // Khai báo mảng tối đa 100 phần tử
printf("Nhập số lượng phần tử (tối đa 100): ");
scanf("%d", &n);
// Nhập các phần tử
printf("Nhập %d phần tử:n", n);
for (int i = 0; i < n; i++) {
printf("arr[%d] = ", i);
scanf("%d", &arr[i]);
}
return 0;
}
Xuất mảng ra màn hình
Để hiển thị các phần tử của mảng, chúng ta cũng sử dụng vòng lặp kết hợp với hàm printf():
// Xuất các phần tử ra màn hình
printf("Các phần tử trong mảng:n");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("n");
Duyệt mảng trong C
Duyệt mảng là quá trình truy cập từng phần tử trong mảng để thực hiện các thao tác với chúng. Có nhiều cách duyệt mảng trong C:
1. Duyệt mảng bằng vòng lặp for
Đây là cách phổ biến nhất để duyệt mảng:
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i]; // Tính tổng các phần tử
}
2. Duyệt mảng bằng vòng lặp while
int i = 0;
while (i < n) {
printf("%d ", arr[i]);
i++;
}
3. Duyệt mảng bằng vòng lặp do-while
int i = 0;
do {
printf("%d ", arr[i]);
i++;
} while (i < n);
Các phép toán cơ bản với mảng một chiều
1. Tính tổng các phần tử trong mảng
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
printf("Tổng các phần tử: %dn", sum);
2. Tìm giá trị lớn nhất và nhỏ nhất
int max = arr[0];
int min = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
}
printf("Giá trị lớn nhất: %dn", max);
printf("Giá trị nhỏ nhất: %dn", min);
3. Tính giá trị trung bình
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
float average = (float)sum / n;
printf("Giá trị trung bình: %.2fn", average);
4. Đếm số lần xuất hiện của một giá trị
int value, count = 0;
printf("Nhập giá trị cần đếm: ");
scanf("%d", &value);
for (int i = 0; i < n; i++) {
if (arr[i] == value) {
count++;
}
}
printf("Số lần xuất hiện của %d là: %dn", value, count);
Sắp xếp mảng trong C
Sắp xếp là một trong những thao tác phổ biến nhất với mảng. Dưới đây là hai thuật toán sắp xếp cơ bản:
1. Sắp xếp nổi bọt (Bubble Sort)
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
// Hoán đổi arr[j] và arr[j+1]
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
2. Sắp xếp chọn (Selection Sort)
void selectionSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
// Tìm phần tử nhỏ nhất trong mảng chưa sắp xếp
int min_idx = i;
for (int j = i+1; j < n; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}
// Hoán đổi phần tử nhỏ nhất với phần tử đầu tiên
int temp = arr[min_idx];
arr[min_idx] = arr[i];
arr[i] = temp;
}
}
Tìm kiếm trong mảng
1. Tìm kiếm tuyến tính (Linear Search)
int linearSearch(int arr[], int n, int x) {
for (int i = 0; i < n; i++) {
if (arr[i] == x) {
return i; // Trả về vị trí nếu tìm thấy
}
}
return -1; // Trả về -1 nếu không tìm thấy
}
2. Tìm kiếm nhị phân (Binary Search) - chỉ áp dụng cho mảng đã sắp xếp
int binarySearch(int arr[], int left, int right, int x) {
while (left <= right) {
int mid = left + (right - left) / 2;
// Kiểm tra xem x có ở giữa không
if (arr[mid] == x) {
return mid;
}
// Nếu x lớn hơn, bỏ qua nửa bên trái
if (arr[mid] < x) {
left = mid + 1;
}
// Nếu x nhỏ hơn, bỏ qua nửa bên phải
else {
right = mid - 1;
}
}
// Nếu không tìm thấy
return -1;
}
Các lỗi thường gặp khi làm việc với mảng một chiều ⚠️
- Truy cập ngoài phạm vi mảng: Khi bạn truy cập vào chỉ số nằm ngoài kích thước mảng đã khai báo, chương trình có thể gặp lỗi không xác định.
- Không kiểm tra kích thước mảng khi nhập liệu: Cần đảm bảo số lượng phần tử nhập vào không vượt quá kích thước mảng đã khai báo.
- Quên khởi tạo mảng: Nếu không khởi tạo giá trị cho mảng, các phần tử sẽ chứa giá trị rác.
- Lỗi off-by-one: Sử dụng sai điều kiện dừng trong vòng lặp, dẫn đến bỏ sót phần tử cuối hoặc truy cập quá phạm vi.
Ứng dụng thực tế của mảng một chiều
Mảng một chiều có rất nhiều ứng dụng thực tế trong lập trình:
- Lưu trữ và xử lý danh sách: Danh sách sinh viên, danh sách sản phẩm...
- Xử lý thống kê: Tính toán điểm trung bình, tìm giá trị lớn nhất/nhỏ nhất...
- Lưu trữ dữ liệu đồ họa: Các điểm ảnh, tọa độ...
- Cài đặt các cấu trúc dữ liệu khác: Stack, Queue, Heap...
- Xử lý chuỗi: Trong C, chuỗi được biểu diễn như một mảng các ký tự.
So sánh mảng một chiều với các cấu trúc dữ liệu khác
Tiêu chí | Mảng một chiều | Danh sách liên kết | Cây |
---|---|---|---|
Truy cập ngẫu nhiên | O(1) - Rất nhanh | O(n) - Chậm | O(log n) - Trung bình |
Thêm/Xóa phần tử | O(n) - Chậm | O(1) - Rất nhanh | O(log n) - Trung bình |
Kích thước bộ nhớ | Cố định khi khai báo | Có thể thay đổi | Có thể thay đổi |
Bộ nhớ phụ trợ | Không cần | Cần (con trỏ) | Cần (con trỏ) |
Mẹo tối ưu khi làm việc với mảng một chiều
- Sử dụng hằng số để định nghĩa kích thước mảng: Giúp code dễ bảo trì hơn.
#define MAX_SIZE 100 int arr[MAX_SIZE];
- Sử dụng cấp phát động khi kích thước mảng cần xác định trong thời gian chạy:
int *arr = (int*)malloc(n * sizeof(int));
- Truyền mảng vào hàm để tách biệt code và tăng khả năng tái sử dụng.
- Kiểm tra biên để tránh lỗi truy cập ngoài phạm vi.
- Sử dụng thư viện <stdlib.h> để sử dụng các hàm sắp xếp và tìm kiếm có sẵn.
Kết luận
Mảng một chiều là cấu trúc dữ liệu cơ bản nhưng vô cùng quan trọng trong lập trình C. Hiểu và sử dụng thành thạo mảng sẽ giúp bạn xây dựng nền tảng vững chắc cho việc học các cấu trúc dữ liệu phức tạp hơn. Bài viết đã cung cấp cho bạn kiến thức từ cơ bản đến nâng cao về mảng một chiều, bao gồm cách khai báo, nhập xuất, các thao tác cơ bản và các thuật toán thông dụng.
Hãy thực hành thường xuyên và áp dụng các kiến thức này vào các bài tập thực tế để nâng cao kỹ năng lập trình của bạn!
Tham khảo thêm: