Mục tiêu Nắm vững định nghĩa biến con trỏ, các thao tác cơ bản trên con trỏ.. Năm vững các mảng động, xâu động cài đặt bằng con trỏ Rèn luyện cách gọi hàm, truyền tham biến.. Ôn t
Trang 1Bài thực hành số 9:
Con trỏ
A Mục tiêu
Nắm vững định nghĩa biến con trỏ, các thao tác cơ bản trên con trỏ
Năm vững các mảng động, xâu động cài đặt bằng con trỏ
Rèn luyện cách gọi hàm, truyền tham biến
B Ôn tập:
Các định nghĩa kiểu con trỏ
Các thao tác cơ bản trên con trỏ
Mảng động, xâu động cài đặt bằng con trỏ
Truyền tham số
I Biến cấu trỏ - Kiểu con trỏ:
1 Cú pháp định nghĩa biến con trỏ:
KDL *ConTro;
2 Định nghĩa kiểu con trỏ
typedef KDL *KieuConTro;
II Các phép toán trên con trỏ:
1 Phép toán con trỏ “ * “:
*px : trả về nội dung của địa chỉ mà con trỏ px tới
2 Phép gán địa chỉ cho con trỏ cùng kiểu:
giả sử:
int *px, x;
px = &x;
( khi đó có: *px == x)
3 Gán 2 con trỏ cùng kiểu
Trang 2Lưu ý: Mọi con trỏ đều có thể nhận giá trị NULL
px = NULL;
4 Cấp phát vùng nhớ cho biến con trỏ (để chứa dữ liệu)
px = new KDL;
5 Giải phóng vùng nhớ cho biến con trỏ
delete px;
III Mảng động 1chiều
(Cấp phát động cho mảng 1 chiều thông qua con trỏ)
Dùng con trỏ để cài đặt mảng 1 chiều
1 Khai báo :
KDL *a;
2 Cấp phát vung nhớ :
//Cấp phát cho mảng động a chứa đủ MAX phần tử kiểu KDL
a = new KDL[MAX];
3 Thu hồi vùng nhớ :
delete []a;
4 Truy cập đến phần tử (địa chỉ, giá trị) trong mảng:
IV Mảng động 2 chiều (Ma trận)
(Cấp phát động cho mảng 2 chiều thông qua con trỏ)
1 Khai báo :
KDL *a;
2 Cấp phát vùng nhớ để lưu trử dữ liệu :
Giá trị : a[i] *(a+i) Địa chỉ : &a[i] a + i
Trang 3a = new KDL[KT1*KT2];
// (a = new int[m*n];)
3 Thu hồi vùng nhớ
delete [ ]a;
4 Duyệt các phần tử của mảng :
Để duyệt các phần tử của mảng, theo cách đã biết là dựa vào chỉ số của các phần
tử của mảng( a[i][j]), ngoài ra có thể sử dụng con trỏ theo cách sau:
a + i*n + j trỏ tới phần tử a[i][j] ( mảng m hàng, n cột)
V Xâu ký tự động
1 Khai báo :
char *a;
//wchar *a; TCHAR *a;
2 Khởi tạo :
*a = NULL;
2 Cấp phát vùng nhớ:
a = new char[MAX];
3 Thu hồi vùng nhớ:
delete [ ]a;
4 Truy cập đến phần tử (địa chỉ, giá trị) trong xâu:
VI Con trỏ cấu trúc:
Xét kiểu cấu trúc: KCT
1 Khai báo :
KCT *p;
Giá trị : a[i] *(a+i) Địa chỉ : &a[i] a + i
Trang 42 Cấp phát vùng nhớ:
p = new KCT
3 Thu hồi vùng nhớ:
delete [ ]p;
4 Truy cập đến các trường dữ liệu của cấu trúc:
Theo cú pháp:
Chẳng hạn với kiểu cấu trúc NHANVIEN (Lab8):
p -> MaNV
p -> Sdt
VII Mảng động cấu trúc
Xét kiểu cấu trúc KCT
1 Khai báo :
KCT *a;
2 Cấp phát vùng nhớ:
a = new KCT[MAX];
3 Thu hồi vùng nhớ:
delete [ ]a;
VIII Truyền tham số
1 Một số điểm lưu ý:
• Muốn hàm trả về một giá trị (Mảng, xâu) thì trả về một con trỏ
• Muốn tham số thực giữu lại thay đổi khi chương trình ra khỏi hàm thì phải dùng các truyền bằng biến (tức là đối phải dùng con trỏ hoặc tham chiếu) 2.Truyền tham số:
p -> Ten_Thanh_Phan
Trang 5C Luyện tập:
Ví dụ 1:
Cho mảng a[0 n-1] có n số nguyên, x là số nguyên Viết chương trình thực hiện chức năng sau:
Chen(a,n,x,k) ≡ chèn x vào a tại vị trí thứ k, kết quả trả về a
(đếm k từ 0 )
Thực hiện:
Bước 1: Tạo Project với tên “Lab9_Vd1”
Bước 2: Tạo tập tin chương trình vd1.cpp
Bước 3: Trong tập tin vd1.cpp, soạn code theo cấu trúc:
#include <iostream>
#define MAX 1000
using namespace std;
void Nhap(int *a, int n);
void Xuat(int *a, int n);
void Chen(int *a, int &n, int x, int k);
void main()
{
Trang 6int a[MAX], n, x, k;
cout<<"\nNhap n = ";
cin>>n;
Nhap(a,n);
Xuat(a,n);
cout<<"\nNhap gia tri can chen x = ";
cin>>x;
do
{
cout<<"\nNhap vi tri can chen (0 <= K <= "<<n<<" )k = "; cin>>k;
if(0 <= k && k <= n)
break; }
while(1);
Chen(a, n,x,k);
Xuat(a,n);
}
//Cac ham nhap xuat
void Nhap(int *a, int n)
{
for (int i = 0; i < n; i++)
{
cout<<"\na["<<i<<"] = ";
cin>>*(a+i);
}
}
void Xuat(int *a, int n)
{
int i;
cout<<"\n";
for (i = 0; i < n; i++)
cout<<*(a+i)<<'\t';
}
void Chen(int *a, int &n, int x, int k)
{
int i;
for(i = n-1; i >= k; i )
*(a+i+1) = *(a+i);
*(a+k) = x;
n = n+1;
}
Lưu ý:
Trang 7Hàm main() có thể viết cách khác như sau:
void main()
{
int *a, //Dùng con trỏ
n, x, k;
cout<<"\nNhap n = ";
cin>>n;
a = new int[n]; //cấp phát vùng nhớ đề a chứa đủ n giá trị kiểu int Nhap(a,n);
Xuat(a,n);
cout<<"\nNhap gia tri can chen x = ";
cin>>x;
do
{
cout<<"\nNhap vi tri can chen (0 <= K <= "<<n<<" )k = "; cin>>k;
if(0 <= k && k <= n)
break; }
while(1);
Chen(a, n,x,k);
Xuat(a,n);
delete []a; //Thu hồi vùng nhớ đã cấp phát cho a
}
//Khi đó ta bỏ định nghĩa hằng MAX ở trước
Ví dụ 2:
Viết chương trình tính tích 2 ma trận vuông cấp n
Thực hiện:
Bước 1: Tạo Project với tên “Lab9_Vd2”
Bước 2: Tạo tập tin chương trình vd1.cpp
Bước 3: Trong tập tin vd2.cpp, soạn code theo cấu trúc sau:
#include<iostream>
usingnamespace std;
void Nhap(int *a, int n, char Kt);
void Xuat(int *a, int n, char Kt);
void Tich_MT(int *a, int *b, int *c, int n);
void main()
{
int *a, *b, *c, n;
Trang 8cout<<"\nNhap n = ";
cin>>n;
a = newint[n*n];
b = newint[n*n];
c = newint[n*n];
Nhap(a,n,'a');
Nhap(b,n,'b');
Tich_MT(a,b,c, n);
Xuat(a,n,'a');
Xuat(b,n,'b');
Xuat(c,n,'c');
cout<<'\n';
delete []a;
delete []b;
delete []c;
}
//Nhap ma tran Kt
void Nhap(int *a, int n, char Kt)
{
int i, j;
cout<<"\nNhap ma tran "<<Kt;
for (i = 0; i < n; i++)
for(j = 0; j < n; j++) {
cout<<"\n"<<Kt<<"["<<i<<"]["<<j<<"]= "; cin>>*(a+i*n+j);
} }
//Xuat ma tran Kt
void Xuat(int *a, int n, char Kt)
{
int i, j;
cout<<"\nMa tran "<<Kt<<":\n";
for (i = 0; i < n; i++)
{
cout<<'\n';
for (j = 0; j < n; j++)
cout<<*(a+i*n+j)<<'\t';
}
}
//c = ab
void Tich_MT(int *a, int *b, int *c, int n)
{
Trang 9int i,j,k;
for (i = 0; i < n; i++)
for(j = 0; j < n; j++) {
*(c+i*n+j) = 0;
for(k = 0; k < n; k++)
*(c+i*n+j) += *(a+i*n+k)* *(b+k*n+j);
} }
Lưu ý:
Hàm main() có thể viết cách khác như sau:
void main()
{
int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX];
int n;
cout<<"\nNhap n = ";
cin>>n;
Nhap( (int)a,n,’a’); //ép kiểu
Nhap((int)b,n,’b’);
Tich_MT( (int) a, (int) b, (int)c, n);
Xuat((int)a,n,’a’);
Xuat((int)b,n,’b’);
Xuat((int)c,n,’c’);
}
//Khi đó ta cần định nghĩa hằng MAX ở trước
Ví dụ 3:
Viết chương trình tổ chức menu thực hiện các thao tác trên xâu ký tự với các chức năng sau:
1 Trả về chiều dài xâu
2 Nối xâu b vào sau xâu a (Xâu kết quả gồm 2 xâu a,b)
3 So sánh 2 xâu ký tự theo thứ tự từ điển (phân biệt chữ thường và hoa)
4 So sánh 2 xâu ký tự theo thứ tự từ điển (bỏ qua chữ thường và hoa)
5 Chép xâu b sang xâu a
6 Đảo ngựoc xâu ký tự
7 Trả về số nguyên từ xâu các ký số
8 Trả về số thực từ xâu các ký tự (số, dấu chấm)
(dùng các hàm thư viện sau)
Trang 10Nguyên mẫu của hàm Chức năng Thư viện
char *strcat( char *Dest, const char *Src ); Nối xâu Src vào sau xâu
Dest, kết quả trả về xâu mới gồm 2 xâu trên
string.h
int strcmp(const char *s1, const char *s2 ); So sánh 2 chuỗi s1, s2 theo
thứ tự từ điển.
Kq =-1; s1<s2;
Kq=0; s1==s2
Kq = 1; s1 > s2
string.h
char *strcpy(char *Dest, const char *Src ); Chép Src sang dest string.h
int stricmp( const char *s1, const char *s2 ); So sánh 2 chuỗi s1, s2 (bỏ
qua chữ thường , hoa) string.h
đảo ngược)
string.h
thực
stdlib.h
nguyên
stdlib.h
Ví dụ 4:
Xem ví dụ 1, lab8:
• Viết lại hàm nhập Ds Hàm nhập Ds sẽ gọi hàm nhập một cấu trúc
//Hàm nhập dữ liệu cho cấu trúc p : dùng tham chiếu
void Nhap_CT(NHANVIEN &p)
{
cout<<"\nMa nhan vien: ";
gets(p.MaNV);
cout<<"\nHo nhan vien: ";
gets(p.HoNV);
cout<<"\nTen nhan vien: ";
gets(p.TenNV);
cout<<"\nTuoi: ";
cin>>p.Tuoi;
cout<<"\nDia chi: ";
gets(p.Dc);
Trang 11cout<<"\nSo dien thoai: ";
cin>>p.Sdt;
cout<<"\nLuong: ";
cin>>p.Luong;
cout<<"\nPhong: ";
gets(p.Phong);
}
//Hàm nhập danh sách nhân viên gọi hàm nhập một nhân viên
void Nhap ( NHANVIEN Ds[MAX], int n)
{
int i;
for( i = 0; i < n; i++)
{
cout<<"\nNhap thong tin nguoi thu "<<i+1;
Nhap_CT(Ds[i]);
}
}
• Viết lại hàm DSLuong_Tang ( NHANVIEN Ds[MAX], int n), hàm này gọi hàm
Hv, hàm Hv hoán đổi giá trị 2 cấu trúc
void Hv(NHANVIEN &p, NHANVIEN &q) //p, q dùng tham chiếu
{
NHANVIEN Tam;
Tam = p;
p = q;
q = Tam;
}
//Sap danh sach tang dan theo luong
void DSLuong_Tang ( NHANVIEN Ds[MAX], int n)
{
int i, j;
for( i = 0; i < n-1; i++)
for(j=i+1; j < n; j++)
if(Ds[i].Luong > Ds[j].Luong)
Hv(Ds[i],Ds[j]);
}
D Bài tập
Bài 1:
Trang 121 Cs_Am_Max: Tìm chỉ số (đầu tiên) của số âm lớn nhất, nếu có Nếu không, trả
về -1
2 Tong_Phan_Biet: Tổng các giá trị phân biệt
2 Sap_Am_Tang: Sắp tăng các số âm, các số khác giữ nguyên vị trí
Bài 2:
Viết một chương trình nhập vào một ma trận vuông cấp n, với n là số nguyên dương , các phần tử của ma trận là số nguyên , Xuất ra màn hình ma trận đã nhập, tính và in ra màn hình giá trị S – T , trong đó :
• , hi là số âm nhỏ nhất của hàng i ; i ∈
• ,vj Là giá trị lớn nhất của cột j ; j∈
Yêu cầu của chương trình là sử dụng các hàm :
• Nhập ma trận ,
• Xuất ma trận ,
• Tính S,
• Tính T
Bài 3:
Viết chương trình quản lý các khách hàng thuê bao điện thoại, trong đó sử dụng cấu trúc gồm
Mã khách hàng,
Họ tên,
Địa chỉ,
Số điện thoại
Yêu cầu chương trình thực hiện các chức năng sau:
• Thêm một khách hàng mới
• Xóa một khách hàng
• Tìm kiếm địa chỉ khi biết số điện thoại
∏
=
= n
i i h S
∑
=
= n
j j v T
1
1 ,
0 n−