Tải bản đầy đủ (.doc) (12 trang)

Bài thực hành số 9: Con trỏ pdf

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (193.97 KB, 12 trang )

Bà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.
Lư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
a = 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
2. 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
C. 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()
{
int 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 ý:
Hà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>
using namespace 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;
cout<<"\nNhap n = ";
cin>>n;
a = new int[n*n];
b = new int[n*n];
c = new int[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)
{
int 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)
Nguyê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
size_t strlen(const char *s);

Trả về chiều dài xâu s string.h
char *_strrev( char *s );
Đảo ngược xâu s (s đã bị
đảo ngược)
string.h
double atof( const char *str );
Chuyển xâu ký số thành số
thực
stdlib.h
int atoi( const char *str );
Chuyển xâu ký số thành số
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);
cout<<"\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:
1. 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 đó :
• , h
i
là số âm nhỏ nhất của hàng i ; i ∈ .
• ,v
j
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
hS
1
1,0 −n

=
=
n
j
j
vT
1
1,0 −n

×