Giáo trình C - Chương 1: Biến con trỏ

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 tthì ta nói biến thứ nhất trỏ đến biến thứ hai .

Cũng nh-mọi biến khác, biếncon 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ểudữ 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

pdf11 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 1792 | Lượt tải: 0download
Tóm tắt nội dung Giáo trình C - Chương 1: Biến con trỏ, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
*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: 
main() 
 { 
 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)); 
6
 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 
 { 
 printf("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); 
7
 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(); 
 } 
Trong 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ã 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 
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 !"; 
8
 char 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++) 
 if (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 : 
9
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"); 
 for(out=0;out<count;out++) 
 printf("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ế 
10
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 
Đ7. Con trỏ trỏ đến con trỏ 
 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]={ 
 {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 . 
 1000 13 15 17 19 21 table[0] 
11
table==1000 1010 20 22 24 26 28 table[1] 
 1020 31 33 35 37 39 table[2] 
 1030 40 42 44 46 48 table[3] 
Để 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"); 
 } 
 getch(); 
 } 
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 

File đính kèm:

  • pdfGiao_Trinh_C_Chuong1.pdf
Tài liệu liên quan