You are on page 1of 27

CON TRỎ

Phần 5 – Mảng động (tiếp theo)

[2017 – 04 – 15]

Biên soạn bởi: Nguyễn Trung Thành


https://www.facebook.com/abcxyztcit

Học từ cái đáy của thế giới đi lên là cách duy


“ nhất bạn trở thành master. ”
Nguyễn Trung Thành
Mục lục
A. Giới thiệu ................................................................................................... 1
1. Điều kiện để học được tài liệu này .......................................................... 1
2. Dẫn nhập ............................................................................................... 1
B. Nhập mảng động 1 chiều ............................................................................ 3
C. Cái hay của việc sử dụng mảng động ......................................................... 12
1. Kích thước của mảng phù hợp với nhu cầu người dùng ......................... 12
2. Hàm trả về 1 mảng............................................................................... 12
3. Mảng có thể co giãn, thay đổi số lượng phần tử.................................... 13
D. Vấn đề mở rộng........................................................................................ 16
1. Tham chiếu .......................................................................................... 16
2. Tham chiếu của ngôn ngữ C++ .............................................................. 17
E. Bài tập ..................................................................................................... 22
F. Lời kết ...................................................................................................... 25
1
Giới thiệu

A. Giới thiệu
1. Điều kiện để học được tài liệu này
 Có kiến thức nền tảng vững chắc với ngôn ngữ C (hoặc C++).
 Đã học xong 4 bài giảng trước đó (con trỏ phần 1  phần 4).

2. Dẫn nhập
Ở bài giảng về con trỏ phần 2 (bộ nhớ RAM), bạn đã được giới thiệu sơ lược về “con trỏ trỏ
đến con trỏ”.

Giả sử ta có int n và int *p = &n.

byte byte … byte byte byte byte byte byte byte byte byte byte
0 1 400 401 402 403 404 405 406 407 408 409
n p = 400

Nhìn vào hình trên, ta thấy địa chỉ của n là 400.

Vấn đề là, con trỏ cũng là 1 biến nên nó cũng có địa chỉ, ta nhận thấy p có địa chỉ là 406.

Điều này có nghĩa là…

Liệu có thể nào có 1 con trỏ q khác và nó lưu giá trị = 406. Woowwwww !!!

Con trỏ q trỏ đến con trỏ p, và con trỏ p trỏ đến n.

byte byte … byte … … byte … … byte … …


0 1 400 406 nào đó
n p = 400 q = 406

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


2
Giới thiệu
byte byte … byte … … byte … … byte … …
0 1 400 406 nào đó
n p = 400 q = 406

Lưu ý:

p lưu giá trị 400, và địa chỉ của p là 406.

q lưu giá trị 406 và địa chỉ của q là 1 giá trị nào đó =)).

Và biết đâu, có 1 con trỏ r khác đang lưu địa chỉ của q. Có nghĩa là…

r trỏ đến q, q trỏ đến p, p trỏ đến n.

Ta nói rằng:

 n là 1 biến số nguyên int bình thường.


 p là con trỏ cấp 1 có kiểu int* (con trỏ cấp 1).
 q là con trỏ cấp 2 có kiểu int** (con trỏ cấp 2).
 r là con trỏ cấp 3 có kiểu int*** (con trỏ cấp 3).

q và r ta gọi là con trỏ đa cấp (từ cấp 2 trở lên).

Trong bài học này, chúng ta sẽ vận dụng con trỏ đa cấp để tạo ra mảng động. Đồng thời chúng
ta sẽ khảo sát những tính chất hay ho của mảng động.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


3
Nhập mảng động 1 chiều
B. Nhập mảng động 1 chiều
Lấy lại hình minh họa:

byte byte … byte … … byte … … byte … …


0 1 400 406 nào đó
n p = 400 q = 406

điều khiển

int n;
int *p = &n;
int **q = &p;

Ta có

 p lưu địa chỉ của n nên p có thể điều khiển được n (hiển nhiên).
 Tương tự, q lưu địa chỉ của p nên q có thể điều khiển được p.

Vậy giả sử ta có lệnh…

*q = 401.

Điều gì xảy ra ? Giá trị của con trỏ p đã bị thay đổi thành 401.

byte byte … byte byte … byte … … byte … …


0 1 400 401 406 nào đó
n p = 401 q = 406

điều khiển

Rất đơn giản đúng không, con trỏ đa cấp bản chất cũng là con trỏ mà thôi.

 Con trỏ cấp 1 có kiểu int* sẽ điều khiển được số nguyên int.
 Con trỏ cấp 2 có kiểu int** sẽ điều khiển được con trỏ cấp 1 có kiểu int*.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


4
Nhập mảng động 1 chiều
Cũng nhờ ứng dụng của con trỏ mà ta có thể thay đổi được giá trị của biến.

Cho đoạn code sau:

void test(int n)
{
n = 7;
}

int main()
{
int n = 0;

test(n);

// in ra giá trị của n

return 0;
}

Chạy chương trình, bạn đoán xem sẽ in ra màn hình số 0 hay số 7 ? Chắc chắn là in ra số 0 rồi.
Học lập trình cơ bản là phải biết.

n ở hàm test không liên quan gì đến n của hàm main.

HÀM TEST HÀM MAIN

byte byte byte byte byte byte byte byte


400 401 402 403 500 501 502 503
n=7 n=0

Vậy nếu muốn n ở hàm test liên quan đến n của hàm main thì sao ? Muốn in ra n = 7 thì sao ?

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


5
Nhập mảng động 1 chiều
Vậy nếu muốn n ở hàm test liên quan đến n của hàm main thì sao ?

#include <stdio.h>

void test(int *pn)


{
*pn = 7;
}

int main()
{
int n = 0;

test(&n);
// in ra giá trị của n

return 0;
}

Lúc này khi in ra giá trị của n thì chắc chắn sẽ in ra số 7.

Vì sao vậy ?

Ở hàm main, ta truyền địa chỉ của biến n vào hàm test.

Trong hàm test, ta có con trỏ pn lưu địa chỉ của n.

 pn có khả năng điều khiển được biến n, có thể thay đổi được giá trị n của hàm main.

HÀM TEST HÀM MAIN

byte byte byte byte byte byte byte byte


400 401 402 403 500 501 502 503
pn = 500 n=0

điều khiển

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


6
Nhập mảng động 1 chiều
Nhờ vào ứng dụng của con trỏ mà ta có thể nhập vào trọn vẹn với hàm nhập mảng bình
thường như sau:

void NhapMang(int *a, int *pn) int main()


{ {
/* int a[20];
nhập n int n = 0;

for (i = 0; i < n; i++) NhapMang(a, &n);


nhập a[i]
*/ return 0;
} }

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


7
Nhập mảng động 1 chiều
Tương tự, bạn hãy đoán xem chương trình sau bị sai ở chỗ nào:

C C++
#include <stdio.h> #include <iostream>
#include <stdlib.h> // malloc, free using namespace std;

void test(int *a) void test(int *a)


{ {
a = (int*)malloc(20 * sizeof(int)); a = new int[20];
} }

int main() int main()


{ {
int *a = NULL; int *a = NULL;

test(a); test(a);

a[0] = 9; a[0] = 9;

return 0; return 0;
} }

HÀM TEST HÀM MAIN

byte byte byte byte byte byte byte byte


400 401 402 403 500 501 502 503
a = byte nào đó a = NULL

byte … … …
nào đó
Bộ nhớ được cấp phát động

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


8
Nhập mảng động 1 chiều
Kết thúc hàm test, chuyện gì xảy ra ?

HÀM TEST HÀM MAIN

byte byte byte byte byte byte byte byte


400 401 402 403 500 501 502 503
a = byte nào đó a = NULL

byte … … …
nào đó
Bộ nhớ được cấp phát động

Hàm test được giải phóng bộ nhớ hoàn toàn NHƯNG vùng nhớ được cấp phát động vẫn còn
đó.

Đồng thời, a ở hàm main vẫn là NULL  lệnh gán a[0] = 9 là sai hoàn toàn .

Kết thúc chương trình, hàm main được giải phóng bộ nhớ NHƯNG vùng nhớ được cấp phát
động vẫn còn đó  hiện tượng memory leaks.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


9
Nhập mảng động 1 chiều
Vậy, để khắc phục thì ta làm thế nào ?

C C++
#include <stdio.h> #include <iostream>
#include <stdlib.h> // malloc, free using namespace std;

void test(int **pa) void test(int **pa)


{ {
*pa = (int*)malloc(20 * sizeof(int)); *pa = new int[20];
} }

int main() int main()


{ {
int *a = NULL; int *a = NULL;

test(&a); test(&a);

a[0] = 9; a[0] = 9;

free(a); delete[] a;
a = NULL; a = NULL;

return 0; return 0;
} }

HÀM TEST HÀM MAIN

byte byte byte byte byte byte byte byte


400 401 402 403 500 501 502 503
pa = 500 a = 300

điều khiển

byte … … …
300
Bộ nhớ được cấp phát động

Điều mà ta mong muốn là thay đổi con trỏ a ở hàm main, như vậy ở hàm test ta truyền vào địa
chỉ của a để điều khiển nó, bạn hãy suy nghĩ thật đơn giản nhé.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


10
Nhập mảng động 1 chiều
Ứng dụng tất cả những gì đã học, ta sẽ viết hàm “Nhập mảng động 1 chiều” 

C C++
#include <stdio.h> #include <iostream>
#include <stdlib.h> // malloc, free using namespace std;

void NhapMang(int **pa, int *pn) void NhapMang(int **pa, int *pn)
{ {
int i;
printf("Nhap so luong phan tu = "); cout << "Nhap so luong phan tu = ";
scanf("%d", pn); cin >> *pn;

*pa = (int*)malloc((*pn) * sizeof(int)); *pa = new int[*pn];

for (i = 0; i < (*pn); i++) for (int i = 0; i < (*pn); i++)


{ {
scanf("%d", &(*pa)[i]); cin >> (*pa)[i];
} }
} }

int main() int main()


{ {
int *a = NULL; int *a = NULL;
int n = 0; int n = 0;

NhapMang(&a, &n); NhapMang(&a, &n);

// GIẢI PHÓNG BỘ NHỚ // GIẢI PHÓNG BỘ NHỚ


free(a); delete[] a;
a = NULL; a = NULL;

return 0; return 0;
} }

OK, mọi thứ thật là đơn giản đúng không nào ?

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


11
Nhập mảng động 1 chiều
Nhìn chung để cấp phát mảng động 1 chiều thì ta cần dùng con trỏ cấp 2. Vậy có cách nào để
né đi con trỏ cấp 2 hay không ? Chắc chắn là có .

Hãy xem đây:

C C++
#include <stdio.h> #include <iostream>
#include <stdlib.h> // malloc, free using namespace std;

int* NhapMang(int *pn) int* NhapMang(int *pn)


{ {
int *a = NULL; int *a = NULL;
int i;
printf("Nhap so luong phan tu = "); cout << "Nhap so luong phan tu = " ;
scanf("%d", pn); cin >> *pn;

a = (int*)malloc((*pn) * sizeof(int)); a = new int[*pn];

for (i = 0; i < (*pn); i++) for (int i = 0; i < (*pn); i++)


{ {
scanf("%d", &a[i]); cin >> a[i];
} }

return a; return a;
} }

int main() int main()


{ {
int *a = NULL; int *a = NULL;
int n = 0; int n = 0;

a = NhapMang(&n); a = NhapMang(&n);

// GIẢI PHÓNG BỘ NHỚ // GIẢI PHÓNG BỘ NHỚ


free(a); delete[] a;
a = NULL; a = NULL;

return 0; return 0;
} }

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


12
Cái hay của việc sử dụng mảng động
C. Cái hay của việc sử dụng mảng động
1. Kích thước của mảng phù hợp với nhu cầu người dùng

Cái này chắc bạn biết rõ rồi đúng không.

2. Hàm trả về 1 mảng


Khi học lập trình cơ bản, bạn viết 1 hàm và bạn mong muốn hàm đó trả về 1 số nguyên, 1 số
thực, 1 phân số…

Vấn đề là khi bạn muốn trả về 1 mảng bình thường, liệu có được hay không ?
int* NhapMang(int *pn) Với những gì mà bạn học được từ bài giảng trước đó,
{
int a[20]; bạn nhìn vào đoạn code trên xem có gì sai không ?
 Bộ nhớ của hàm NhapMang bao gồm con trỏ
// nhập vào n
pn và 20 số nguyên của mảng a.
for (i = 0; i < (*pn); i++)  Khi kết thúc hàm NhapMang, toàn bộ 20 số
{
// nhập a[i] nguyên của mảng a sẽ “bay theo mây khói”.
} Hàm NhapMang trả về địa chỉ của vùng nhớ đã
return a; bị giải phóng  rất nguy hiểm  sai.
}

int main()
{
int *a = NULL;
int n = 0;

a = NhapMang(&n);

return 0;
}

Bạn có thể khắc phục bằng cách tạo ra 1 struct và struct này lưu toàn bộ mảng, tuy nhiên đây
chỉ là xoay sở tạm thời.

Khi bạn học về cấp phát mảng động, bạn đã giải quyết được bài toán này đúng không ? Vấn đề
là hàm main bạn cần thêm lệnh giải phóng bộ nhớ.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


13
Cái hay của việc sử dụng mảng động
3. Mảng có thể co giãn, thay đổi số lượng phần tử
Ví dụ: hiện tại mảng a có tối đa 20 phần tử (được cấp phát động bằng malloc, calloc, new,…).

Bạn muốn chèn thêm 1 phần tử nữa thì sao ?

Bài toán đặt ra: làm cho mảng a “to hơn” bằng cách thay đổi số lượng phần tử tối đa của mảng
là 21 phần tử.

Trong ngôn ngữ C

Bạn sử dụng hàm realloc (trong thư viện stdlib.h) để cấp phát bộ nhớ lại.

Để giải quyết vấn đề trên, rất đơn giản, ta code như sau:

a = realloc(a, 21 * sizeof(int));

Hàm realloc có dạng như sau:


void* realloc(void* ptr, size_t size)

Hàm nhận vào con trỏ ptr (địa chỉ mà đã được cấp phát bộ nhớ từ trước).
Hàm nhận vào số lượng byte cần cấp phát (size).

Hàm trả về địa chỉ, nơi mà được cấp phát động vừa đủ size phần tử.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


14
Cái hay của việc sử dụng mảng động
Hàm realloc sẽ tìm đến địa chỉ đã cấp phát được trỏ bởi ptr. Sau đó hàm yêu cầu hệ điều hành
cấp phát đủ size bộ nhớ rồi copy dữ liệu từ vùng nhớ cũ (ptr) sang vùng nhớ mới, sau đó hàm
giải phóng vùng nhớ cũ (ptr). Cuối cùng hàm trả về địa chỉ của vùng nhớ mới.

C
#include <stdlib.h> // malloc, free, realloc

int main()
{
int *a = NULL;
int n = 20;

a = (int*)malloc(n * sizeof(int));

// SỬ DỤNG MẢNG a

// TĂNG ĐỘ DÀI TỐI ĐA LÊN 1 PHẦN TỬ


n = n + 1;
a = (int*)realloc(a, n);

// GIẢI PHÓNG BỘ NHỚ


free(a);
a = NULL;

return 0;
}

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


15
Cái hay của việc sử dụng mảng động
Trong ngôn ngữ C++
C++ có những cơ chế về hướng đối tượng và các đối tượng quản lý vùng nhớ riêng nên không
thể realloc theo các bình thường được.

Vì vậy, cách làm bình thường của chúng ta là… làm thủ công: giải phóng vùng nhớ cũ và cấp
phát lại vùng nhớ.

C++
#include <iostream>
using namespace std;

int main()
{
int *a = NULL;
int n = 20;

a = new int[n];

// SỬ DỤNG MẢNG a

// TĂNG ĐỘ DÀI TỐI ĐA LÊN 1 PHẦN TỬ


int *b = a;

a = new int[n + 1];


for (int i = 0; i < n; i++)
a[i] = b[i];

delete[] b;
b = NULL;

n = n + 1;

// GIẢI PHÓNG BỘ NHỚ


delete[] a;
a = NULL;

return 0;
}

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


16
Vấn đề mở rộng
D. Vấn đề mở rộng
1. Tham chiếu
Tham chiếu là một khái niệm trừu tượng trong lập trình.

Nó là 1 cách diễn đạt “đối tượng đang sử dụng gắn liền với vùng nhớ nào”.

Ví dụ:

Khai báo biến x;


Khai báo con trỏ p và cho p lưu địa chỉ của x;

Giả sử x nằm tại địa chỉ 700 trong bộ nhớ. Ta nói rằng:

Vùng nhớ tại địa chỉ 700 có 2 cái tên.

 Cái tên thứ 1 đó là “x”.


 Cái tên thứ 2 đó là “*p”.

Hoặc nói gần nghĩa hơn:

Vùng nhớ tại địa chỉ 700 có 2 tham chiếu

 Tham chiếu đầu tiên là biến x.


 Tham chiếu thứ 2 đó là “*p”.

Ta cũng có thể nói rằng “con trỏ p đang trỏ đến x” hoặc “con trỏ p đang tham chiếu đến x”.

Tham chiếu là 1 khái niệm rất trừu tượng, bạn đừng mong muốn hiểu rõ nó. Bạn chỉ cần trải
nghiệm đủ nhiều là dần dần bạn tự hiểu.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


17
Vấn đề mở rộng
2. Tham chiếu của ngôn ngữ C++
Ngôn ngữ C không có tham chiếu, nhưng C++ thì có.

Bạn chạy thử đoạn code sau:

C++
1 #include <iostream>
2 using namespace std;
3
4 int main()
5 {
6 int x = 5;
7 int &r = x;
8
9 r = 21;
10
11 cout << x << endl;
12
13 return 0;
14 }

Kết quả chạy:

21

Vì sao lại như vậy ? Vì r là 1 tên gọi khác của x.

Ta nói rằng: r là tham chiếu đến x.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


18
Vấn đề mở rộng
Giải thích từng bước chạy:

C++
1 #include <iostream>
2 using namespace std;
3
4 int main()
5 {
6 int x = 5;
7 int &r = x;
8
9 r = 21;
10
11 cout << x << endl;
12
13 return 0;
14 }

Ở dòng code số 6: ta khai báo biến x và khởi tạo x = 5.

byte byte byte byte byte byte …


500 501 502 503 504 505
5

Vùng nhớ từ byte 500 đến byte 503 được đặt tên là “x”.

Ở dòng code số 7: khai báo r là tham chiếu đến x. Như vậy vùng nhớ từ byte 500 đến byte 503
có thêm 1 cái tên mới, đó chính là “r”.

x, r

byte byte byte byte byte byte …


500 501 502 503 504 505
5
Vùng nhớ từ byte 500 đến byte 503 có 2 cái tên: x và r.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


19
Vấn đề mở rộng

Giải thích từng bước chạy:

C++
1 #include <iostream>
2 using namespace std;
3
4 int main()
5 {
6 int x = 5;
7 int &r = x;
8
9 r = 21;
10
11 cout << x << endl;
12
13 return 0;
14 }

Ở dòng code số 9: ta gán r = 21.

x, r

byte byte byte byte byte byte …


500 501 502 503 504 505
21

Điều này hoàn toàn tương tự như gán x = 21, bởi vì x và r đều là sự “trừu tượng hóa” của vùng
nhớ từ byte 500 đến byte 503.

Tham chiếu của C++ là vậy đấy.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


20
Vấn đề mở rộng
Tham chiếu của C++ được ứng dụng rất nhiều, nó có thể thay thế con trỏ, bởi vì con trỏ ta phải
tốn công lấy *, còn tham chiếu thì không cần, có vẻ tự nhiên và đơn giản hơn.

Ví dụ sau đây minh họa ứng dụng của tham chiếu trong C++:
#include <iostream>
using namespace std;

void test(int k)
{
k = 3;
}

int main()
{
int x = 0;
test(x);

// in ra số 0
cout << x << endl;

return 0;
}

Chắc chắn in ra màn hình số 0, vì x ở hàm main không liên quan gì k ở hàm test.

Nhưng nếu ta sửa lại như sau:


#include <iostream>
using namespace std;

void test(int &k)


{
k = 3;
}

int main()
{
int x = 0;
test(x);

// in ra số 3
cout << x << endl;

return 0;
}

Ta nói rằng: k ở hàm test là một tên gọi khác của x ở hàm main. k là tham chiếu đến x.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


21
Vấn đề mở rộng
Nhờ tính chất trên mà ta có thể viết hàm cấp phát bộ nhớ động bằng C++ như sau:

C++
#include <iostream>
using namespace std;

void NhapMang(int *&a, int &n)


{
cout << "Nhap so luong phan tu: ";
cin >> n;

a = new int[n];

for (int i = 0; i < n; i++)


{
cin >> a[i];
}
}

int main()
{
int *a = NULL;
int n = 0;

NhapMang(a, n);

delete[] a;
a = NULL;

return 0;
}

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


22
Bài tập
E. Bài tập
Tất cả đều sử dụng mảng động, ở mỗi bài làm bạn phải có ít nhất 2 hàm: hàm nhập mảng và
hàm xuất mảng.

Bài 1. Nhập vào mảng, xuất mảng, tính tổng các phần tử của mảng.

Bài 2. Đảo ngược nội dung của mảng.

Ví dụ mảng a = {9 8 7 6}  a = {6 7 8 9}

Bài 3. Đếm số lượng số nguyên tố trong mảng.

Ví dụ mảng a = {9, 0, 5, -1, 7}  có 2 số nguyên tố.

Bài 4. Nhập, xuất mảng a. Tạo ra mảng b (được cấp phát động) chứa các phần tử là số lẻ trong
mảng a. Xuất ra mảng b.

Chương trình phải chia mã nguồn thành 3 file: file main, header BaiLam + code BaiLam.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


23
Bài tập
Bài 5. Ghép mảng.

Nhập vào 2 mảng a và b, tạo ra mảng c bằng cách ghép mảng a và mảng b. Mảng c chứa vừa
đủ số lượng phần tử.

Ví dụ:

a = { 9, 8, 7 } với na = 3

b = { 5, 3, 4, 6 } với nb = 4

 c = { 9, 8, 7, 5, 3, 4, 6 } với nc = 7.
Mảng c chứa tối đa 7 phần tử (vừa đủ, không dư).

Bài 6. Cắt mảng.

Nhập vào mảng a. Cắt mảng a tại vị trí vt để có được mảng b và mảng c.

Ví dụ:

a = { 9, 8, 7, 5, 3, 4, 6 }, với na = 7. Cắt tại vị trí vt = 3.

 b = { 9, 8, 7 } với nb = 3 (chứa tối đa 3 phần tử)


 c = { 5, 3, 4, 6 } với nc = 4 (chứa tối đa 4 phần tử).

Bài 7. Xóa phần tử cuối cùng của mảng. Mảng sau khi xóa phải vừa đủ số lượng phần tử.

Ví dụ: ban đầu mảng a = {9, 8, 7, 6}, với n = 4.

Sau khi xóa phần tử cuối, mảng là { 9, 8, 7} , với n = 3.


Ghi chú: sau khi xóa thì mảng a chứa tối đa 3 phần tử (vừa đủ, không dư).

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


24
Bài tập
Bài 8. Xóa đi 1 phần tử của mảng tại vị trí vt. Yêu cầu: mảng sau khi xóa phải vừa khít số lượng
phần tử.

Chương trình cho phép nhập mảng a, nhập vào vị trí cần xóa.

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit


25
Lời kết
F. Lời kết
Hi vọng tài liệu này sẽ giúp ích cho bạn. Cảm ơn bạn đã xem.

Tác giả: Nguyễn Trung Thành


Facebook: https://www.facebook.com/abcxyztcit

Con trỏ (phần 5) Nguyễn Trung Thành - https://www.facebook.com/abcxyztcit

You might also like