Bài giảng Ngôn ngữ lập trình C - Dữ liệu kiểu cấu trúc
Mục đích
Biết cách khai báo các kiểu dữ liệu phức
tạp: cấu trúc
Cách biểu diễn các kiểu danh sách liên kết
nhờ cấu trúc tự trỏ
Các thao tác trên danh sách liên kết
ai báo
Ví dụ:
struct sinhvien {
char hoten[30];
float diemtb;
};
typedef struct sinhvien sv;
typedef struct sinhvien *ptr_sv;
Cấu trúc struct sinhvien sẽ là sv
Định nghĩa một kiểu con trỏ cấu trúc có tên là ptr_sv
Khi đó:
sv sv1, sv2, dssv[100]; ~ struct sinhvien sv1, sv2, dssv[100];
ptr_sv ptrsv; ~ struct sinhvien *ptrsv;
Thao tác trên biến cấu trúc
Truy cập thành phần trong cấu trúc
Truy cập tới thành phần cấu trúc từ con
trỏ cấu trúc
Nhập dữ liệu cho biến cấu trúc
Truy cập thành phần trong cấu trúc
Cần đến tên thành phần và biến tương ứng
Cú pháp:
.
Dấu chấm (.) là toán tử truy cập thành phần cấu trúc
Nếu có nhiều cấu trúc lồng nhau thì sử dụng nhiều
dấu (.) tương ứng
Ví dụ:
p.x = 0; p.y = 5;
dg1.dsdinh[10].x = 0; dg1.n = 10;
Truy cập thành phần cấu trúc từ
con trỏ cấu trúc
Nếu ptr là con trỏ cấu trúc, có 2 cách để
truy cập tới thành phần của nó
Cách 1:
(*ptr).
Cách 2:
ptr->
Nhập dữ liệu cho biến cấu trúc
Nên sử dụng biến trung gian
Nhập dữ liệu qua biến trung gian
Gán các giá trị nhập được cho các thành phần cần
nhập
Ví dụ
float temp;
printf("Toa do x=");
scanf("%f", &temp);
p.x = temp;
printf("Toa do y=");
scanf("%f", &temp);
p.y = temp;
Ví dụ
/*struct2.c*/
#include
#include
struct sinhvien {
char hoten[30];
float diemtb;
};
void main()
{
int n;
int k;
int i;
struct sinhvien dssv[100];
char name[30];
float temp;
clrscr();
n = 0;
do {
printf("Nhap thong tin sinh vien thu %d\n",n+1);
printf("Ho ten:");
fflush(stdin);
gets(name);
if (strcmp(name,"")!=0)
{
strcpy(dssv[n].hoten,name);
printf("Diem:");
scanf("%f",&temp);
dssv[n++].diemtb = temp;
}
} while (strcmp(name,"")!=0);
if (!n) {
printf("Khong co sinh vien nao\n");
return;
}
else {
k = 0;
// printf("DS Sv nhan hoc bong");
for (i=0; i<n; i++){
if (dssv[i].diemtb >=7)
k++;
}
if (!k)
printf("Khong co sinh vien dat hoc bong");
else
for (i=0; i<n; i++)
if (dssv[i].diemtb >=7)
printf("%d\t%s
%5.2f\n",i+1,dssv[i].hoten,dssv[i].diemtb);
}
getch();
}
Phép gán giữa các biến cấu trúc
Gán nội dung của một biến cấu trúc cho
một biến cấu trúc khác cùng kiểu
Ví dụ
/*struct3.c*/
#include
#include
struct sinhvien {
char hoten[30];
float diemtb;
} sv1, sv2;
void main()
{
clrscr();
sv1.diemtb = 8.7;
strcpy(sv1.hoten,"Nguyen Van A");
sv2 = sv1;
printf("sv1: (%s\t%5.2f)\n",sv1.hoten,sv1.diemtb);
printf("sv2: (%s\t%5.2f)\n",sv2.hoten,sv2.diemtb);
getch();
}
Kết quả
Truyền biến cấu trúc cho hàm
Truyền biến cấu trúc bằng tham trị
Nội dung của biến cấu trúc dùng làm tham số
thực được sao chép sang vùng nhớ dành cho
tham số hình thức
Giảm tốc độ thực hiện chương trình
Truyền biến cấu trúc bằng tham biến
Truyền cho hàm địa chỉ của cấu trúc
Ví dụ
Khai báo hai cấu trúc
Cấu trúc điểm gồm 2 thành phần hoành độ,
tung độ
Cấu trúc tam giác gồm 3 thành phần là 3 biến
có kiểu điểm
Nhập, tính diện tích tam giác
Cho biến tam giác vừa nhập là loại tam giác
nào
Ví dụ
/*struct4.c*/
#include
#include
#include
typedef struct {
float x, y;
} diem;
typedef struct {
diem A, B, C;
} tamgiac;
void nhap(tamgiac *);
float canh(diem, diem);
float canhbp(diem, diem);
int loaitg(tamgiac);
float dientich(tamgiac);
void main() {
tamgiac tg;
clrscr();
printf("Nhap toa do cac dinh tam giac\n");
nhap(&tg);
printf("Canh BC:%f\n", canh(tg.B,tg.C));
printf("Canh CA:%f\n", canh(tg.C,tg.A));
printf("Canh AB:%f\n", canh(tg.A,tg.B));
switch (loaitg(tg)) {
case 1:
printf("Tam giac deu\n"); break;
case 2:
printf("Tam giac vuong can\n"); break;
case 3:
printf("Tam giac can\n"); break;
case 4:
printf("Tam giac vuong\n"); break;
case 5:
printf("Tam giac thuong\n"); break;
}
printf("Dien tich %f\n",dientich(tg));
getch();
}
void nhap(tamgiac *temp){
float t;
printf("Nhap dinh A\n");
printf("x=");
scanf("%f",&t);
temp->A.x = t;
printf("y=");
scanf("%f",&t);
temp->A.y = t;
printf("Nhap dinh B\n");
printf("x=");
scanf("%f",&t);
temp->B.x = t;
printf("y=");
scanf("%f",&t);
temp->B.y = t;
printf("Nhap dinh C\n");
printf("x=");
scanf("%f",&t);
temp->C.x = t;
printf("y=");
scanf("%f",&t);
temp->C.y = t;
}
float canh(diem p, diem q){
return (sqrt(pow(p.x-q.x,2.0)+pow(p.y-q.y,2.0)));
}
float canhbp(diem p, diem q){
return (pow(p.x-q.x,2.0)+pow(p.y-q.y,2.0));
}
float dientich(tamgiac tg){
float a, b, c, p;
a = canhbp(tg.B,tg.C);
b = canhbp(tg.A,tg.C);
c = canhbp(tg.A,tg.B);
p = (a+b+c)/2;
return (sqrt(p*(p-a)*(p-b)*(p-c)));
}
int loaitg(tamgiac tg){
float a, b, c;
a = canh(tg.B,tg.C);
b = canh(tg.A,tg.C);
c = canh(tg.A,tg.B);
if (a==b||b==c||c==a)
if (a==b&&b==c)
return 1;
else
if (a==b+c||b==c+a||c==b+a)
return 2;
else return 3;
else if (a==b+c||b==c+a||c==a+b)
return 4;
else return 5;
}
Cấu trúc tự trỏ
Khái niệm cấu trúc tự trỏ:
Cấu trúc có ít nhất một thành phần là con trỏ
chỉ đến bản thân cấu trúc
Đặc điểm
Kéo dài danh sách ra vô hạn
Hạn chế bộ nhớ nếu số lượng phần tử nhỏ
Các thao tác phức tạp hơn
Ví dụ
struct sinhvien {
char hoten[30];
float diem;
struct sinhvien *next;
};
struct tree {
float x;
struct tree *left, *right;
};
Ví dụ - LIFO
Tạo danh sách móc nối gồm 100 số tự
nhiên đầu tiên; in lại danh sách.
/*dsmn3.c*/
#include
#include
typedef struct mn {
int so;
struct nn *next;
} mn;
mn *ds;
mn *ptmoi(int);
void taods();
void inds();
void main(){
taods();
inds();
getch();
}
mn *ptmoi(int k){
mn *p;
p = (mn *)malloc(sizeof(mn));
p->so = k;
return p;
}
void taods(){ //Kieu LIFO
int i;
mn *p;
ds = NULL;
for (i=1; i<=100; i++){
p = ptmoi(i);
p->next = ds;
ds = p;
}
}
void inds(){
mn *p;
for (p=ds; p; p=p->next)
printf("%5d",p->so);
puts("");
}
Cách 2
mn* ptmoi(int);
mn* taods();
void inds(mn*)
void main()
{
mn *ds;
ds=taods();
inds(ds);
getch();
}
mn *taods(){
int i;
mn *p, *ds;
ds = NULL;
for (i=1; i<=100; i++){
p = ptmoi(i);
p->next = ds;
ds = p;
}
return ds;
}
Ví dụ - LIFO
Tạo ngẫu nhiên một dãy gồm 10 số
nguyên, các số nằm trong khoảng từ 0
đến 100, đưa vào một danh sách móc nối
Sắp lại danh sách theo thứ tự giảm dần
Xóa tất cả các số chẵn
/*dsmn4.c*/
#include
#include
#include
typedef struct mn {
int so;
struct mn *next;
} mn;
mn *ds;
int m = 10;
void taoday(){
int i;
mn *p;
randomize();
ds = NULL;
for (i=0; i<m; i++){
if (!(p=(mn*)malloc(sizeof(mn)))){
puts("Loi cap phat bo nho");
getch();
exit(0);
}
p->so = random(51);
p->next = ds;
ds = p;
}
}
void sapxep(){
mn *p, *t;
int x;
p = ds;
for (p = ds; p->next; p = p->next)
for (t = p->next; t; t=t->next)
if (p->so so)
{
x = p->so;
p->so = t->so;
t->so = x;
}
}
void inday(){
mn *p;
for (p=ds; p; p=p->next)
printf("%5d",p->so);
puts("");
}
void xoasau(mn *p){
if (p->next)
p->next = (p->next)->next;
else
printf("Khong hop le");
}
void main(){
mn *p;
clrscr();
taoday();
inday();
sapxep();
inday();
for (p = ds; p->next;)
if ((p->next)->so %2==0)
xoasau(p);
else if (p->next)
p = p->next;
if (ds->so%2==0)
ds = ds->next;
inday();
getch();
}
Kết quả
Ví dụ - FIFO
Đưa vào một danh sách móc nối thông tin
tên và điểm của từng học sinh; nhập điểm
chuẩn:
Đưa những học sinh đạt điểm chuẩn vào đầu
danh sách
Những học sinh không đạt xuống cuối danh
sách
(không làm thay đổi thứ tự)
/*dsmn5.c*/
#include
#include
#include
typedef struct {
char ten[20];
float diem;
} hocsinh;
typedef struct mn{
hocsinh hs;
struct mn *next;
} ptr;
ptr *ds;
void taods(){
ptr *p, *q;
hocsinh x;
float d;
char w[20];
ds = NULL;
puts("Nhap danh sach ten, diem. Het go /");
fflush(stdin);
gets(w);
while (strcmp(w,"/")){
strcpy(x.ten,w);
scanf("%f",&d);
x.diem = d;
p = (ptr*)malloc(sizeof(ptr));
p->hs = x;
p->next = NULL;
if (ds)
q->next = p;
else
ds = p;
q = p;
fflush(stdin);
gets(w);
}
}
void sapxep(){
float d;
hocsinh x;
ptr *p;
int tiep = 1;
printf("Nhap diem chuan");
scanf("%f",&d);
while (tiep){
tiep = 0;
for (p=ds; p->next; p=p->next)
if (p->hs.diemnext)->hs.diem>=d){
x = p->hs;
p->hs = (p->next)->hs;
(p->next)->hs = x;
tiep = 1;
}
}
}
void inds(){
ptr *p;
for (p=ds; p; p=p->next)
printf("%s %6.1f\n",p->hs.ten,p->hs.diem);
getch();
}
void main(){
taods();
inds();
sapxep();
inds();
}
Cây tìm kiếm nhị phân
Ví dụ:
Nhập một dãy số thực
Xây dựng cây tìm kiếm nhị phân từ dãy số đó
/*tree.c*/
#include
#include
#include
typedef struct node {
float k;
struct node *left, *right;
} node;
node *goc;
node *nutmoi(float x);
void them(float x, node *p);
void taocay();
void incay(node *p);
void tim(float x, node *p, int t);
void main(){
float y;
taocay();
incay(goc);
printf("Nhap y=");
scanf("%f",&y);
tim(y,goc,1);
incay(goc);
getch();
}
node *nutmoi(float x){
node *p;
if(!(p=(node*)malloc(sizeof(node)))){
printf("Loi cap phat bo nho");
getch();
exit(0);
}
p->k = x;
p->left = p->right = NULL;
return p;
}
void them(float x, node *p){
if (x==p->k) return;
if (xk){
if (p->left)
them(x,p->left);
else p->left = nutmoi(x);
}
else{
if(p->right)
them(x,p->right);
else p->right = nutmoi(x);
}
}
void taocay(){
float x;
int i, n;
printf("x=");
scanf("%f",&x);
printf("n=");
scanf("%d",&n);
for (i=1; i<n; i++){
printf("x=");
scanf("%f",&x);
them(x,goc);
}
}
void incay(node *p){
if (!p) return;
incay(p->left);
printf("%6.1f",p->k);
incay(p->right);
}
void tim(float x, node *p, int t){
if(!p){
printf("Khong tim thay");
getch();
exit(0);
}
if (p->k==x){
puts("Da tim thay");
getch();
exit(0);
}
if (xk)
tim(x,p->left,t+1);
else tim(x,p->right,t+1);
}
File đính kèm:
Bài giảng Ngôn ngữ lập trình C - Dữ liệu kiểu cấu trúc.pdf

