1
TIN HỌC ĐẠI CƯƠNG
www.uit.edu.vn
BÀI 10
BÀI 10
BỘ NHỚ ĐỘNG
BỘ NHỚ ĐỘNG
KIỂU DỮ LIỆU CÓ CẤU TRÚC
KIỂU DỮ LIỆU CÓ CẤU TRÚC
Tin học đại cương
2
CẤP PHÁT VÀ GIẢI PHÓNG BỘ NHỚ ĐỘNG9
NỘI DUNG
NỘI DUNG
Tin học đại cương
3
NỘI DUNG BÀI BỘ NHỚ ĐỘNG
NỘI DUNG BÀI BỘ NHỚ ĐỘNG
Khái niệm biến “động”
Các hàm cấp phát bộ nhớ
Hàm malloc
Hàm calloc
Hàm realloc
Hàm giải phóng bộ nhớ
Hàm free
Tin học đại cương
4
BIẾN ĐỘNG
BIẾN ĐỘNG
Biến động là biến được “tạo” ra khi chạy
chương trình. Thông qua con trỏ, vùng nhớ biến
được cấp phát và quản lý.
Các hàm thao tác vùng nhớ trên C được định
nghĩa trong thư viện stdlib.h hoặc alloc.h
Các hàm cấp phát và giải phóng bộ nhớ
Hàm malloc
Hàm calloc
Hàm realloc
Hàm free
Tin học đại cương
5
HÀM MALLOC / HÀM FREE
HÀM MALLOC / HÀM FREE
Chức năng của hàm malloc là gọi cấp phát một
vùng nhớ có kích thước size:
void *malloc(size_t size);
Ví dụ:
int *p;
p=(int *) malloc(100);
p=(int *) malloc(80*sizeof(int));
Hàm free được dùng để giải phóng một vùng
nhớ đã được cấp phát thông qua con trỏ prt:
void free(void *ptr);
Tin học đại cương
6
#include <string.h>
#include <stdio.h>
#include <alloc.h>
void main(void)
{
char *str;
/* allocate memory for string */
str = (char *) malloc(10);
/* copy "Hello" to string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
}
VÍ DỤ
VÍ DỤ
Tin học đại cương
7
HÀM CALLOC VÀ REALLOC
HÀM CALLOC VÀ REALLOC
Bên cạnh hàm malloc, một vùng nhớ còn có
thể được cấp phát bằng hàm calloc và cấp
phát lại bằng hàm realloc.
Hàm calloc cấp phát một vùng nhớ có kích
thước nitems* size bytes.
void *calloc(size_t nitems, size_t
size);
Hàm realloc điều chỉnh lại vùng nhớ đã được
cấp phát block, với kích thước mới là size
bytes.
void *realloc(void* block, size_t
size);
Tin học đại cương
8
BỘ NHỚ ĐỘNG VÀ MẢNG 1 CHIỀU
BỘ NHỚ ĐỘNG VÀ MẢNG 1 CHIỀU
Cấp phát vùng nhớ n phần tử cho biến con trỏ
int *a :
a = (int *)malloc(n*sizeof(int));
a =(int *)calloc(n, sizeof(int));
Kiểm tra cấp phát thành công và thực hiện các
thao tác tiếp (như đối với mảng):
if(a!=NULL)
{
// dùng như mảng cho a[0], a[1], …
…………
free(a);
}
Tin học đại cương
9
BỘ NHỚ ĐỘNG VÀ MẢNG 2 CHIỀU
BỘ NHỚ ĐỘNG VÀ MẢNG 2 CHIỀU
a = (int **)malloc(m*sizeof(int *));
if(a!=NULL)
{ kt=0;
for(i=0; i<m; i++)
a[i]=NULL;
for(i=0; i<m; i++)
{
if(kt==1) break;
a[i]=(int *)malloc(n*sizeof(int));
if(a[i]==NULL) kt=1;
}
if(kt==0)
{
/* dùng như mảng 2 chiều a[i][j] */
………
for(i=0; i<m; i++)
if(a[i]!=NULL) free(a[i];
free(a);
}
}
Tin học đại cương
10
KIỂU DỮ LIỆU CÓ CẤU TRÚC10
NỘI DUNG
NỘI DUNG
Tin học đại cương
11
Khái niệm
Khai báo kiểu cấu trúc struct
Mảng và con trỏ cấu trúc
Truy xuất các thành phần của cấu trúc
Kiểu cấu trúc và hàm
Ví dụ minh họa
NỘI DUNG BÀI KIỂU CẤU TRÚC
NỘI DUNG BÀI KIỂU CẤU TRÚC
Tin học đại cương
12
Kiểu cấu trúc (hay bản ghi đối với một số NNLT
khác) là dạng dữ liệu thường được định nghĩa để
mô tả dữ liệu có nhiều thành phần thuộc nhiều
kiểu dữ liệu khác nhau.
Kiểu dữ liệu của từng thành phần có thể là các
kiểu dữ liệu cơ bản (ký tự, số nguyên, số thực),
con trỏ, mảng, và thậm chí là một kiểu cấu trúc.
Kiểu cấu trúc trên C được định nghĩa thông qua
từ khoá struct
KHÁI NIỆM
KHÁI NIỆM
Tin học đại cương
13
Cú pháp tổng quát:
struct [<tên cấu trúc>]
{
[<KDL> <tên biến [, tên biến, …]>];
[<KDL> <tên biến [, tên biến, …]>];
…
} [<danh sách các biến cấu trúc>];
<tên cấu trúc> và <danh sách các biến
cấu trúc> là tùy chọn nhưng ít nhất phải có
một trong 2 được khai báo.
Các biến cùng kiểu KDL có thể khai báo cách
nhau bởi dấu phẩy. Các KDL khác nhau khai báo
riêng cách nhau bởi dấu chấm phẩy.
KHAI BÁO STRUCT
KHAI BÁO STRUCT
Tin học đại cương
14
Trong C, ta có thể đặt <tên kiểu> cho một <định
nghĩa kiểu> thông qua từ khoá typedef:
typedef <định nghĩa kiểu>
<tên kiểu>;
Ví dụ:
typedef struct tagHocSinh
{
char sHoTen[50];
int nToan, nVan;
float fDTB;
} HOCSINH, *PTR_HOCSINH;
Khi đó ta có thể khai báo một biến hs như sau:
HOCSINH hs;
KHAI BÁO STRUCT
KHAI BÁO STRUCT
Tin học đại cương
15
Các thao tác trên mảng, con trỏ và vùng nhớ động
cho các biến cấu trúc hoàn toàn tương tự như đối
với các biến có kiểu dữ liệu thông thường.
Ví dụ:
HOCSINH hs, manghs[20];
PTR_HOCSINH phs1, phs2;
manghs[5] = hs;
phs1 = &hs;
phs2 = (PTR_HOCSINH)calloc(10,
sizeof(HOCSINH));
MẢNG VÀ CON TRỎ CẤU TRÚC
MẢNG VÀ CON TRỎ CẤU TRÚC
Tin học đại cương
16
Để truy xuất đến một thành phần của biến cấu
trúc tĩnh ta dùng toán tử chấm “.” và dùng toán tử
“->” đối với biến con trỏ.
Ví dụ:
HOCSINH hs;
hs.sHoTen=“Phúc Khang An”;
hs.nToan=10;
hs.nVan = 7;
hs.fDTB = (hs.nToan + hs.nVan)/ 2.0;
Không nên dùng toán tử & đối với thành phần
cấu trúc.
TRUY XUẤT THÀNH PHẦN CẤU TRÚC
TRUY XUẤT THÀNH PHẦN CẤU TRÚC
Tin học đại cương
17
Với các biến:
HOCSINH hs;
PTR_HOCSINH phs = &hs;
Ta có thể truy xuất đến thành phần sHoTen của
cấu trúc bằng các cách tương đương như:
gets(hs.sHoTen);
gets(phs->sHoTen);
gets((*phs).sHoTen);
TRUY XUẤT THÀNH PHẦN CẤU TRÚC
TRUY XUẤT THÀNH PHẦN CẤU TRÚC
Tin học đại cương
18
Áp dụng cho biến mảng cấu trúc:
HOCSINH dshs[100];
PTR_HOCSINH pdshs = dshs;
Ta có thể truy xuất đến thành phần sHoTen của
cấu trúc bằng các cách tương đương như:
gets(dshs[i].sHoTen);
gets(pdshs[i].sHoTen);
gets(*(dshs+i).sHoTen);
gets(*(pdshs+i).sHoTen);
gets(pdshs->sHoTen); pdshs++;
gets((*pdshs).sHoTen); pdshs++;
TRUY XUẤT THÀNH PHẦN CẤU TRÚC
TRUY XUẤT THÀNH PHẦN CẤU TRÚC
Tin học đại cương
19
Các thao tác trên hàm cho biến cấu trúc hoàn
toàn tương tự cho biến thông thường. Chẳng hạn
truyền tham biến và tham trị như sau:
Prototype:
void NhapHS(PTR_HOCSINH phs);
void XuatHS(HOCSINH hs);
Khi đó ta có thể gọi dùng hàm:
HOCSINH hs;
NhapHS(&hs);
XuatHS(hs);
KIỂU CẤU TRÚC VÀ HÀM
KIỂU CẤU TRÚC VÀ HÀM
Tin học đại cương
20
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagHOCSINH
{
char sHoTen[50];
float fVan, fToan;
float fDTB;
}HOCSINH, *PTR_HOCSINH;
void NhapHS(PTR_HOCSINH phs, int stt);
void XuatHS(HOCSINH hs, int stt);
VÍ DỤ MINH HỌA
VÍ DỤ MINH HỌA
Tin học đại cương
21
void main()
{
int i, nSoHS;
PTR_HOCSINH pDSHS;
clrscr();
printf("So luong hoc sinh: ");
scanf("%d", &nSoHS);
pDSHS = (PTR_HOCSINH)calloc(nSoHS,
sizeof(HOCSINH));
if(pDSHS==NULL) return;
for(i=0; i<nSoHS; i++)
NhapHS(&pDSHS[i], i);
for(i=0; i<nSoHS; i++)
XuatHS(pDSHS[i], i);
if(pDSHS) free(pDSHS);
getch();
}
VÍ DỤ MINH HỌA
VÍ DỤ MINH HỌA
Tin học đại cương
22
void NhapHS(PTR_HOCSINH phs, int stt)
{
char hoten[50];
float van, toan;
flushall();
printf("\nHoc sinh thu %d:", stt+1);
printf("\nHo Ten: ");
gets(hoten);
printf("Diem van: ");
scanf("%f", &van);
printf("Diem toan: ");
scanf("%f", &toan);
strcpy(phs->sHoTen, hoten);
phs->fVan = van;
phs->fToan = toan;
phs->fDTB = (float)(van+toan)/2;
}
VÍ DỤ MINH HỌA
VÍ DỤ MINH HỌA
Tin học đại cương
23
void XuatHS(HOCSINH hs, int stt)
{
printf("\n\nHoc sinh thu %d: %s",
stt+1, hs.sHoTen);
printf("\nVan %.1f, Toan %.1f. DTB %.1f",
hs.fVan, hs.fToan, hs.fDTB);
}
VÍ DỤ MINH HỌA
VÍ DỤ MINH HỌA
24
www.uit.edu.vn