Mảng (Array) trong C/C++

Mảng trong C/C++ là gì? Nếu chưa biết, mời bạn cùng Quantrimang.com tìm hiểu những điều cần biết về mảng C++/C nhé!

Mảng là một loại cấu trúc dữ liệu trong ngôn ngữ lập trình C/C++, nó lưu trữ một tập hợp tuần tự các phần tử cùng kiểu với độ dài cố định. Mảng thường được sử dụng để lưu trữ tập hợp dữ liệu, nhưng nó cũng hữu dụng khi dùng để lưu trữ một tập hợp biến có cùng kiểu.

Thay vì khai báo biến một cách rời rạc, như biến bien1, bien1,… và bien99, bạn có thể khai báo một mảng các giá trị như bien[0], bien[1] và … bien[99] để biểu diễn các giá trị riêng biệt. Một phần tử cụ thể của mảng có thể được truy cập qua index (chỉ số).

Tất cả mảng đều bao gồm các vị trí nhớ liền kề nhau. Địa chỉ thấp nhất tương ứng với phần tử đầu tiên và địa chỉ cao nhất tương ứng với thành phần cuối cùng của mảng.

Tại sao cần dùng tới mảng?

Bạn có thể dùng các biến mảng bình thường (v1, v2, v3…) khi có một số lượng nhỏ các đối tượng. Thế nhưng nếu muốn lưu trữ nhiều trường hợp, việc quản lý chúng sẽ khó hơn với các biến bình thường. Ý tưởng cho sự ra đời của mảng đại diện cho nhiều trường hợp dùng biến.

Ưu điểm:

  • Tối ưu hóa code: Bạn có thể trích xuất hoạc phân loại dữ liệu hiệu quả.
  • Truy cập ngẫu nhiên: Lấy dữ liệu nằm ở một vị trí index.

Nhược điểm:

Giới hạn kích thước:Chỉ có thể lưu trữ kích thước cố định của các phần tử trong mảng. Nó không mở rộng kích thước ở thời gian chạy..

Array vs Pointer

Array và pointer là hai nhân tố khác nhau trong lập trình C/C++. Sự nhầm lẫn thường xảy ra do tên mảng chỉ địa chỉ của nhân tố đầu tiên và mảng thường được chuyển dưới dạng poiter (ngay cả khi bạn dùng dấu ngoặc vuông). Vì thế, hãy lưu ý trước khi dùng array và pointer trong lập trình C/C++.

Khai báo mảng trong C/C++

Để khai báo một mảng trong ngôn ngữ C/C++, bạn xác định kiểu của phần tử và số lượng các phần tử được yêu cầu bởi biến đó như sau:

Kieu Ten_mang [ Kich_co_mang ];

Đây là mảng một chiều. Kich_co_mang phải là một số nguyên lớn hơn 0 và Kieu phải hợp lệ trong ngôn ngữ C/C++. Ví dụ, khai báo mảng balance với 10 phần tử có kiểu double, sử dụng câu lệnh sau đây:

char balance[10];

Khởi tạo mảng trong C/C++

Bạn có thể khởi tạo mảng trong C/C++ hoặc từng phần tử một hoặc sử dụng một câu lệnh như dưới đây:

int balance[5] = {15, 20, 25, 30, 35};

Số lượng các giá trị trong dấu ngoặc nhọn {} không được lớn hơn số lượng phần tử khai báo trong dấu ngoặc vuông [].

Nếu bạn không khai báo kích cỡ mảng thì mảng vừa đủ lớn để giữ các giá trị được khởi tạo. Vì vậy nếu viết như dưới đây bạn vẫn sẽ nhận được mảng giống hệt bên trên:

int balance[] = {15, 20, 25, 30, 35};

Bạn có thể tạo ra cùng một mảng giống như đã làm trong ví dụ trước.

balance[4] = 35;

Câu lệnh bên trên gán phần tử thứ 5 của mảng có giá trị 35. Tất cả các mảng đều có chỉ số (index) đầu tiên bằng 0, đây được gọi là chỉ số cơ bản và phần tử cuối cùng của mảng có chỉ số bằng độ lớn của mảng trừ đi 1. Dưới đây là cách biểu diễn hình họa cho chuỗi khai báo bên trên thông qua chỉ số:

01234
balance1520253035

Truy cập các phần tử mảng trong C/C++

Một mảng được truy cập bởi cách đánh chỉ số trong tên của mảng. Dưới đây là một cách truy cập một giá trị của mảng:

int hocphi = hocphik60[55];

Câu lệnh trên lấy phần tử thứ 56 của mảng và gán giá trị này cho biến hocphi. Dưới đây là một ví dụ về việc sử dụng với tất cả mô tả bên trên:

#include <iostream> 
using namespace std; 
#include <iomanip> 
using std::setw; 
int main () 
{ 
   int n[10]; 
   //n la mot mang gom 10 so nguyen 
   //khoi tao gia tri cac phan tu cua mang n la 0 
   for (int i = 0; i < 10; i++) 
   { 
      n[i] = i + 100; 
      //thiet lap phan tu tai vi tri i la i + 100 
   } 
   cout << "Phan tu thu:" << setw(13) << "Gia tri la:" << endl; 
   //hien thi gia tri cua moi phan tu 
   for (int j = 0; j < 10; j++) 
   { 
      cout << setw(7)<< j << setw(13) << n[j] << endl; 
   } return 0; }
Chương trình này sử dụng hàm setw(so_nguyen) trong C/C++ để định dạng output. Tại đây, tham số so_nguyen là một số chỉ độ rộng của kết quả mà bạn muốn hiển thị. Chẳng hạn, với so_nguyen là 3 tức là bạn dành 3 vị trí để in kết quả, nếu kết quả cần hiển thị là thừa thì nó sẽ bị cắt bớt, nếu thiếu thì chèn thêm khoảng trống vào. Hàm setw() được dùng cho cả coutcin.

Chạy chương trình C/C++ trên sẽ cho kết quả như hình sau:

Kết quả truy cập các phần tử mảng trong C/C++

Chi tiết về mảng trong C/C++

Mảng là một phần rất quan trọng trong ngôn ngữ C/C++. Dưới đây là những định nghĩa quan trọng liên quan đến một mảng cụ thể mà được trình bày rõ ràng hơn cho các lập trình viên C/C++:

Khái niệmMiêu tả

Mảng đa chiều trong C/C++

C/C++ hỗ trợ các mảng đa chiều. Mẫu đơn giản nhất của mảng này là mảng hai chiều

Con trỏ tới một mảng trong C/C++

Bạn có thể trỏ tới phần tử đầu tiên của mảng một cách đơn giản chỉ bởi xác định tên mảng đó, chứ không phải một chỉ số

Truyền mảng tới hàm như là tham số trong C/C++

Bạn có thể truyền tới hàm một điểm trỏ chỉ tới một mảng bởi xác định tên mảng chứ không phải là một chỉ số

Trả về mảng từ hàm trong C/C++

C/C++ cho phép một hàm có thể trả về một mảng

Mảng đa chiều trong C++

C++ hỗ trợ các mảng đa chiều. Dưới đây là mẫu chung của một khai báo mảng đa chiều:

kieu_du_lieu ten_mang[kich_co_1][kich_co_2]...[kich_co_N];

Ví dụ, khai báo sau tạo một mảng số nguyên 3 chiều: 5. 10. 4:

int hocphi[5][10][4];

Mảng hai chiều trong C++

Mẫu đơn giản nhất của mảng đa chiều là mảng hai chiều. Một mảng hai chiều về bản chất là danh sách của các mảng một chiều. Để khai báo một mảng hai chiều integer với kích cỡ x, y, bạn nên viết như sau:

kieu_du_lieu ten_mang [ x ][ y ];

Ở đây, kieu_du_lieu có thể là bất kỳ kiểu dữ liệu có hiệu lực nào và ten_mang sẽ là một định danh C++ có hiệu lực.

Một mảng hai chiều có thể như là một bảng mà có x hàng và y cột. Một mảng hai chiều a chứa 3 hàng và 4 cột có thể được hiển thị như sau:

Mảng hai chiều trong C++

Như vậy, mỗi phần tử trong mảng a được định danh bởi một tên phần tử trong kiểu mẫu a[i][j], với a là tên mảng và i, j là các subscript – chỉ số được xác định duy nhất mỗi phần tử trong a.

Khởi tạo mảng hai chiều trong C++

Các mảng đa chiều có thể được khởi tạo bởi xác định các giá trị trong dấu móc vuông cho mỗi hàng. Sau đây là một hàng với 3 hàng và mỗi hàng chứa 4 cột.

int a[3][4] = {
 {0, 1, 2, 3} , /* khoi tao gia tri cho hang ma co chi muc la 0 */
 {4, 5, 6, 7} , /* khoi tao gia tri cho hang ma co chi muc la 1 */
 {8, 9, 10, 11} /* khoi tao gia tri cho hang ma co chi muc la 2 */
};

Các dấu ngoặc ôm, mà chỉ các hàng giá trị là tùy ý. Khởi tạo sau là tương đương với ví dụ trên:

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

Truy cập các phần tử của mảng hai chiều trong C++

Các phần tử mảng hai chiều được truy cập bởi sử dụng các chỉ số, ví dụ chỉ số hàng và chỉ số cột. Ví dụ:

int val = a[2][3];

Lệnh trên sẽ truy cập vào phần tử thứ 4 từ hàng thứ 3 của mảng. Bạn có thể kiểm tra lại nó trong sơ đồ trên. Bây giờ chúng ta xem xét ví dụ dưới đây, chúng tôi đã sử dụng các vòng lặp lồng vào nhau để xử lý một mảng hai chiều:

include <iostream>
using namespace std;
int main ()
{
  //mang sau co 5 hang va 2 cot.
  int a[5][2] = {{0,0}, {1,2}, {2,4}, {3,6},{4,8}};
  //hien thi gia tri cua cac phan tu trong mang
  for (int i = 0; i < 5; i++)
  for (int j = 0; j < 2; j++)
  {
  cout << "Gia tri cua a[" << i << "][" << j << "] la: ";
  cout << a[i][j]<< endl;
  }
return 0;
}

Chạy chương trình C++ trên sẽ cho kết quả như hình sau:

Truy cập các phần tử của mảng hai chiều trong C++

Như phần trên đã giải thích, bạn có thể có các mảng với số chiều bất kỳ, nhưng hầu hết các mảng bạn tạo ra sẽ là một hoặc hai chiều.

Con trỏ tới một mảng trong C++

Có thể bạn sẽ không hiểu chương này tới khi bạn đã đọc qua chương về Con trỏ trong C++.

Vì thế giả sử rằng bạn đã hiểu biết chút nào đó về con trỏ trong C++, vậy chúng ta cùng bắt đầu: Một tên mảng là một con trỏ hằng số tới phần tử đầu tiên của mảng. Vì thế, trong khai báo:

double phithuebao[50];

phithuebao là một con trỏ tới &phithuebao[0], mà là địa chỉ của phần tử đầu tiên của mảng phithuebao. Do vậy, đoạn chương trình sau gán p địa chỉ của phần tử đầu tiên của phithuebao:

double *p; 
double phithuebao[10]; 
p = phithuebao;

Sử dụng các tên mảng như là các con trỏ hằng số là hợp lệ, và ngược lại. Vì thế, *(phithuebao + 4) là cách chính thống để truy cập dữ liệu tại phithuebao[4].

Một khi bạn lưu địa chỉ của phần tử đầu tiên trong p, bạn có thể truy cập các phần tử mảng bởi sử dụng *p, *(p+1), *(p+2), ... Dưới đây là ví dụ để chỉ tất cả các khái niệm được đề cập ở trên:

#include <iostream> 
using namespace std; 
int main () 
{ 
    //mang sau co 5 phan tu. 
    double phithuebao[5] = {1000.0, 2.0, 3.4, 17.0, 50.0}; 
    double *p; 
    p = phithuebao; 
    // hien thi gia tri cac phan tu trong mang 
    cout << "Hien thi gia tri mang boi su dung con tro!" << endl; 
    for (int i = 0; i < 5; i++) 
    { 
        cout << "Gia tri cua *(p + " << i << ") la: "; 
        cout << *(p + i) << endl; 
    } 
    cout << "Hien thi gia tri mang boi su dung phithuebao lam dia chi!" << endl; 
    for (int i = 0; i < 5; i++) 
    { 
        cout << "*Gia tri cua (phithuebao + " << i << ") la: "; 
        cout << *(phithuebao + i) << endl; 
    } 
return 0; 
}

Chạy chương trình C++ trên sẽ cho kết quả như hình sau:

Con trỏ tới một mảng trong C++

Trong ví dụ trên, p là một con trỏ tới double, mà có nghĩa là nó có thể lưu giữ địa chỉ của một biến kiểu double. Một khi chúng ta có địa chỉ trong p, thì sau đó *p sẽ cung cấp giá trị có sẵn tại địa chỉ được lưu trong p, như chúng tôi đã chỉ trong ví dụ trên.

Truyền mảng như là các tham số hàm trong C++

Trả về mảng từ hàm trong C++

C++ không cho phép bạn trả về toàn bộ một mảng như là một tham số tới một hàm. Tuy nhiên, bạn có thể trả về một con trỏ tới một mảng bởi xác định tên mảng đó mà không phải là một chỉ số. Bạn sẽ học về con trỏ trong chương tới, vì thế bạn có thể bỏ qua chương này tới khi bạn hiểu khái niệm về Con trỏ trong C++.

Nếu bạn muốn trả về một mảng một chiều từ một hàm, bạn sẽ phải khai báo một hàm trả về một con trỏ như trong ví dụ sau:

int * tenHam() 
{ 
. 
. 
. 
}

Điểm thứ hai cần nhớ là C++ không ủng hộ việc trả về địa chỉ của biến cục bộ tới bên ngoài hàm, vì thế bạn sẽ phải định nghĩa biến cục bộ như là biến Static.

Bây giờ, giả sử hàm sau sẽ tạo 10 số ngẫu nhiên và trả chúng về bởi sử dụng một mảng và gọi hàm này như sau:

#include <iostream> 
#include <ctime> 
#include <stdlib.h> /* thu vien cho ham srand, rand */ using namespace std; 
// phan dinh nghia cua ham de tao va tra ve cac so ngau nhien. 
int * soNgauNhien( ) 
{ 
   static int r[10]; 
   srand( (unsigned)time( NULL )); 
   for (int i = 0; i < 10; ++i) 
   { 
     r[i] = rand(); 
     cout << r[i] << endl; 
   } 
   return r; 
} 
// ham main de goi phan dinh nghia ham tren. 
int main () 
{ 
   // mot con tro tro toi mot so nguyen. 
   int *p; 
   p = soNgauNhien(); 
   for (int i = 0; i < 10; i++) 
   { 
      cout << "Gia tri cua *(p + " << i << ") la: "; 
      cout << *(p + i) << endl; 
   } 
return 0; 
}

Chạy chương trình C++ trên sẽ cho kết quả như hình sau:

Trả về mảng từ hàm trong C++

Thứ Sáu, 03/03/2023 15:00
4,324 👨 253.463
1 Bình luận
Sắp xếp theo
  • Phú Quách
    Phú Quách Tìm các phần tử dương tại tam giác phía dưới đường chéo chính
    Thích Phản hồi 25/03/22
    ❖ Lập trình C++