?? 10.txt
字號:
if(*p>max)max=*p;
else if (*p<min)min=*p;
return;
}
main()
{int i,number[10],*p;
p=number; /*使p指向number數組*/
printf("enter 10 integer umbers:\n");
for(i=0;i<10;i++,p++)
scanf("%d",p);
p=number;
max_min_value(p,10);
printf("\nmax=%d,min=%d\n",max,min);
}
歸納起來,如果有一個實參數組,想在函數中改變此數組的元素的值,實參與形參的對應關系有以下4種:
1) 形參和實參都是數組名。
main()
{int a[10];
……
f(a,10)
……
f(int x[],int n)
{
……
}
}
a和x指的是同一組數組。
2) 實用數組,形參用指針變量。
main()
{int a[10];
……
f(a,10)
……
f(int *x,int n)
{
……
}
}
3) 實參、型參都用指針變量。
4) 實參為指針變量,型參為數組名。
【例10.20】用實參指針變量改寫將n個整數按相反順序存放。
void inv(int *x,int n)
{int *p,m,temp,*i,*j;
m=(n-1)/2;
i=x;j=x+n-1;p=x+m;
for(;i<=p;i++,j--)
{temp=*i;*i=*j;*j=temp;}
return;
}
main()
{int i,arr[10]={3,7,9,11,0,6,7,5,4,2},*p;
p=arr;
printf("The original array:\n");
for(i=0;i<10;i++,p++)
printf("%d,",*p);
printf("\n");
p=arr;
inv(p,10);
printf("The array has benn inverted:\n");
for(p=arr;p<arr+10;p++)
printf("%d,",*p);
printf("\n");
}
注意:main函數中的指針變量p是有確定值的。即如果用指針變作實參,必須現使指針變量有確定值,指向一個已定義的數組。
【例10.21】用選擇法對10個整數排序。
main()
{int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The original array:\n");
for(i=0;i<10;i++)
printf("%d,",a[i]);
printf("\n");
p=a;
sort(p,10);
for(p=a,i=0;i<10;i++)
{printf("%d ",*p);p++;}
printf("\n");
}
sort(int x[],int n)
{int i,j,k,t;
for(i=0;i<n-1;i++)
{k=i;
for(j=i+1;j<n;j++)
if(x[j]>x[k])k=j;
if(k!=i)
{t=x[i];x[i]=x[k];x[k]=t;}
}
}
說明:函數sort用數組名作為形參,也可改為用指針變量,這時函數的首部可以改為:
sort(int *x,int n) 其他可一律不改。
10.3.4 指向多維數組的指針和指針變量
本小節以二維數組為例介紹多維數組的指針變量。
1. 多維數組的地址
設有整型二維數組a[3][4]如下:
0 1 2 3
4 5 6 7
8 9 10 11
它的定義為:
int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}
設數組a的首地址為1000,各下標變量的首地址及其值如圖所示。
前面介紹過,C語言允許把一個二維數組分解為多個一維數組來處理。因此數組a可分解為三個一維數組,即a[0],a[1],a[2]。每一個一維數組又含有四個元素。
例如a[0]數組,含有a[0][0],a[0][1],a[0][2],a[0][3]四個元素。
數組及數組元素的地址表示如下:
從二維數組的角度來看,a是二維數組名,a代表整個二維數組的首地址,也是二維數組0行的首地址,等于1000。a+1代表第一行的首地址,等于1008。如圖:
a[0]是第一個一維數組的數組名和首地址,因此也為1000。*(a+0)或*a是與a[0]等效的, 它表示一維數組a[0]0 號元素的首地址,也為1000。&a[0][0]是二維數組a的0行0列元素首地址,同樣是1000。因此,a,a[0],*(a+0),*a,&a[0][0]是相等的。
同理,a+1是二維數組1行的首地址,等于1008。a[1]是第二個一維數組的數組名和首地址,因此也為1008。&a[1][0]是二維數組a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。
由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。
此外,&a[i]和a[i]也是等同的。因為在二維數組中不能把&a[i]理解為元素a[i]的地址,不存在元素a[i]。C語言規定,它是一種地址計算方法,表示數組a第i行首地址。由此,我們得出:a[i],&a[i],*(a+i)和a+i也都是等同的。
另外,a[0]也可以看成是a[0]+0,是一維數組a[0]的0號元素的首地址,而a[0]+1則是a[0]的1號元素首地址,由此可得出a[i]+j則是一維數組a[i]的j號元素首地址,它等于&a[i][j]。
由a[i]=*(a+i)得a[i]+j=*(a+i)+j。由于*(a+i)+j是二維數組a的i行j列元素的首地址,所以,該元素的值等于*(*(a+i)+j)。
【例10.22】
main(){
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
printf("%d,",a);
printf("%d,",*a);
printf("%d,",a[0]);
printf("%d,",&a[0]);
printf("%d\n",&a[0][0]);
printf("%d,",a+1);
printf("%d,",*(a+1));
printf("%d,",a[1]);
printf("%d,",&a[1]);
printf("%d\n",&a[1][0]);
printf("%d,",a+2);
printf("%d,",*(a+2));
printf("%d,",a[2]);
printf("%d,",&a[2]);
printf("%d\n",&a[2][0]);
printf("%d,",a[1]+1);
printf("%d\n",*(a+1)+1);
printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
}
2. 指向多維數組的指針變量
把二維數組a分解為一維數組a[0],a[1],a[2]之后,設p為指向二維數組的指針變量。可定義為:
int (*p)[4]
它表示p是一個指針變量,它指向包含4個元素的一維數組。若指向第一個一維數組a[0],其值等于a,a[0],或&a[0][0]等。而p+i則指向一維數組a[i]。從前面的分析可得出*(p+i)+j是二維數組i行j 列的元素的地址,而*(*(p+i)+j)則是i行j列元素的值。
二維數組指針變量說明的一般形式為:
類型說明符 (*指針變量名)[長度]
其中“類型說明符”為所指數組的數據類型。“*”表示其后的變量是指針類型。“長度”表示二維數組分解為多個一維數組時,一維數組的長度,也就是二維數組的列數。應注意“(*指針變量名)”兩邊的括號不可少,如缺少括號則表示是指針數組(本章后面介紹),意義就完全不同了。
【例10.23】
main(){
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*p)[4];
int i,j;
p=a;
for(i=0;i<3;i++)
{for(j=0;j<4;j++) printf("%2d ",*(*(p+i)+j));
printf("\n");}
}
10.4 字符串的指針指向字符串的針指變量
10.4.1 字符串的表示形式
在C語言中,可以用兩種方法訪問一個字符串。
1) 用字符數組存放一個字符串,然后輸出該字符串。
【例10.24】
main(){
char string[]=”I love China!”;
printf("%s\n",string);
}
說明:和前面介紹的數組屬性一樣,string是數組名,它代表字符數組的首地址。
2) 用字符串指針指向一個字符串。
【例10.25】
main(){
char *string=”I love China!”;
printf("%s\n",string);
}
字符串指針變量的定義說明與指向字符變量的指針變量說明是相同的。只能按對指針變量的賦值不同來區別。對指向字符變量的指針變量應賦予該字符變量的地址。
如:
char c,*p=&c;
表示p是一個指向字符變量c的指針變量。
而:
char *s="C Language";
則表示s是一個指向字符串的指針變量。把字符串的首地址賦予s。
上例中,首先定義string是一個字符指針變量,然后把字符串的首地址賦予string(應寫出整個字符串,以便編譯系統把該串裝入連續的一塊內存單元),并把首地址送入string。程序中的:
char *ps="C Language";
等效于:
char *ps;
ps="C Language";
【例10.26】輸出字符串中n個字符后的所有字符。
main(){
char *ps="this is a book";
int n=10;
ps=ps+n;
printf("%s\n",ps);
}
運行結果為:
book
在程序中對ps初始化時,即把字符串首地址賦予ps,當ps= ps+10之后,ps指向字符“b”,因此輸出為"book"。
【例10.27】在輸入的字符串中查找有無‘k’字符。
main(){
char st[20],*ps;
int i;
printf("input a string:\n");
ps=st;
scanf("%s",ps);
for(i=0;ps[i]!='\0';i++)
if(ps[i]=='k'){
printf("there is a 'k' in the string\n");
break;
}
if(ps[i]=='\0') printf("There is no 'k' in the string\n");
}
【例10.28】本例是將指針變量指向一個格式字符串,用在printf函數中,用于輸出二維數組的各種地址表示的值。但在printf語句中用指針變量PF代替了格式串。 這也是程序中常用的方法。
main(){
static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
char *PF;
PF="%d,%d,%d,%d,%d\n";
printf(PF,a,*a,a[0],&a[0],&a[0][0]);
printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);
printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);
printf("%d,%d\n",a[1]+1,*(a+1)+1);
printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
}
【例10.29】本例是把字符串指針作為函數參數的使用。要求把一個字符串的內容復制到另一個字符串中,并且不能使用strcpy函數。函數cprstr的形參為兩個字符指針變量。pss指向源字符串,pds指向目標字符串。注意表達式:(*pds=*pss)!=`\0'的用法。
cpystr(char *pss,char *pds){
while((*pds=*pss)!='\0'){
pds++;
pss++; }
}
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cpystr(pa,pb);
printf("string a=%s\nstring b=%s\n",pa,pb);
}
在本例中,程序完成了兩項工作:一是把pss指向的源字符串復制到pds所指向的目標字符串中,二是判斷所復制的字符是否為`\0',若是則表明源字符串結束,不再循環。否則,pds和pss都加1,指向下一字符。在主函數中,以指針變量pa,pb為實參,分別取得確定值后調用cprstr函數。由于采用的指針變量pa和pss,pb和pds均指向同一字符串,因此在主函數和cprstr函數中均可使用這些字符串。也可以把cprstr函數簡化為以下形式:
cprstr(char *pss,char*pds)
{while ((*pds++=*pss++)!=`\0');}
即把指針的移動和賦值合并在一個語句中。 進一步分析還可發現`\0'的ASCⅡ碼為0,對于while語句只看表達式的值為非0就循環,為0則結束循環,因此也可省去“!=`\0'”這一判斷部分,而寫為以下形式:
cprstr (char *pss,char *pds)
{while (*pdss++=*pss++);}
表達式的意義可解釋為,源字符向目標字符賦值,移動指針,若所賦值為非0則循環,否則結束循環。這樣使程序更加簡潔。
【例10.30】簡化后的程序如下所示。
cpystr(char *pss,char *pds){
while(*pds++=*pss++);
}
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cpystr(pa,pb);
printf("string a=%s\nstring b=%s\n",pa,pb);
}
10.4.2 使用字符串指針變量與字符數組的區別
用字符數組和字符指針變量都可實現字符串的存儲和運算。但是兩者是有區別的。在使用時應注意以下幾個問題:
1. 字符串指針變量本身是一個變量,用于存放字符串的首地址。而字符串本身是存放在以該首地址為首的一塊連續的內存空間中并以‘\0’作為串的結束。字符數組是由于若干個數組元素組成的,它可用來存放整個字符串。
2. 對字符串指針方式
char *ps="C Language";
可以寫為:
char *ps;
ps="C Language";
而對數組方式:
static char st[]={"C Language"};
不能寫為:
char st[20];
st={"C Language"};
而只能對字符數組的各元素逐個賦值。
從以上幾點可以看出字符串指針變量與字符數組在使用時的區別,同時也可看出使用指針變量更加方便。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -