本章主要教学内容_第1页
本章主要教学内容_第2页
本章主要教学内容_第3页
本章主要教学内容_第4页
本章主要教学内容_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

会计学1本章主要教学内容2§7.1指针(Pointer)的概述C的数据类型:

基本类(简单类)——字符型/整型/实型/枚举型构造类(组合类)——数组/结构体/共用体指针类空类型(void)第1页/共65页31.内存地址2.寻址方式整型变量i…...…...2000200420062005200120022003地址10与指针相关的概念与问题第2页/共65页4内存是计算机内的存储部件,所有指令和数据都保存在内存内速度快,但是掉电即失可以随机访问只要指名要访问的内存单元的地址,就可以立即访问到该单元地址是一个无符号整数,其字长一般与主机相同内存中的每个字节都有唯一的一个地址地址按字节编号,按类型分配空间内存地址返回第3页/共65页5如何读写内存中的数据?通过变量的地址访问变量所在的存储单元两种寻址方式

(1)直接(寻址)访问直接按变量地址来存取变量内容的访问方式

(2)间接(寻址)访问通过指针变量来间接存取它所指向的变量的访问方式寻址方式…...…...2000200420062002101214a的首地址2000a的首地址Pa*P第4页/共65页6指针(Pointer)的概念指针是C语言提供的一种数据类型,它只存放地址型的数据指针变量专门存放地址型数据的变量变量的指针变量的地址指针的使用原则先定义,后使用永远要清楚每个指针指向了哪里永远要清楚指针指向的位置是什么第5页/共65页7指针变量的定义指针变量定义的一般形式:

类型关键字*指针变量名例:int*p;定义了一个指针变量p,简称指针pP里保存一个地址。此时这个地址是哪呢(p指向哪呢)?指针变量初始化P=&a;*p就像普通的变量一样使用,其值是p指向的内存的内容

p可以动态地指向不同内存,从而使*p代表不同的变量&a指针P*P变量a&a第6页/共65页8定义指针变量注意以下问题

(1)变量前面的“*”不能省略。

int*ptr1,ptr2;如:(2)指针变量只能指向定义时所规定类型的变量。

(3)引用指针变量前,必须让它指向一个变量。第7页/共65页9判断对错?

inti,*p;p=&i;

int*p;float*q;p=q;inti;float*p;p=&i;int*p;p=100;指针变量只存放地址!一个指针变量不能指向与其类型不同的变量!应在类型相同的指针变量之间赋值第8页/共65页10&与*操作符

&用来取变量的地址inti,*p;

p=&i;int*p,a[10];

p=a;int*p,a[10];

p=&a[0];int*p,a[10];

p=&a[5];*用来取指针指向地址的内容inti,*p;

p=&i;

*p=0;int*p,a[10];

p=a;

*p=0;int*p,a[10];

p=&a[0];

*p=0;int*p,a[10];

p=&a[5];

*p=0;第9页/共65页11指针的指向

指针指向非其定义时声明的数据类型,将引起warningVoid*类型的指针可以指向任意类型的变量指针在初始化时一般常用*p=NULL;NULL表示空指针,即无效指针但它只是逻辑上无效,并不是真正地无效避免指针变量非法引用如果指针指向一个非你控制的内存空间,并对该空间进行访问,将可能造成危险inti;float*p;p=&i;使用时强制类型转换例

char*p1;void*p2;p1=(char*)p2;第10页/共65页12例main(){inti=10;int*p;

*p=i;printf("%d",*p);}危险!例

main(){inti=10;int*p;

p=&i;*p=20;printf("%d",*p);}指针变量p…...…...2000200420062005整型变量i10200120022003随机第11页/共65页13指针与其它类型变量的对比

共性在内存中占据一定大小的存储单元先定义,后使用特殊性它的内容只能是地址,而不能是数据必须初始化后才能使用,否则指向不确定的存储单元只能指向同一基类型的变量可参与的运算:加、减一个整数,自增、自减、关系、赋值第12页/共65页14指针运算(1)

算术运算

int*p,a[10];p=a;p++;/*p的值增加多少?*/6000600160026003600460056006pp+1指针的加减运算是以其指向的类型的字长为单位的第13页/共65页15指针运算(2)

int*p,*q,a[10];

p=a;

q=&a[5];q–p其值为5,代表差5个int字长q=p+3;指针运算不能乱算一般只进行指针和整数的加减运算,同类型指针之间的减法运算其它运算,比如乘法、除法、浮点运算、指针之间的加法等,并无意义,所以也不支持第14页/共65页16指针运算(3)

关系运算(1)只有指向同一种数据类型的两个指针才能进行关系运算,值为1或0

p>qp<qp==q(2)指针不与非指针量进行比较,但可与NULL(即0值)进行等或不等的关系运算,判断p是否为空指针

P==NULLp!=NULL第15页/共65页17赋值运算指针在使用前一定要赋值为指针变量赋的值必须是一个地址main(){

int*p; scanf("%d",p);…}main(){

inta,*p=&a;scanf("%d",p);…}指针运算(4)

第16页/共65页18指针与函数

指针既然是数据类型,自然可以做函数的参数和返回值的类型指针做参数的经典例子:两数的互换第17页/共65页19例7.1:编写函数实现两数的互换voidSwap(int*x,int*y){inttemp;temp=*x;*x=*y;*y=temp;}main(){inta,b;a=15;b=8;Swap(&a,&b);printf("a=%d,b=%d",a,b);}

voidSwap(intx,inty){inttemp;temp=x;x=y;y=temp;}main(){inta,b;a=15;b=8;Swap(a,b);printf("a=%d,b=%d",a,b);}程序1程序2主调函数被调函数实参形参结果有何不同?第18页/共65页20主调函数被调函数main(){inta,b;a=15;b=8;Swap(a,b);printf("a=%d,b=%d",a,b);}voidSwap(intx,inty){inttemp;temp=x;x=y;y=temp;}1515ab实参形参88xyab程序1xy没互换第19页/共65页21简单变量作函数参数图7-1Swap函数调用前后参数变化的示意图c)从Swap函数返回①③y

15815(b)执行Swap函数158a)调用Swap函数temp

xy

Swap函数②158main函数atempx81515tempxy

b158158aabb第20页/共65页22主调函数被调函数main(){inta,b;a=15;b=8;Swap(&a,&b);printf("a=%d,b=%d",a,b);}voidSwap(int*x,int*y){inttemp;temp=*x;*x=*y;*y=temp;}&a&a实参形参&b&bxyab程序2xy15ab8互换第21页/共65页23指针变量作函数参数图7-2用指针变量作函数参数实现两数互换函数的示意图1588&a&b&a(a)调用Swap函数

a

a

b

*x

*x

*y

y

x

x

&a

&b

main函数

Swap函数

temp15&b15(b)执行Swap函数

b

*y

y

temp②①③第22页/共65页24swap函数的几种错误形式(1/3)参数单向传递voidSwap(intx,inty){

inttemp;temp=x;/*x,y为内部变量*/x=y;y=temp;}第23页/共65页25参数单向传递voidSwap(int*p1,int*p2){

int*p;p=p1;/*p1,p2为内部变量*/p1=p2;p2=p;}swap函数的几种错误形式(2/3)第24页/共65页26指针p没有确切地址voidSwap(int*p1,int*p2){

int*p;/*指针p未初始化*/*p=*p1;*p1=*p2;*p2=*p;}swap函数的几种错误形式(3/3)第25页/共65页27例7.3打印出最高分及其学号

#include<stdio.h>#defineSIZE10voidFindMax(floatscore[],longnum[],intn,float

*pMaxScore,long

*pMaxNum)main(){ floatscore[SIZE],maxScore;inti; longnum[SIZE],maxNum; printf("Pleaseenterthenumberandscore:\n"); for(i=0;i<SIZE;i++)

{ scanf("%ld%f",&num[i],&score[i]);

} FindMax(score,num,SIZE,&maxScore,

&maxNum); printf("maxScore=%f,maxNum=%ld\n",maxScore,maxNum);}第26页/共65页28例7.3打印出最高分及其学号voidFindMax(floatscore[],longnum[],intn,float*pMaxScore,long*pMaxNum){ inti; *pMaxScore=score[0]; *pMaxNum=num[0];

for(i=1;i<n;i++) {

if(score[i]>*pMaxScore) {*pMaxScore=score[i];*pMaxNum=num[i]; } }}maxScoremaxNum&maxScorepMaxScore&maxNumpMaxNumscore[0]num[0]第27页/共65页29§7.2字符串与字符数组、字符指针字符串一串以'\0'结尾的字符在C语言中被看作字符串用双引号括起的一串字符是字符串常量,C语言自动为其添加'\0'终结符C语言并没有为字符串提供任何专门的表示法,完全使用字符数组和字符指针来处理字符数组每个元素都是字符类型的数组charstring[100];字符指针指向字符类型的指针Char*p;数组和指针可以等同看待第28页/共65页30字符指针变量与字符数组的区别定义方法不同

charstr[10];

char*ptr;赋值方法和含义不同

charstr[10];str=”china”;/*错误*/strcpy(str,”china”);/*正确*/

char*ptr;ptr=”china”;/*正确*/第29页/共65页31字符指针变量与字符数组的区别在定义一个数组时,在编译时即分配单元,有确定地址,而定义一个字符指针变量时,如未对它赋初值,则其所指数据是不定的,因而使用是危险的。

例如,输入字符串时

charstr[10];scanf("%s",str);/*正确*/char*a;scanf("%s",a);/*错误*/

应为:

char*a;charstr[10];a=str;scanf("%s",a);/*正确*/第30页/共65页32字符指针变量与字符数组的区别初始化含义不同

char*pstr=”china”;

等价于

char*pstr;

pstr=”china”;

charstr[14]=”china”;不等价于

charstr[14];

str=”china”;字符指针是变量,而数组名是地址常量第31页/共65页33例7.5字符串拷贝方法1:用字符数组编程实现/*函数功能:字符串拷贝函数参数:字符型数组srcStr,存储源字符串字符型数组dstStr,存储目的字符串函数返回值:无*/下标:01234567891011HelloChina\0HelloChina\0from[i]to[i]下标移动方向to[i]='\0'fromto结束拷贝ii++i第32页/共65页34例7.5字符串拷贝方法1:用字符数组编程实现voidMyStrcpy(chardstStr[],charsrcStr[]){

inti=0;

while(srcStr[i]!='\0') { dstStr[i]=srcStr[i]; i++; }

dstStr[i]='\0';}第33页/共65页35方法2:用字符指针编程实现/*函数功能:字符串拷贝函数参数:字符型指针srcStr,指向源字符串字符型指针dstStr,指向目的字符串函数返回值:无*/例7.5字符串拷贝HelloChina\0HelloChina\0*from*to指针移动方向指针移动方向*to='\0'tofrom++fromfromto++to第34页/共65页36方法2:用字符指针编程实现

voidMyStrcpy(char*dstStr,constchar*srcStr){

while(*srcStr!='\0') { *dstStr=*srcStr; srcStr++; dstStr++; }

*dstStr='\0';

}例7.5字符串拷贝第35页/共65页37例7.6计算实际字符个数方法1:用字符数组实现/*函数功能:计算字符串的长度函数参数:字符型数组str,存储字符串函数返回值:字符串的长度*/unsignedintMyStrlen(charstr[]){

inti

;

unsignedintlen=0;

for(i=0;str[i]!='\0';i++) { len++; }

return(len);}第36页/共65页38例7.6计算实际字符个数方法2:用字符指针实现/*函数功能:计算字符串的长度函数参数:字符型指针变量pStr,指向字符串函数返回值:字符串的长度*/unsignedintMyStrlen(char*pStr){

unsignedintlen=0;

for(;*pStr!='\0';pStr++) { len++; }

return(len);}第37页/共65页39§7.3指针与数组间的关系指针的算术运算和关系运算常常是针对数组元素;表达式中,数组名被自动转化为指向数组中第一个元素的常量指针;数组的下标运算符“[]”实际上就是以一个指针作为其操作数;(a[i],解释为*(a+i))数据元素可以通过指针来引用,指针也可用下标形式来表示。第38页/共65页40数组名就是一个指针只是不能修改这个指针的指向可以定义函数的参数为数组名指针也可当作数组名使用

int*p,a[10];

p=a;数组元素的几种等价引用形式(1)a[i](2)*(a+i)(3)p[i](4)*(p+i)60006001600260036004600560066007a[0]a[1]a[2]a[3]aa+1a+260006001600260036004600560066007a[0]a[1]a[2]a[3]app++p++指针与一维数组P+1与P++?第39页/共65页41输入输出数组的全部元素main(){

inta[10];

inti;

for(i=0;i<10;i++)scanf("%d",&a[i]);

for(i=0;i<10;i++)printf("%d",a[i]);}main(){

inta[10];

int*p,i;

for(p=a;p<(a+10);p++)scanf("%d",p);

for(p=a;p<(a+10);p++)printf("%d",*p);}方法1:下标法方法2:指针法第40页/共65页42例7.7在一个已排好序的数组中插入一个数据x,插入后数组元素保持排序关键:找到该插入的位置,然后依次移动插入位置及其后的所有元素腾出这一位置放入待插入的元素

13579a[0]a[1]a[2]a[3]a[4]a[5]插入位置pos

x=4x插入前:③

①134579x插入后:插入元素xa[0]a[1]a[2]a[3]a[4]a[5]第41页/共65页43#include<stdio.h>#defineARR_SIZE10voidInsert(inta[],intn,intx);main(){

int

a[ARR_SIZE+1],x,i,n; scanf("%d",&n);/*插入元素前数组元素的个数*/for(i=0;i<n;i++){scanf(“%d”

,&a[i]);/*输入排好序的元素*/}scanf(“%d”,&x);/*输入待插元素*/Insert(a,n,x);for(i=0;i<n+1;i++){printf(“%-4d”

,a[i]);}}

第42页/共65页44voidInseart(inta[],intn,intx){

inti,pos;

for(i=0;(i<n)&&(x>a[i]);i++) { } pos=i;

for(i=n-1;i>=pos;i--) { a[i+1]=a[i];/*向后移动*/ } a[pos]=x;/*插入元素x到位置pos*/}例7.7在一个已排好序的数组中插入一个数据x,插入后数组元素保持排序第43页/共65页45指针变量作为函数参数实现插入#include<stdio.h>#defineARR_SIZE10voidInsert(inta[],intn,intx);main(){

int

a[ARR_SIZE+1],x,i,n; int*P=NULL;

……

p=aInsert(a,n,x);

……}

voidInseart(inta[],intn,intx){

…… }第44页/共65页46删除数组中指定元素32456

删除x后:插入元素xa[0]a[1]a[2]a[3]a[4]a[5]321456a[0]a[1]a[2]a[3]a[4]a[5]待删除位置pos

x=1删除x前:①

③第45页/共65页47C语言将二维数组看作一维数组,其每个数组元素又是一个一维数组a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]aa[0]+0a+1a[1]+0a[0]+1a[0]+2&a[0][0]&a[1][0]&a[1][1]a[1]+1&a[1][2]&a[0][1]&a[0][2]a[1]+2inta[2][3];指针与二维数组

a[0][0] a[0] a[0][1] a[0][2] a[1][0] a[1] a[1][1] a[1][2]

a

第46页/共65页48一维数组a

a[1]

a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]行地址列地址列地址列地址a[0]+0a[0]+1a[0]+2a[0]+3a[2]+0a[2]+1a[2]+2a[2]+3a[1]+0a[1]+1a[1]+2a[1]+3一维数组a[2]一维数组a[1]一维数组a[0]a[0]

a[2]

a+0&a[0]

a+1&a[1]

a+2&a[2]

指针与二维数组图示第47页/共65页49a代表二维数组的首地址,第0行的地址a+i代表第i行的地址*(a+i)即a[i]

代表第i行第0列的地址*(a+i)+j即a[i]+j代表第i行第j列的地址*(*(a+i)+j)即a[i][j]代表第i行第j列的元素行地址转变成列地址指针与二维数组第48页/共65页50元素a[i][j]的地址的几种等价的引用方式&a[i][j]a[i]+j

*(a+i)+j

&(*(a+i))[j]元素a[i][j]的几种等价的引用方式a[i][j]*(a[i]+j)

*(*(a+i)+j)

(*(a+i))[j]指针与二维数组第49页/共65页51charweekDay[7][10]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};表7-1星期表的内容0Sunday1Monday2Tuesday3Wednesday4Thursday5Friday6SaturdayweekDay[0]weekDay[1]weekDay[2]weekDay[3]weekDay[4]weekDay[5]weekDay[6]Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0例7.8任意输入英文的星期几,在查找星期表后输出其对应的数字。

第50页/共65页52#include<string.h>main(){

inti,pos;

int

findFlag=0;

charx[10];

charweekDay[][10]={"Sunday","Monday","Tuesday", "Wednesday","Thursday","Friday","Saturday"}; printf("Pleaseenterastring:"); scanf("%s",x);

for(i=0;i<7&&!findFlag;i++) {

if(strcmp(x,weekDay[i])==0) { pos=i; findFlag=1; } }

if(findFlag) printf("%sis%d\n",x,pos);

else printf("Notfound!\n");}例7.8第51页/共65页53二维数组的指针——行指针定义的一般格式:类型关键字(*P)[常量N]int(*p)[3];p=a;//用行地址初始化

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

for(j=0;j<n;j++) printf("%d",*(*(p+i)+j));a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]pp++利用行列指针引用二维数组元素第52页/共65页54二维数组的指针——列指针int*p;p=*a;//用列地址初始化相对于数组起始地址的偏移量i*n+jfor(i=0;i<m;i++)

for(j=0;j<n;j++) printf("%d",*(p+i*n+j));a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]pp++利用行列指针引用二维数组元素第53页/共65页55例7.9编写一个计算任意m行n列二维数组中元素的最大值,并指出其所在的行、列下标值的函数。659787927692919094706580第54页/共65页56intFindMax(int*p,intm,intn,int*pRow,int*pCol){

inti,j,max; max=p[0]; *pRow=0; *pCol=0;

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

{

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

{

if(p[i*n+j]>max){ max=p[i*n+j]; *pRow=i; *pCol=j;} } }

return(max);}例7.9第55页/共65页57§7.4指针数组元素均为指针类型数据的数组,称为指针数组

定义形式为:

类型关键字*数组名[数组长度];例如

char*pStr[5];初始化char*pstr[]={"aa","bbb","cccccccc"};第56页/共65页58例7.10字符串按字典顺序排序方法1:用二维数组来实现char

str[N][10]={"Pascal","Basic","Fortran","Java","VisualC"};

for(i=0;i<N-1;i++) {

for(j=i+1;j<N;j++) {

if(strcmp(str[j],str[i])<0)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论