CHƯƠNG 5: KIỂU CON TRỎ VÀ KIỂU CẤU TRÚC Giới thiệu các kiến thức về kiểu Con trỏ và kiểu Cấu trúc: khái niệm, cách định nghĩa, khai báo biến con trỏ, biến cấu trúc, cách truy xuất dữ l
Trang 1CHƯƠNG 5: KIỂU CON TRỎ VÀ KIỂU
CẤU TRÚC
Giới thiệu các kiến thức về kiểu Con trỏ và kiểu Cấu
trúc: khái niệm, cách định nghĩa, khai báo biến con trỏ, biến cấu trúc, cách truy xuất dữ liệu bằng con trỏ và
thao tác với từng thành phần của cấu trúc
Trang 2CHƯƠNG 5: KIỂU CON TRỎ VÀ KIỂU
Trang 3- Địa chỉ và phép toán &
- Khai báo biến con trỏ
- Các phép toán trên con trỏ
- Cấp phát và giải phóng bộ nhớ cho con trỏ
5.1 Kiểu Con trỏ
Trang 4- Địa chỉ Là một đại lượng dùng để định vị (xác định) vị trí
- Đối tượng muốn xác định ở đây là các biến và các phần tử (ô nhớ) chứa dữ liệu
- Để xác định được địa chỉ của một đối tượng nào đó trong C++, ta sử dụng phép toán một ngôi lấy địa chỉ là “&” theo
Trang 5Trường hợp, đối tượng là một biến, ta viết
&Tenbien \\Lấy địa chỉ của biến
Trang 7- Con trỏ là một biến chứa địa chỉ của biến khác.
- Giả sử P là con trỏ chứa địa chỉ của biến x thì ta gọi p trỏ tới x hay x được trỏ bởi p
- Thông qua con trỏ, ta có thể làm việc được với nội dung của ô nhớ mà con trỏ trỏ đến
Khai báo biến con trỏ
Trang 8- tên_biến_con_trỏ cũng được đặt theo quy tắc đặt tên
=> Khai báo con trỏ có tên tên_biến_con_trỏ trỏ tới ô nhớ
Khai báo biến con trỏ
Trang 9- Sử dụng con trỏ
Để con trỏ có tênbiếncontrỏ trỏ đến biến (ô nhớ) có
kiểudữliệu ta cần phải gán con trỏ tênbiếncontrỏ cho địa chỉ của biến(ô nhớ) cần trỏ đến:
tênbiếncontrỏ = địa chỉ của ô nhớ (biến) cần trỏ tới
Lưu ý: Không thể gán một hằng địa chỉ cụ thể cho
Trang 11+ Phép gán:
- Gán con trỏ với địa chỉ một biến
- Gán các con trỏ với nhau (phải cùng kiểu)
Các phép toán trên con trỏ
Trang 13+ Phép tăng giảm địa chỉ:
p+n: Con trỏ trỏ đến thành phần thứ n sau pp-n: Con trỏ trỏ đến thành phần thứ n trước p
Một đơn vị tăng của con trỏ bằng kích thước của biến được trỏ
Chẳng hạn, biến có kiểu nguyên thì khi con trỏ tăng hay
giảm một đơn vị tương đương với 2 bytes
Các phép toán trên con trỏ
Trang 15+ Phép toán tự tăng, giảm: p++, p , ++p, p
Trang 16- Cấp phát bộ nhớ: sử dụng toán tử new
+ Cấp phát tĩnh + Cấp phát động
Trang 17- Giải phóng bộ nhớ: sử dụng toán tử delete
Trang 18Cấp phát và giải phóng bộ nhớ cho con trỏ
Trang 19Bài 1 Viết chương trình khai báo biến con trỏ kiểu nguyên
Sau đó, nhập vào một dãy gồm 10 số nguyên Hiển thị dãy đó ra màn hình:
- Theo thứ tự nhập vào
- Theo thứ tự ngược lại
Bài 2 Sử dụng con trỏ để nhập vào một dãy gồm n số thực
Sau đó:
- Hiển thị dãy vừa nhập ra màn hình
- Hiển thị dãy vừa nhập ra màn hình sau khi đã sắp xếp
Cấp phát và giải phóng bộ nhớ cho con trỏ
Trang 20- Kiểu cấu trúc là gì?
- Làm thế nào để định nghĩa một cấu trúc?
- Cách khai báo biến cấu trúc?
- Làm thế nào để làm việc với các thành phần của cấu trúc?
5.2 Kiểu cấu trúc
Trang 21- Kiểu cấu trúc là kiểu dữ liệu bao gồm nhiều thành phần
có kiểu khác nhau, mỗi thành phần được gọi là một trường (field)
- Chẳng hạn, Sinh viên gồm nhiều trường: mã sinh viên, họ tên, ngày tháng năm sinh, giới tính, quê quán, …
Khái niệm
Trang 22- Xác định các kiểu dữ liệu đơn giản của các biến thành
phần được nhóm lại trong cấu trúc đó
- Cần chỉ ra: tên của cấu trúc và các thành phần của nó
Phân biệt thành phần này với thành phần khác thông qua
kiểu dữ liệu, tên biến và kết thúc bằng dấu chấm phẩy (;) Các thành phần của cấu trúc được đặt trong cặp dấu móc
nhọn ({}) và dùng dấu chấm phẩy (;) để kết thúc việc định nghĩa một cấu trúc
Định nghĩa cấu trúc
Trang 23Cú pháp tổng quát để định nghĩa một kiểu cấu trúc như sau:
Trang 24Ví dụ:
struct Ngaythang
{
unsigned int Ngay;
unsigned int Thang;
unsigned int Nam;
};
//struct lồng nhau
struct Sinhvien{
Trang 25Cú pháp khai báo biến kiểu cấu trúc:
struct Ngaythang
{
unsigned int Ngay;
unsigned int Thang;
unsigned int Nam;
};
Ngaythang Ngay_den, Ngay_di
//Vừa định nghĩa vừa khai báo biến
struct Ngaythang {
unsigned int Ngay;
unsigned int Thang;
unsigned int Nam;
}Ngay_den, Ngay_di;
Khai báo biến cấu trúc
Trang 27Ví dụ: struct Ngaythang
{ unsigned int Ngay, Thang, Nam;
Trang 28Ví dụ: struct Ngaythang
{ unsigned int Ngay, Thang, Nam;
Trang 29- Nếu kiểu struct được khai báo trước tất cả các hàm, nó có
hiệu lực trong toàn bộ chương trình có sử dụng nó
- Nếu nó đặt bên trong một hàm, thì chỉ có hàm đó được
dùng nó
- Thông thường kiểu cấu trúc được khai báo trong tệp tiêu
đề (.h) và được sử dụng trong chương trình bằng lệnh
#include
Phạm vi của cấu trúc
Trang 30- Nếu biến cấu trúc là thành phần trực tiếp của một cấu
trúc, ta truy cập theo cú pháp:
Tên_biến_cấu_trúc.tên_thành_phần
- Nếu biến cấu trúc là thành phần trực tiếp của một cấu trúc
mà bản thân cấu trúc này lại là thành phần của một cấu trúc khác lớn hơn, ta truy cập theo cú pháp:
Tên_biến_cấu_trúc.tên_biến_cấu_trúc.tên_thành_phần
Tên_biến_cấu_trúc.tên_biến_cấu_trúc.tên_biến_cấu_tr úc.tên_thành_phần
Truy cập thành phần của cấu trúc
Trang 31Lưu ý:
Đối với cấu trúc, ta có thể gán 2 giá trị biến cấu trúc cho
nhau Phép gán này cũng tương đương với việc gán từng
thành phần của cấu trúc
Truy cập thành phần của cấu trúc
Trang 32cout<<“Tong diem : "<<sv.Mon1+sv.Mon2+sv.Mon3<<endl;
cout<<“Tong diem : "<<hs.Mon1+hs.Mon2+hs.Mon3<<endl;
Truy cập thành phần của cấu trúc
Trang 33- Con trỏ cấu trúc là con trỏ chứa địa chỉ của một biến cấu trúc hoặc một vùng nhớ có kiểu cấu trúc nào đó.
- Cách khởi tạo một con trỏ cấu trúc:
+ Gán địa chỉ của một biến cấu trúc cho một thành phần của mảng
+ Con trỏ được khởi tạo bằng việc sử dụng toán tử
Trang 34struct Sinhvien {
char Hoten[30], Gioitinh[5];
cout<<"Nhap gioi tinh : "; cin.getline(lop[10].Gioitinh,5);
cout<<"Nhap diem : "; cin>>lop[10].Diem;
p = lop;
cout<<p[10].Hoten<<endl;
Con trỏ cấu trúc
Trang 35- Các thành phần của cấu trúc cũng giống như các biến Do
đó, việc lấy địa chỉ của các thành phần này cũng tương tự như với biến
Trang 36typedef struct Têncấutrúc tênbiếncấutrúc;
Trang 37Cách 2:
struct Têncấutrúc{
Trang 39Cách 4:
struct tênbiếncấutrúc{
các thành phần;
tênbiếncấutrúc *contrỏ;
};
5.3 Cấu trúc tự trỏ
Trang 42- Mảng cấu trúc là mảng mà kiểu phần tử của nó là kiểu
cấu trúc
Ví dụ: ta xét khai báo sau
⇒Xây dựng danh sách
struct sinhvien{
Trang 43- Con trỏ và mảng một chiều
- Con trỏ và xâu ký tự
5.5 Con trỏ và mảng
Trang 44- Con trỏ có thể trỏ đến một biến hoặc một mảng.
- Khi đó, địa chỉ của mảng chính là địa chỉ của phần tử đầu tiên của mảng a[0] a+i là địa chỉ thành phần thứ i của
mảng a
- Nếu cho con trỏ *p trỏ đến mảng a ta gán: p=a hoặc p=&a
- Khi đó, giá trị dữ liệu của của phần tử a[0] là *p=a[0],
phần tử thứ i là *(p+i)=a[i]=*(a+i)
Chú ý: ta có thể viết *(p+1), *(a+1), *(p++) nhưng không
Con trỏ và mảng một chiều
Trang 45cout<<"In cac gia tri vua nhap "<<endl;
for (i=0;i<n;i++) cout<<a[i]; cout<<endl;
for (p=a;p<a+n;p++) cout<<*p; cout<<endl;
for (p=a,i=0;i<n;i++) cout<<*(p+i); cout<<endl;
for (i=0;i<n;i++) cout<<*(a+i); cout<<endl;
Con trỏ và mảng một chiều
Trang 46Một con trỏ ký tự có thể xem như một xâu ký tự, trong đó xâu chính là tất cả các ký tự kể từ byte con trỏ đầu tiên đến byte “\0” gặp đầu tiên Vì vậy, có thể khai báo các xâu dưới dạng con trỏ ký tự như sau:
char *st;
char *st1=“Hello”;
Con trỏ và xâu ký tự
Trang 47Các hàm trên xâu vẫn được áp dụng như khai báo nó dưới dạng mảng ký tự Tuy nhiên, ta có thể gán trực tiếp 2 xâu dưới dạng con trỏ.
Ví dụ: char *st;
char *s=“Hello”;
st = s;
Con trỏ và xâu ký tự
Trang 48Khi khai báo xâu dạng con trỏ, thì nó vẫn chưa cấp phát bộ nhớ cụ thể Do đó, ta phải sử dụng toán tử new để xin cấp phát bộ nhớ cho xâu với độ dài cần thiết.
Ví dụ 1: char *st, *s = new char[30];
Trang 49 Khái niệm chung
- Mảng con trỏ là mảng mà các phần tử của nó là các con
trỏ có cùng kiểu
- Do phần tử của mảng con trỏ là một con trỏ trỏ đến một mảng nào đó -> cho phép quản lý nhiều mảng dữ liệu cùng kiểu
5.6 Mảng con trỏ
Trang 50 Khai báo mảng con trỏ
Trang 52BÀI TẬP THỰC HÀNH
1 Cho p, q là các con trỏ trỏ đến ký tự c Gán *p = *q + 1 Khi
đó, có thể khẳng định *q = *p – 1?
2 Cho p, q là 2 con trỏ trỏ đến biến nguyên x = 10 Gán *p = *q +
5 Lúc này, giá trị của *p và *q là bao nhiêu?
3 Cho p, q, r, s là các con trỏ trỏ đến biến nguyên x = 5 Gán *q =
*p + 1; *r = *q + 1; *s = *r + 1 *q = *s – 2 Hỏi giá trị của
biến x là bao nhiêu?
4 Không dùng mảng, hãy nhập vào một dãy số nguyên sau đó
xuất dãy ra màn hình theo thứ tự ngược lại.
5 Không dùng mảng, hãy nhập vào một dãy số nguyên sau đó in
ra màn hình dãy đã được sắp xếp dãy theo chiều tăng (hoặc
giảm) dần?
Trang 53BÀI TẬP THỰC HÀNH
6 Dùng con trỏ, nhập giá trị vào cho một dãy các số thực Sau đó, tìm và xuất ra màn hình phần tử lớn nhất và bé nhất có trong dãy.
7 Sử dụng con trỏ, nhập vào một dãy ký tự Sau đó, tìm và thay thế các ký tự ‘a’ bằng ký tự ‘b’ Hiển thị ra màn hình dãy ký tự trước và sau khi thay thế.
8 Xây dựng hàm nhập, xuất, sắp xếp mảng bất kỳ bằng cách sử dụng biến con trỏ làm tham số hình thức của hàm Sử dụng các hàm trên để viết chương trình nhập các giá trị vào cho mảng
sau đó xuất ra màn hình các giá trị của mảng trước và sau khi sắp xếp
9 Sử dụng con trỏ để xây dựng hàm tính tổng 2 mảng Sau đó,
xuất ra màn hình kết quả tính được.
Trang 54BÀI TẬP THỰC HÀNH
10 Sử dụng con trỏ, nhập vào một xâu ký tự Sau đó, đếm và xuất
ra màn hình tần suất xuất hiện các ký tự trong xâu.
11 Sử dụng con trỏ, nhập vào một xâu ký tự Sau đó, đếm và xuất
ra màn hình các từ có trong xâu.
12 Tính số ngày đã qua kể từ đầu năm cho đến ngày hiện tại
Quy ước ngày được khai báo dưới dạng cấu trúc.
13 Nhập một ngày tháng năm dưới dang cấu trúc Tính chính xác (kể cả năm nhuận) số ngày đã qua bắt đầu từ ngày 1/ 1/ 1 đến ngày vừa nhập
14 Khai báo ngày tháng năm theo kiểu cấu trúc Viết chương
trình tính khoảng cách (số ngày) giữa 2 tháng bất kỳ
Trang 55BÀI TẬP THỰC HÀNH
15 Viết chương trình nhập vào một ngày tháng năm bất kỳ Xuất
ra màn hình ngày đó là thứ mấy nếu ta xem ngày 1/ 1/ 1 là thứ 2.
16 Viết chương trình nhập vào 2 ngày nào đó của tháng bất kỳ của năm bất kỳ Tính và hiển thị ra màn hình khoảng cách giữa
2 ngày đó là bao nhiêu ngày.
17 Cho số phức dưới dạng cấu trúc gồm có 2 phần là phần thực
và phần ảo Viết chương trình nhập vào 2 số phức bất kỳ Tính
và xuất ra màn hình kết quả tổng, hiệu, tích, thương của chúng
18 Cho phân số dưới dạng cấu trúc gồm 2 phần là tử số và mẫu
số Viết chương trình nhập vào 2 phân số Tính và hiển thị ra màn hình tổng, hiệu, tích, thương của chúng sau khi đã rút gọn.
Trang 56BÀI TẬP THỰC HÀNH
19 Viết chương trình nhập vào một mảng sinh viên, thông tin về mỗi sinh viên gồm: Hoten, tuoi, quequan Sắp xếp mảng vừa nhập theo chiều tăng dần của chuỗi Sau đó, xuất ra màn hình mảng sau khi đã sắp xếp.
20 Cho hình chữ nhật dưới dạng cấu trúc gồm chiều dài và chiều rộng Nhập vào một mảng các hình chữ nhật Tính và xuất ra màn hình chu vi, diện tích tương ứng của mỗi hình.
21 Tạo danh sách gồm 10 số nguyên dương Sau đó sắp xếp danh sách theo thứ tự tăng dần.
22 Tạo danh sách LIFO gồm 100 số nguyên tố đầu tiên
23 Tạo danh sách FIFO gồm n sinh viên, mỗi sinh viên được
quản lý bởi: họ tên, tuổi, điểm trung bình Sau đó sắp xếp danh