第6章C语言指针.docx

上传人:b****8 文档编号:9808371 上传时间:2023-02-06 格式:DOCX 页数:30 大小:178.52KB
下载 相关 举报
第6章C语言指针.docx_第1页
第1页 / 共30页
第6章C语言指针.docx_第2页
第2页 / 共30页
第6章C语言指针.docx_第3页
第3页 / 共30页
第6章C语言指针.docx_第4页
第4页 / 共30页
第6章C语言指针.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

第6章C语言指针.docx

《第6章C语言指针.docx》由会员分享,可在线阅读,更多相关《第6章C语言指针.docx(30页珍藏版)》请在冰豆网上搜索。

第6章C语言指针.docx

第6章C语言指针

6.4.4指针与字符数组

6.5指针的地址分配

6.6指针数组

[例6-13]上述程序也可采用指针变量作子程序的形式参数。

#include

main()

{

  intsub_max();

  intn,a[10],*ptr=a;

  intmax;

  for(n=0;n<=9;n++)

  scanf("%d",&a[n]);

  max=sub_max(ptr,10);

  printf("max=%d\n",max);

}

intsub_max(b,i)/*形式参数为指针变量*/

int*b,i;

{

  inttemp,j;

  temp=b[0];/*数组元素指针的下标法表示*/

  for(j=1;j<=i-1;j++)

  if(temp

  returntemp;

}

  在子程序中,形式参数是指针,调用程序的实际参数ptr为指向一维数组a的指针,虚实结合,子程序的形式参数b得到ptr的值,指向了内存的一维数组。

数组元素采用下标法表示,即一维数组的头指针为b,数组元素可以用b[j]表示。

其内存中虚实参数的结合如图6-10所示。

运行程序:

1357924680

max=9

[例6-14]上述程序的子程序中,数组元素还可以用指针表示。

#include

main()

{

  intsub_max();

  intn,a[10],*ptr=a;

  intmax;

  for(n=0;n<=9;n++)

  scanf("%d",&a[n]);

  max=sub_max(ptr,10);

  printf("max=%d\n",max);

}

intsub_max(b,i)/*子程序定义*/

int*b,i;

{

  inttemp,j;

  temp=*b++;

  for(j=1;j<=i-1;j++)

  if(temp<*b)temp=*b++;

  returntemp;

}

 

  在程序中,赋值语句temp=*b++;可以分解为:

temp=*b;b++;两句,先作temp=*b;后作b++;程序的运行结果与上述完全相同。

  对上面的程序作修改,在子程序中不仅找最大元素,同时还要将元素的下标记录下来。

#include

main()

{

  int*max();/*函数声明*/

  intn,a[10],*s,i;

  for(i=0;i<10;i++)/*输入数据*/

  scanf("%d",a+i);

  s=max(a,10);/*函数调用*/

  printf("max=%d,index=%d\n",*s,s-a);

}

int*max(a,n)/*定义返回指针的函数*/

  int*a,n;

{

  int*p,*t;/*p用于跟踪数组,t用于记录最大值元素的地址*/

  for(p=a,t=a;p-a

  if(*p>*t)t=p;

  returnt;

}

  在max()函数中,用p-a

运行程序:

1357924680

max=9,index=4

[例6-15]用指向数组的指针变量实现一维数组的由小到大的冒泡排序。

编写三个函数用于输入数据、数据排序、数据输出。

  在第5章的例题中,我们介绍过选择法排序及算法,此例再介绍冒泡排序算法。

为了将一组n个无序的数整理成由小到大的顺序,将其放入一维数组a[0]、a[1]...a[n-1]。

冒泡算法如下:

  (开序)

①相邻的数组元素依次进行两两比较,即a[0]与a[1]比、a[1]与a[2]比...a[n-2]与a[n-1]比,通过交换保证数组的相邻两个元素前者小,后者大。

此次完全的两两比较,能免实现a[n-1]成为数组中最大。

②余下n-1个元素,按照上述原则进行完全两两比较,使a[n-2]成为余下n-1个元素中最大。

③进行共计n-1趟完全的两两比较,使全部数据整理有序。

  下面给出一趟排序的处理过程:

原始数据3825

第一次相邻元素比:

3825

第二次相邻元素比:

3285

第三次相邻元素比:

3258

  4个元素进行3次两两比较,得到一个最大元素。

若相邻元素表示为a[j]和a[j+1],用指针变量P指向数组,则相邻元素表示为*(P+j)和*(P+j+1)程序实现如下:

#include

#defineN10

main()

{

  voidinput();/*函数声明*/

  voidsort();

  voidoutput();

  inta[N],*p;/*定义一维数组和指针变量*/

  input(a,N);/*数据输入函数调用,实参a是数组名*/

  p=a;/*指针变量指向数组的首地址*/

  sort(p,N);/*排序,实参p是指针变量*/

  output(p,N);/*输出,实参p是指针变量*/

}

voidinput(arr,n)/*无需返回值的输入数据函数定义,形参arr是数组*/

intarr[],n;

{

  inti;

  printf("inputdata:

\n");

  for(i=0;i

  scanf("%d",&arr);

}

voidsort(ptr,n)/*冒泡排序,形参ptr是指针变量*/

int*ptr,n;

{

  inti,j,t;

  for(i=0;i

  for(j=0;j

  if(*(ptr+j)>*(ptr+j+1))/*相临两个元素进行比较*/

  {

      t=*(ptr+j);/*两个元素进行交换*/

      *(ptr+j)=*(ptr+j+1);

      *(ptr+j+1)=t;

  }

}

voidoutput(arr,n)/*数据输出*/

intarr[],n;

{

  inti,*ptr=arr;/*利用指针指向数组的首地址*/

  printf("outputdata:

\n");

  for(;ptr-arr

  printf("%4d",*ptr);

  printf("\n");

}

运行程序:

3579323432110 

1233579102343

  由于C程序的函数调用是采用传值调用,即实际参数与形式参数相结合时,实参将值传给形式参数,所以当我们利用函数来处理数组时,假如需要对数组在子程序中修改,只能传递数组的地址,进行传地址的调用,在内存相同的地址区间进行数据的修改。

在实际的应用中,假如需要利用子程序对数组进行处理,函数的调用利用指向数组(一维或多维)的指针作参数,无论是实参还是形参共有下面四种情况:

实参  实参  形参  

1  数组名  数组名  

2  数组名  指针变量  

3  指针变量  数组名  

4  指针变量  指针变量 

  在函数的调用时,实参与形参的结合要注重所传递的地址具体指向什么对象,是数组的首址,还是数组元素的地址,这一点很重要。

[例6-16]用指向二维数组的指针作函数的参数,实现对二维数组的按行相加。

#include

#defineM3

#defineN4

main()

{

  floata[M][N];

  floatscore1,score2,score3,*pa=a[0];/*指针变量pa指向二维数组*/

  /*score1,score2,score3分别记录三行的数据相加*/

  inti,j;

  voidfun();

  for(i=0;i

  for(j=0;j

  scanf("%f",&a[j]);

  fun(pa,&score1,&score2,&score3);

  /*函数调用,不仅传递数组首地址,还要传递变量的地址*/

  printf("%.2f,%.2f,%.2f\n",score1,score2,score3);

}

voidfun(b,p1,p2,p3)

floatb[][N],*p1,*p2,*p3;

{

  inti,j;

  *p1=*p2=*p3=0;

  for(i=0;i

  for(j=0;j

  {

      if(i==0)*p1=*p1+b[j];/*第0行的数据相加*/

      if(i==1)*p2=*p2+b[j];/*第1行的数据相加*/

      if(i==2)*p3=*p3+b[j];/*第2行的数据相加*/

  }

}

程序中与形式参数p1、p2和p3相对应的是实际参数&score1、&score2和&score3,其实际含义为p1=&score1等,即将变量的地址传递给指针变量达到按行相加。

运行程序:

1234

3456

5678

10.00,18.00,26.00

[例6-17]求解二维数组中的最大值及该值在二维数组中的位置。

  我们知道,二维数组在内存中是按行存放,假定我们定义二维数组和指针如下:

inta[3][4],*p=a[0];

则指针p就指向二维数组。

其在内存的存放情况如图6-11所示。

从上述存放情况来看,若把二维数组的首地址传递给指针p,则映射过程如图6-11所示。

我们只要找到用p所表示的一维数组中最大的元素及下标,就可转换为在二维数组中的行列数。

 

#include

main()

{

  inta[3][4],*ptr,i,j,max,maxi,maxj;

  /*max是数组的最大,maxi是最大元素所在行,maxj是最大元素所在列*/

  for(i=0;i<3;i++)

  for(j=0;j<4;j++)

  scanf("%d",&a[j]);

  ptr=a[0];/*将二维数组的首地址传递给指针变量*/

  max_arr(ptr,&max,&maxi,12);

  maxj=maxi%4;/*每行有四个元素,求该元素所在列*/

  maxi=maxi/4;/*求该元素所在行*/

  printf("max=%d,maxi=%d,maxj=%d",max,maxi,maxj);

}

intmax_arr(b,p1,p2,n)

int*b,*p1,*p2,n;

/*b指向二维数组的指针,p1指向最大值,p2指向最大值在一维数组中的位置,*/

/*n是数组的大小*/

{

  inti;

  *p1=b[0];*p1=0;

  for(i=1;i

  if(b>*p1) 

  {

      *p1=b;*p2=i;

  }

}

运行程序:

4789

3793

1526

max=9,maxi=0,maxj=3

div>6.4.4指针与字符数组

  在前面的课程中,我们用过了字符数组,即通过数组名来表示字符串,数组名就是数组的首地址,是字符串的起始地址。

下面的例子用于简单字符串的输入和输出。

#include

main()

{

  charstr[20];

  gets(str);

  printf("%s\n",str);

}

goodmorning!

goodmorning!

    现在,我们将字符数组的名赋予一个指向字符类型的指针变量,让字符类型指针指向字符串在内存的首地址,对字符串的表示就可以用指针实现。

其定义的方法为:

charstr[20],*P=str;这样一来,字符串str就可以用指针变量P来表示了。

#include

main()

{

  charstr[20],*p=str;/*p=str则表示将字符数组的首地址传递给指针变量p*/

  gets(str);

  printf("%s\n",p);

}

goodmorning!

goodmorning!

  需要说明的是,字符数组与字符串是有区别的,字符串是字符数组的一种非凡形式,存储时以“\0”结束,所以,存放字符串的字符数组其长度应比字符串大1。

对于存放字符的字符数组,若未加“\0”结束标志,只能按逐个字符输入输出。

[例6-18]字符数组的正确使用方法。

#include

main()

{

  charstr[10],*p=str;

  inti;

  scanf("%s",str);/*输入的字符串长度超过10*/

  for(i=0;i<10;i++)

  printf("%c",*p++);/*正确输出*/

  printf("\n");

  p=str;

  printf("%s",p);/*字符数组无'\0'标志,输出出错*/

  puts(str);/*字符数组无'\0'标志,输出出错*/

}

  对上述程序中字符数组以字符串形式输出,若无“\0”标志,则找不到结束标志,输出出错。

[例6-19]用指向字符串的指针变量处理两个字符串的复制。

字符串的复制要注重的是:

若将串1复制到串2,一定要保证串2的长度大于或等于串1。

#include

main()

{

  charstr1[30],str2[20],*ptr1=str1,*ptr2=str2;

  printf("inputstr1:

");

  gets(str1);/*输入str1*/

  printf("inputstr2:

");

  gets(str2);/*输入str2*/

  printf("str1------------str2\n");

  printf("%s.......%s\n",ptr1,ptr2);

  while(*ptr2)*ptr1++=*ptr2++;/*字符串复制*/

  *ptr1='\0';/*写入串的结束标志*/

  printf("str1------------str2\n");

  printf("%s.......%s\n",str1,str2);

}

  在程序的说明部分,定义的字符指针指向字符串。

语句while(*ptr2)*ptr1++=*ptr2++;先测试表达式的值,若指针指向的字符是“\0”,该字符的ASCII码值为0,表达式的值为假,循环结束,表达式的值非零,则执行循环*ptr1++=*ptr2++。

语句*ptr1++按照运算优先级别,先算*ptr1,再算ptr1++。

运行程序:

 

inputstr1:

IloveChina!

 

inputstr2:

IloveChengdu!

 

str1--------------------str2

IloveChina!

.......IloveChengdu!

str1--------------------str2

IloveChengdu!

.......IloveChengdu!

  现在,我们修改程序中语句printf("%s.......%s\n",str1,str2)为printf("%s.......%s\n",ptr1,ptr2);

会出现什么结果呢?

请思考。

[例6-20]用指向字符串的指针变量处理两个字符串的合并。

#include

main()

{

  charstr1[50],str2[20],*ptr1=str1,*ptr2=str2;

  printf("inputstr1:

");

  gets(str1);

  printf("inputstr2:

");

  gets(str2);

  printf("str1------------str2\n");

  printf("%s.......%s\n",ptr1,ptr2);

  while(*ptr1)ptr1++;/*移动指针到串尾*/

  while(*ptr2)*ptr1++=*ptr2++;/*串连接*/

  *ptr1='\0';/*写入串的结束标志*/

  ptr1=str1;ptr2=str2;

  printf("str1------------------str2\n");

  printf("%s.......%s\n",ptr1,ptr2);

}

inputstr1:

IloveChina!

 

inputstr2:

IloveChengdu!

 

str1--------------------str2

IloveChina!

.......IloveChengdu!

str1------------------------------------------str2

IloveChina!

IloveChengdu!

......IloveChengdu!

.

  需要注重的是,串复制时,串1的长度应大于等于串2;串连接时,串1的长度应大于等于串1与串2的长度之和。

6.5指针的地址分配

  我们可以定义指针变量指向任何类型的变量。

在上述的处理过程中,指针变量指向的变量通过传递变量的地址来实现。

指针变量的取值是内存的地址,这个地址应当是安全的,不可以是随意的,否则,写入内存单元的值将会使得已存放的数据或程序丢失。

应使用编译系统提供的标准函数来实现地址分配。

  ANSI标准建议设置了两个最常用的动态分配内存的函数malloc()和free(),并包含在stdlib.h中,但有些C编译却使用malloc.h包含。

使用时请参照具体的C编译版本。

  我们这里所指的动态内存分配其含义是指:

当定义指针变量时,其变量的取值是随机的,可能指向内存的任一单元。

若指针的指向是不安全的内存地址,在该地址空间上的数据交换就会产生意料不到的效果。

为此,在程序的执行过程中,要保证指针操作的安全性,就要为指针变量分配安全地址。

在程序执行时为指针变量所做的地址分配就称之为动态内存分配。

当无需指针变量操作时,可以将其所分配的内存归还系统,此过程我们称之为内存单元的释放。

malloc()用以向编译系统申请分配内存;free()用以在使用完毕释放掉所占内存。

[例6-21]两个字符串的交换。

#include

#include

#include

main()

{

  char*ptr1,*ptr2,*temp;

  ptr1=malloc(30);/*动态为指针变量分配长度为30字节的存储空间*/

  ptr2=malloc(20);

  temp=malloc(30);

  printf("inputstr1:

");

  gets(ptr1);/*输入字符串*/

  printf("inputstr2:

");

  gets(ptr2);

  printf("str1------------str2\n");

  printf("%s.......%s\n",ptr1,ptr2);

  strcpy(temp,ptr1);/*串复制*/

  strcpy(ptr1,ptr2);

  strcpy(ptr2,temp);

  printf("str1------------str2\n");

  printf("%s.......%s\n",ptr1,ptr2);

  free(ptr1);

  free(ptr2);

}

  为指针变量分配的存储空间长度取决于存放字符的多少。

在上述的程序中,两个串的交换可以通过标准函数strcpy()来完成,也可以通过串指针交换指向完成,用temp=ptr1;

  ptr1=ptr2;ptr2=temp;三条赋值语句实现。

但是,利用指针交换指向,其物理意义与串通过函数进行的复制完全不同。

前者是存放串地址的指针变量数据交换,后者是串在内存物理空间的数据交换。

指针变量用完后,将指针变量所占的存储空间释放。

运行程序:

run

inputstr1:

China

inputstr2:

Chengdu

str1------------str2

China----------Chengdu

str1------------str2

Chengdu-----China

6.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 少儿英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1