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

pdf55 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 2131 | Lượt tải: 1download
Tóm tắt nội dung Bài giảng Ngôn ngữ lập trình C - Dữ liệu kiểu cấu trúc, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
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:

  • pdfBài giảng Ngôn ngữ lập trình C - Dữ liệu kiểu cấu trúc.pdf
Tài liệu liên quan