CH NG 1: BI N CON TR
§1 KHÁI NI M CHUNG
M t con tr là m t bi n ch a đ a ch c a m t bi n khác N u m t bi n
ch a đ a ch c a m t bi n khác thì ta nói bi n th nh t tr đ n bi n th hai
Cũng nh m i bi n khác, bi n con tr cũng ph i đ c khai báo tr c khi dùng D ng t ng quát đ khai báo m t bi n con tr là:
type *<tên bi n>
Trong đó: type là b t kì ki u d li u c b n thích h p nào đ c ch p nh n trong C và <tên bi n> là tên c a m t bi n con tr Ki u d li u c b n xác
đ nh ki u c a nh ng bi n mà con tr có th ch đ n Ví d khai báo bi n con
tr ch đ n các bi n nguyên và bi n ki u kí t :
char *p;
int *x,*y;
Con tr có m t tr đ c bi t g i là NULL Tr này có nghĩa là con tr ch a tr
t i m t đ a ch h p l nào c Đ dùng đ c tr này chúng ta ph i dùng
#include <stdio.h> đ u ch ng trình
§2 CÁC PHÉP TOÁN V CON TR
C có hai phép toán đ c bi t đ i v i con tr : * và & Phép toán & là phép toán tr v đ a ch trong b nh c a bi n sau nó Ví d :
p = &a;
s đ t vào bi n p đ a ch trong b nh c a bi n a Đ a ch này không có liên quan gì đ n tr s c a bi n a Nói cách khác đ a ch c a bi n a không liên quan gì đ n n i dung c a bi n a
Phép toán * là phép toán tr v tr c a bi n đ t t i đ a ch đ c mô t
b i bi n đi sau nó Ví d n u bi n a ch a đ a ch c a bi n b thì
p = *a
s đ t tr s c a bi n b vào bi n p
Ch ng trình 1 1 : L p ch ng trình in s 100 lên màn hình
main()
{
int *p,a,b;
clrscr();
a=100;
p=&a;
b=*p;
printf( %d ,b);
Trang 2}
§3 T M QUAN TR NG C A D LI U KHI KHAI
BÁO BI N CON TR
C n ph i b o đ m là con tr luôn luôn tr đ n m t ki u d li u phù
h p Ví d khi khai báo con tr ki u int, trình biên d ch s hi u là con tr bao gi cũng ch đ n m t bi n có đ dài là 2 byte
Ta xét m t ch ng trình nh sau:
Ch ng trình 1 2
main()
{
float x=10.1,y;
int *p;
clrscr();
p=&x;
y=*p;
printf( %f ,y);
getch();
}
Ch ng trình này nh m gán tr c a x cho bi n y và in ra tr đó Khi biên d ch ch ng trình không báo l i mà ch nh c nh :
Suspencious pointer conversion in function main
Tuy nhiên ch ng trình không gán tr x cho y đ c Lí do là ta khai báo m t con tr int và cho nó tr t i bi n float x Nh v y trình biên d ch s
ch chuy n 2 byte thông tin cho y ch không ph i 4 byte đ t o ra m t s
d ng float
§4 CÁC BI U TH C CON TR
1 Các phép gán con tr : Cũng gi ng nh b t kì m t bi n nào khác , ta có
th dùng m t con tr v ph i c a m t phép gán đ gán tr c a m t con tr cho m t con tr khác Ví d ta vi t:
2.
Ch ng trình 1 3 :
main()
{
Trang 3int x;
int *p1,*p2;
clrscr();
p1 = &x;
p2 = p1;
printf(“ %p”,p2);
getch();
}
Ch ng trình này hi n lên đ a ch c a bi n x d ng hex b ng cách dùng m t mã đ nh d ng khác c a hàm printf() %p mô t r ng s hi n lên
m t tr ch a trong m t bi n con tr theo d ng reg:xxxx v i reg là tên c a
m t trong các thanh ghi segment c a CPU còn xxxx là đ a ch offset tính t
đ u segment
2 Các phép toán s h c c a con tr : Trong C, ta ch có th dùng hai phép
toán s h c tác đ ng lên con tr là phép + và Đ hi u đ c cái gì s x y ra khi th c hi n m t phép toán s h c lên con tr ta gi s p1 là m t con tr ch
đ n m t s nguyên có đ a ch là 2000 Sau khi th c hi n bi u th c
p1++ ;
con tr s ch đ n s nguyên n m đ a ch 2002 vì m i khi tăng con tr lên 1
nó s ch đ n s nguyên k ti p mà m i s nguyên l i có đ dài 2 byte Đi u này cũng đúng khi gi m Ví d :
p1 ;
s tr t i s nguyên đ a ch 1998 Nh v y m i khi con tr tăng lên 1, nó s
ch đ n d li u k ti p t i đ a ch nào đó tu theo đ dài c a ki u d li u C còn cho phép c ng hay tr m t s nguyên v i m t con tr Bi u th c :
p1 = p1 + 9;
s làm cho con tr ch t i ph n t th 9 có ki u là ki u mà p1 tr t i và n m sau phân t hi n th i nó đang tr đ n Ngoài các phép toán trên , con tr không ch p nh n m t phép toán nào khác
3 So sánh các con tr : Chúng ta có th so sánh 2 con tr trong m t bi u th c
quan h Ví d cho hai p và q, phát bi u sau đây là h p l :
if (p<q)
printf(“p tro den mot vi tri bo nho thap hon q\n”);
Tuy nhiên c n nh r ng phép toán trên là so sánh hai đ a ch ch a trong p
và q ch không ph i n i dung c a hai bi n mà p và q tr t i
Trang 44 Các ví d v vi c dùng con tr :
Ch ng trình 1 4 : Phân tích ch ng trình sau:
main()
{
int i,j,*p;
i=5;
p=&i;
j=*p;
*p=j+2;
}
Trong ch ng trình trên ta khai báo hai bi n nguyên là i và j và m t
bi n con tr p tr t i m t s nguyên Ch ng trình s phân ph i b nh cho
3 bi n này ví d t i các đ a ch 100, 102 và 104 vì m i s nguyên dài 2 byte
và con tr m c nhiên cũng đ c mã hoá b ng 2 byte
l nh i = 5 cho tr s c a bi n i là 5
l nh p = &i làm cho con tr ch t i bi n i nghĩa là con tr p ch a đ a ch c a
bi n i Bây gi p ch đ n bi n i
l nh j = *p đ t n i dung c a bi n do p ch t i (bi n i) vào bi n j nghĩa là gán
5 cho j
Trang 5M t trong nh ng v n đ lí thú khi dùng con tr là xem n i dung b
nh c a máy tính Ch ng trình sau đây cho phép ta vào đ a ch b t đ u
c a RAM mà ta mu n kh o sát và sau đó hi n lên n i dung m i byte d ng
s hex Trong ch ng trình có t khoá far dùng đ tham kh o đ n các v trí không n m trong cùng m t segment
Ch ng trình 1 5 :
main()
{
unsigned long int start;
char *p;
int t;
clrscr();
printf( Nhap vao dia chi bat dau ma ban muon xem : );
scanf( %lu ,&start);
p = (char far *) start;
for(t=0;;t++,p++)
if(!(t%16))
{
printf( %2x\n ,*p);
getch();
}
}
Trong ch ng trình ta dùngđ nh d ng %x trong hàm printf() đ in ra
s d ng hex Dòng p = (char far *) start; dùng bi n đ i s nh p vào thành
m t con tr
Trong ch ng tr c chúng ta đã th y các ví d v m ng Con tr
th ngđ c dùng khi x lí m ng Chúng ta xét ch ng trình sau:
Ch ng trình 1 6 :
main()
{
int a[10],*pa,x;
a[0] =11;
a[1] =22;
a[2] =33;
a[3] = 44;
Trang 6pa = &a[0];
x=*pa;
pa++;
x=*pa;
x=*pa+1;
x=*(pa+1);
x=*++pa;
x=++*pa;
x=*pa++;
}
int a[10] , *pa , x; khai báo m t b ng g m 10 ph n t ki u int, đ c li t kê là a[0], a[1], , a[9] , m t con tr đ ch đ n m t bi n ki u int và m t bi n ki u int là x
a[0] = 11 .; t a[4] đ n a[9] ch a đ c kh i gán Nh v y chúng s ch a tr
ng u nhiên đã có t i nh ng v trí b nh đã phân ph i cho chúng
pa=&a[0]; đ t vào pa đ a ch c a ph n t đ u tiên c a m ng Bi u th c này
có th vi t đ n gi n là pa = a ; vì tên c a m t m ng luôn luôn đ c trình biên d ch coi là đ a ch c a ph n t đ u tiên c a m ng Tên c a m ng không
có ch s kèm theo có th đ c dùng trong ch ng trình nh m t h ng đ a
ch
x=*pa; đ t n i dung c a bi n nguyên mà pa tr đ n vào (t c là a[0]) vào x
Nh v y x = 11
pa++; pa đ c tăng lên 1 và bây gi tr vào ph n t th 2 c a m ng t c là
ch a đ a ch c a ph n t a[1]
x=*pa ; pa tr đ n ph n t a[1] nên x = 22
x = *pa +1; x =23
x = *(pa+1) ; tr c h t pa+1 đ c th c hi n, nghĩa là pa tr vào a[2], sau đó
n i dung c a a[2] đ c gán cho x nên x= 33 Tuy pa tham gia vào phép toán
nh ng tr s c a nó không thay đ i
x = *++pa; ++ đ c th c hi n tr c nên pa tr t i a[2] Sau đó tr c a a[2]
đ c gán cho x nên x =33
x= ++*pa; *pa đ c th c hi n tr c Do pa ch đ n a[2] nên *pa = 33 và ++*pa=34 Nh v y x = 34 và a[2] = 34
x=*pa++; n i dung c a pa (t c 34) đ c đ t vào x Sau đó nó đ c tăng lên 1 nên ch vào a[3]
Ch ng trình 1 7:
Trang 7{
static int num[]={92,81,70,69,58};
int dex;
clrscr();
for(dex=0;dex<5;dex++)
printf( %d\n ,num[dex]);
getch();
}
Ch ng trình 1 8 :
main()
{
static int num[]={92,81,70,69,58};
int dex;
clrscr();
for(dex=0;dex<5;dex++)
printf( %d\n ,*(num+dex));
getch();
}
Hai ch ng trình ch khác nhau bi u th c: *(num+dex) Cách vi t này t ng đ ng v i num[dex] Nói cách khác truy c p đ n ph n t có ch
s dex trong m ng num Chúng ta hi u *(num+dex) nh sau: đ u tiên num
là đ a ch c a ph n t đ u tiên c a m ng num và ta mu n bi t tr s c a
ph n t có ch s dex Vì v y num+dex s là đ a ch c a ph n t th dex
*(num+dex) xácđ nh n i dung c a ph n t (num+dex) Tóm l i :
*(array+index) t ng t array(index)
Có hai cách truy c p m ng là:
theo kí hi u m ng &array[index]
theo kí hi u con tr array+index
Ch ng trình 1 9: Tính nhi tđ trung bình b ng cách dùng con tr
main()
{
float temp[40];
float sum=0.0;
int num,day=0;
clrscr();
do
Trang 8printf( Cho nhiet do ngay thu %d: ,day+1);
scanf( %f ,temp+day);
}
while(*(temp+day++)>0);
num = day 1;
for(day=0;day<num;day++)
sum+=*(temp+day);
printf( Nhiet do trung binh la : %.3f ,sum/num);
getch();
}
Trong ví d trên chúng ta đã dùng bi u th c (temp+day) đ truy c p m ng Tuy nhiên vi t while((*temp++)>0) vì temp là h ng con tr ch không ph i
bi n con tr Nh v y ch đ c phép thay đ i tr c a bi n con tr ch không
đ c thay đ i tr c a h ng con tr Chúng ta vi t l i ch ng trình nh sau:
Ch ng trình 1 10 :
main()
{
float temp[40];
float sum=0.0;
int num,day=0;
float *p;
clrscr();
p=temp;
do
{
printf( Cho nhiet do ngay thu %d: ,day+1);
scanf( %f ,p);
day++;
}
while(*(p++)>0);
p=temp;
num=day 1;
for(day=0;day<num;day++)
sum+=*(p++);
printf( Nhiet do trung binh la : %.3f ,sum/num);
getch();
Trang 9Trong ch ng trình này đ a ch c a temp đ c đ a vào bi n con tr p Sau
đó ta tham kh o t i p gi ng nh temp Ta dùng p tr t i m ng và *p là n i dung c a đ a ch đó H n n a do p là bi n con tr nên ta có th tăng nó
b ng phát bi u p++
§6 CON TR VÀ CHU I
R t nhi u hàm th vi n trong C làm vi c v i chu i theo con tr Ví d hàm strchr() tr v con tr tr đ n l n xu t hi n đ u tiên c a m t kí t nào
đó trong chu i Ví d : ptr = strchr(str,’x’); thì bi n con tr ptr s đ c gán đ a
ch c a l n xu t hi n kí t ‘x’đ u tiên trong chu i str
Sau đây là ch ng trình cho phép ta gõ vào m t câu và m t kí t c n đ nh
v trong câu Ch ng trình s cho ta:
đ a ch b t đ u c a chu i
đ a ch c a kí t c n đ nh v
đ l ch so v i đi m đ u chu i
Ch ng trình 1 11 :
#include<string.h>
main()
{
char ch,line[81],*ptr;
clrscr();
printf( Cho mot cau : );
gets(line);
printf( Cho ki tu can tim : );
ch=getche();
ptr=strchr(line,ch);
printf( \nChuoi bat dau tai dia chi %u.\n ,line);
printf( Ki tu xuat hien lan dau tai %u.\n ,ptr);
printf( Do la vi tri %d ,(ptr line+1));
getch();
}
Chu i cũng có th đ c kh i t o b ng con tr Ta xét ví d sau:
Ch ng trình 1 11 :
main()
{
char *chao= Xin chao ! ;
Trang 10char ten[30];
clrscr();
printf( Cho ten cua ban : );
gets(ten);
printf(chao);
puts(ten);
getch();
}
Trong ch ng trình trên tađã kh i t o chu i b ng phát bi u
char *chao = “ Xin chao !”
thay cho
static char chao[]=” Xin chao !”
C hai cách đ u cho cùng m t k t qu Trong ph ng án dùng con tr , chao là bi n con tr nên có th thay đ i đ c Ví d phát bi u:
puts(++chao)
s cho k t qu : in chao !
N u ta có m t m ng chu i ta cũng có th dùng m ng con tr tr t i
m ng chu i này Ta kh i t o chúng gi ng nh kh i t o bi n con tr đ n
Ch ng trình 1 12 :
#define max 5
main()
{
int dex;
int enter=0;
char name[40];
static char *list[max]=
{
Hung ,
Ngan ,
Van ,
Hoa ,
Tien
};
clrscr();
printf( Cho ten cua ban : );
gets(name);
for(dex=0;dex<max;dex++)
Trang 11if (strcmp(list[dex],name)==0)
enter=1;
if (enter==1)
printf( Ban da dang ki hoc lop C );
else
printf( Ban chua dang ki vao lop );
getch();
}
Phát bi u char *list[max] nói r ng list là m t m ng con tr g m max
ph n t ch t i các kí t Chúng ta xét ti p m t ví d nh sau:
Ch ng trình 1 13: Nh p vào m t dãy tên và s p x p l iđúng th t a,b,c
#define maxnum 38
#define maxlen 81
main()
{
static char name[maxnum][maxlen];
char *ptr[maxnum];
char *temp;
int count = 0;
int in,out;
clrscr();
while (count<maxnum)
{
printf( Ban cho ten : );
gets(name[count]);
if (strlen(name[count])==0)
break;
ptr[count++]=name[count];
}
for (out=0;out<count 1;out++)
for (in=out+1;in<count;in++)
if (strcmp(ptr[out],ptr[in])>0)
{
temp=ptr[in];
ptr[in]=ptr[out];
ptr[out]=temp;
}
printf( Danh sach da sap xep :\n );
Trang 12printf( Ten thu %d : %s\n ,out+1,ptr[out]);
getch();
}
Ch ng trình này dùng c m ng chu i và m ng con tr chu i Con tr
n m trong m ng đ c khai báo nh sau:
char *ptr[maxnum]
chu i n m trong m ng hai chi u
static char name[maxnum][maxlen]
Do ta không bi t m t chu i dài bao nhiêu nên ph i dùng m ng chu i name
có t i đa maxnum ph n t , m i ph n t có maxlen kí t Khi nh p chu i phát bi u:
ptr[count++] = name[count
s gán đ a ch c a m i chu i đ c c t gi trong m ng name[][] vào ph n t con tr ptr Sau đó m ng con tr này đ c s p x p d a trên m ng name[][]
nh ng m ng name[][] không thayđ i gì c
Ngôn ng C có th x lí các thành ph n c a m ng nh m t m ng C
th C có th xem m t dòng c a m ng hai chi u nh là m t m ng m t chi u
đi u này r t ti n l i nh ta đ th y trong ch ng trình trên Câu l nh ptr[count++] = name[count hoàn toàn h p lí vì v ph i chính là đ a ch c a
m ng name[count] và m ng này là m t thành ph n c a m ng name[][] là
m t m ng hai chi u Ta xem l i khai báo:
static char name[maxnum][maxlen]
rõ ràng ta có th xem đây là m t m ng m t chi u có maxnum chu i và tham
kh o t i ph n t c a m ng m t chi u b ng 1 ch s Ví d :
name[count] v i count<=maxnum
nh th :
name[0] : đ a ch c a chu i 1
name[1] : đ a ch c a chu i 2
Chúng ta có m t ch ng trình in ra m t b ng s đ c vi t nh sau:
Ch ng trình 1 14:
#define row 4
#define col 5
main()
{
static int table[row][col]={
Trang 13{13,15,17,19,21}, {20,22,24,26,28}, {31,33,35,37,39}, {40,42,44,46,48}
};
int c=10;
int i,j;
clrscr();
for(i=0;i<row;i++)
for(j=0;j<col;j++)
table[i][j]+=c;
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
printf( %5d ,table[i][j]);
printf( \n );
}
getch();
}
Trong ch ng trình trên ta dùng kí hi u m ng Bây gi ta mu n vi t
ch ng trình dùng kí hi u con tr thay cho kí hi u m ng V y thì làm th nào đ mô t table[i][j] b ng con tr Ta th y r ng:
table là đ a ch c a ph n t đ u tiên c a toàn b m ng, gi đ nh là 1000
do đây là m ng nguyên nên m i ph n t chi m 2 byte và m i dòng chi m 10 byte vì có 5 ph n t Nh v y đ a ch c a hai dòng li n nhau cách nhau 10 byte
do có th xem m i dòng là m t m ng m t chi u nên các m ng m t chi u li n nhau cách nhau 10 byte
trình biên d ch bi t s c t trong m ng qua khai báo nên nó s hi u table+1 là đem table (tr 1000) c ng v i 10 byte thành 1010 T ng t table+2 cho ta 1020
table==100
0
Trang 14Đ tham kh o đ n t ng ph n t c a dòng tr c h t ta l u ý đ a ch
c a m ng cũng là đ a ch c a ph n t đ u tiên c a m ng Ví d v i m ng
m t chi u a[size] thì a và a[0] là nh nhau Tr l i m ng hai chi u đ a ch
c a m ng m t chi u t o b i dòng th 3 c a m ng table[][] là table[2] hay table+2 Trong kí hi u con tr đ a ch c a ph n t đ u tiên c a m ng m t chi u này là &table[2][0] hay *(table + 2) C hai cách vi t table + 2 và *(table + 2) đ u tham kh o n i dung c a cùng m t ô nh (1020) N u c ng 1 vào table + 3 đ có table + 3 thì ta nh n đ c đ a ch c a dòng th 4 trong m ng table[][] N u c ng 1 vào *(table + 2) đ có *(table + 2) + 1 thì có đ a ch c a
ph n t th 2 trong dòng th 3 c a m ng table[][] Tóm l i:
table[i] = *(table+i)
&table[i] = table+i
table[i][j] = *(*table+i)+j)
&table[i][j] = (*(table+i)+j)
Nh v y ch ng trình trênđ c vi t l i nh sau:
Ch ng trình 1 15 :
#define row 4
#define col 5
main()
{
static int table[row][col]={
{13,15,17,19,21}, {20,22,24,26,28}, {31,33,35,37,39}, {40,42,44,46,48}
};
int c=10;
int i,j;
clrscr();
for(i=0;i<row;i++)
for(j=0;j<col;j++)
*(*(table+i)+j)+=c;
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
printf( %5d ,*(*(table+i)+j));
printf( \n );
}
Trang 15}
Bài t p: L p ch ng trình tính hi u đ dài hai chu i nh p vào t bàn phím
L p ch ng trình xácđ nh giá tr c c đ i c a n s nh p vào t bàn phím
L p ch ng trình qu n lí hàng g m ngày, l ng nh p, l ng xu t và hàng
t n kho