已阅读5页,还剩78页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
计算机软件技术基础(6),4复杂数据类型和程序设计,本章主要内容,1.指针类型和程序设计2.数组类型和程序设计3.结构类型和程序设计4.共用体类型和程序设计5.位运算和位段6.文件7.应用程序举例,4.1指针类型和程序设计,本节主要内容指针的概念和指针的运算指针变量用作函数参数函数的指针与函数调用返回指针值的函数,4.1.1指针的概念和指针的运算,指针就是内存单元所对应的地址。每个存储单元都对应有一个地址和一个名称(如变量名)。因此,C语言中提供了两种对存储单元访问的方式:通过名称和通过变量的地址。由于在系统中内存单元的地址是用有序数来表示的,为了能够操作这些地址,C提供了一种相应的特殊变量来存放这些地址:指针变量。,1.50,1011H,1010H,a,1015H,-124,1016H,5,1018H,82,1020H,1e-3,1022H,1026H,x,c,i,j,k,y,值,地址,变量名,存储类型数据类型*指针变量名;如:char*cptr;其中,存储类型指针变量本身的存储类型,与变量一样也有四种:register、auto、static、extern;数据类型指针变量指向目标的数据类型,可以是基本数据类型,也可是构造数据类型;指针变量名用“*”引导的一个变量名。指针变量定义时若要初始化,其初值应是初始化地址值:p-;+p;-p;p=p+n;p-3;等。(2)赋值运算:可以将一个变量的地址赋给一个指针变量,也可以将一个指针变量指向的地址赋给另一个指针变量。例如:ptr=intx1,x2,y;scanf(“%d,%d”,例二指针变量与指针指向的变量指针变量和指针指向的变量是两个不相同的概念。如以下语句中:intx,*ptr;ptr=scanf(“%d,%d”,#includevoidmain()intx,y,*p1,*p2;scanf(“%d,%d”,如果输入数据为:100,300则输出结果为:100300300100,同样输入数据为:100,300则输出结果为:100300100300为什么?,将它稍作改变,程序一,程序二,swap,swap,main,main,交换对象,交换对象,4.1指针类型和程序设计,本节主要内容指针的概念和指针的运算指针变量用作函数参数函数的指针与函数调用返回指针值的函数,4.1.3函数的指针与函数调用,C程序中的一个函数就是一个程序模块,每个程序模块在内存中都要占有一片存储区,函数名则代表了这个存储区的首址(第一个地址),这个地址称为函数的入口地址。程序中如果调用这个函数,那么程序控制流程就从这个地址转移进这个函数。既然函数名代表函数的首地址,因此,可以用一个指针变量来指向它(存放这个地址)。这个指针就叫做指向函数的指针。通过这个指针就可以实现函数的调用。,由于函数的名字代表了该函数的入口地址,那么就可以定义一个变量来存放这个地址,使之指向函数的入口,这个变量就叫做函数的指针变量。函数指针变量定义的一般形式为:存储类型数据类型(*指针变量名)(形参表)其中,存储类型指定指针本身的存储类型;数据类型指针所指向的函数的返回值类型;(*指针变量名)指定指针的变量名,注意外面的括号不能省略,如果省略,所定义的就成了指针函数;形参表可以没有形参,但括号不能省略。,1.定义指向函数的指针,#includevoidswap(int*p1,int*p2)inttemp;temp=*p1;*p1=*p2;*p2=temp;voidmain()void(*fp)(int*p1,int*p2);intx,y,*pt1,*pt2;,2.用函数的指针来调用函数,fp=swap;scanf(“%d,%d”,在C语言中,由于指针可以作为函数的参数在函数间传递地址数据,而函数指针也是指针,因此理所当然地可以当作函数的参数来传递函数的地址。当然,函数指针传递地址的作用主要是将一个函数传递给另一个函数。当函数在两个函数之间传递时,主调函数所用的实参一般应是被传函数的函数名,而被调函数的形参则应是一个能接受函数地址的函数指针。这种作用常用于某些算法程序的设计中。,3.用指向函数的指针变量作函数参数,梯形积分法:将积分区间等分成若干个小区间,每个小区间用一个梯形来近似,上底和下底分别为被积函数值f(xi-1)和f(xi),斜边用过f(xi-1)和f(xi)两点的一条直线来近似,高就是等分区间的长度。这样就可以用梯形公式计算小区间的面积:于是:,举例数值积分算法及其应用,#includedoubleitg(double(*fn)(floatx),floata,floatb,intn)inti;floatf,h,s;h=(b-a)/n;s=(*fn)(a)+(*fn)(b)/2;for(i=1;in;i+)s=s+(*fn)(a+i*h);return(s*h),梯形积分算法函数,/被积函数1doublef1(floatx)floatf;f=1+x*x;returnf;/被积函数2doublef2(floatx)floatf;f=1-x+x*x;returnf;,/主函数voidmain()intn;doubley1,y2;y1=itg(f1,0.,1.,50);y2=itg(f2,0.,2.,80);printf(“%lf,%lf”,y1,y2);,4.1指针类型和程序设计,本节主要内容指针的概念和指针的运算指针变量用作函数参数函数的指针与函数调用返回指针值的函数,4.1.4返回指针值的函数,C中的函数使用后可以返回一个值,这个返回值的类型可以是整型、实型、字符型等基本类型或空类型(void)。然而,有种函数在被调用后返回的却是一个地址(指针型数据),这种函数就称为返回指针值的函数,也简称为指针函数。其定义形式为:存储类型数据类型*函数名(形参表)例如,某函数的头部定义为:float*function(floatx,floaty)则:float*表示所定义的函数是一个指向实型数据指针值;函数名为function;函数有两个实型参数x和y。,P137例4.4#includevoidmain()int*p1,*p2,*f1(inta);p1=f1(5);printf(“%dn”,*p1);p2=f1(8);printf(“%dn”,*p2);int*f1(inta)a+;return,4复杂数据类型和程序设计,本章主要内容,1.指针类型和程序设计2.数组类型和程序设计3.结构类型和程序设计4.共用体类型和程序设计5.位运算和位段6.文件7.应用程序举例,4.2数组类型和程序设计,本节要求主要内容一维数组二维数组字符数组和字符串指针和数组,4.2.1一维数组,1.一维数组的定义一维数组的定义形式为:存储类型数据类型数组名常量表达式;其中,存储类型:可以是auto(可省略)、static或extern;数据类型:指定数组元素的类型,如int、long、float等;常量表达式:指定数组元素的个数(数组长度),必须有。例如:staticinta20;定义了一个静态数组a,共有20个数组元素,都是整型。数组元素在数组中按下标顺序存放,起始元素的下标为0,最后一个元素的下标为定义数组长度值减1。,在C中,数组不能以一个整体的形式参加数据处理,只能通过对每个组元素的引用来达到处理数组的目的。因此,在实际使用中,更多的是数组元素。一维数组的数组元素引用形式为:数组名下标其中,下标可以是整型常数或表达式,如果是实型,会自动取整。例如:a0=5;x=(a3+2*b4)/a2;sacnf(“%f”,数组元素可以视为一种带下标的变量(下标变量),与和它类型相同的普通变量的使用方法相同,即,凡是能用普通变量的地方,就能使用同类型的数组元素。,2.一维数组元素的引用,在定义数组时,可以同时对数组进行初始化,其形式为:存储类型数据类型数组名常量表达式=常量表达式中的常量表达式就是数组元素赋的初始值,每个数据之间用逗号分隔;如:inta5=1,2,3,4,5;可以只对数组的部分元素初始化,如:inta10=1,2,3,4,5;只给前5个数组元素赋初值。intb10=0,2,0,4,0,6,0,8,0,10;给奇数号元素赋初值,其余元素清0。可以用初始化数据的个数定义数组的长度,如:floatx=1.0,2.2,-3.1,4.7,5.6,6.1;相当于为数组x定义了6个数组元素。未初始化的数组元素,若定义的存储类型为static或extern,则预先清0;若为auto类型,则是随机数。,3.一维数组的初始化,例一输入100个整型数据,找出其中的最大值并显示出来。#includevoidmain()intbuffer100,Max,i;for(i=0;i100;i+)scanf(%d,例二求Fibonacci数列的前20项,并按10项一行输出。#includevoidmain()intfib20=1,1,i;for(i=2;i20;i+)fibi=fibi-1+fibi-2;for(i=0;i20;i+)if(i%10=0)printf(n);printf(%5d,fibi);,结果:11235813213455891442333776109871597258441816765,例三将一维数组倒置并输出。#includevoidmain()inti,j,temp,a10=1,2,3,4,5,6,7,8,9,10;for(i=0,j=9;i=j;i+,j-)temp=ai,ai=aj,aj=temp;for(i=0;i=9;i+)printf(%4d,ai);,结果:10987654321,4.2数组类型和程序设计,本节要求主要内容一维数组二维数组字符数组和字符串指针和数组,4.2.2二维数组,1.二维数组的定义通常可以将一个矩阵定义为一个二维数组,其定义形式如下:存储类型数据类型数组名常量表达式常量表达式;例如:intarr23;就定义了一个两行三列的自动整型二维数组arr。二维数组元素的存放顺序是按行存放的,元素的下标也是从0开始。对于一个有m行n列的二维数组a,其数组元素aij的存放位置可以用式子i*n+j求得。二维以上数组元素的存放位置也可用类似方法求得。,多维数组的定义多维数组的定义也与之类似:存储类型数据类型数组名常量表达式常量表达式;例如:intbar223;定义的就是一个三维数组。其存放顺序为:,附加说明,二维数组元素的表示形式为:数组名下标下标与一维数组元素一样,它们也是下标变量,可以与普通变量同等使用。例如:a01=10;a21=a12*b23;又如:intx43;for(i=0;i4;i+)for(j=0;j3;j+)scanf(“%d”,2.二维数组元素的引用,二维及多维数组的初值可用两种方式赋给:(1)分行赋给如:intarr23=1,2,3,4,5,6;(2)顺序赋给如:intarr23=1,2,3,4,5,6;当然,与一维数组一样,也可以对部分数组元素赋初值,但要注意所赋元素的位置。如:inta34=1,3;就只给第一行第一列的元素和第三行第一列的元素赋了初值。多维数组也可根据所赋初值来定义数组元素个数,但省略的维说明只能是第一维。如:intb23=1,1,1,2,2,2,3,3,3,4,4,4;根据赋初值个数,定义的数组应为b223。,3.二维数组的初始化,例一将一个二维数组的行和列交换存到另一数组中,并输出。#includevoidmain()inta34=1,2,3,4,5,6,7,8,9,10,11,12;intb43,i,j;printf(“原始数组:n”);for(i=0;i3;i+)for(j=0;j4;j+)printf(“%5d”,aij);bji=aij;printf(“n”);printf(“交换数组:n”);for(i=0;i4;i+)for(j=0;j3;j+)printf(“%5d”,bij);printf(“n”);,原始数组:123456789101112,交换数组:159261037114812,例二求一个34矩阵和一个43矩阵的乘积,并输出结果。#includevoidmain()inta34=1,2,3,4,5,6,7,8,9,10,11,12;intb43=12,11,10,9,8,7,6,5,4,3,2,1;intc33,i,j,k;for(i=0;i3;i+)for(j=0;j3;j+)cij=0;for(k=0;k4;k+)cij+=aik*bkj;for(i=0;i3;i+)for(j=0;j字符串2;等于0表示两个字符串相等;小于0表示字符串1字符串2。例如:r=strcmp(“changcheng”,“changhe”);得到的r=-5,表示“changcheng”*(p+i)/*(p+i)相当于aiminv=*(p+i);printf(MIN=%d,minv);,例4.15(P152)找出数据序列中的最小值。,#includeintsum(inta,intn)inti,s=1;for(i=0;in;i+)s+=ai;returns;voidmain()intk,m,x80;scanf(“%d”,2.数组名作函数参数,数组名可以作函数的形参和实参。作形参时,通常不定义其元素个数。元素的个数由调用他的实参来决定。作实参时,只需将类型一致的实参数组名对应于形参数组位置即可。如果将实参写成数组元素,则实参数组的传递从该数组元素的位置开始。在函数调用时,形参数组与实参数组共享存储单元。,p是一个变量,其存储单元中的值可以随时改变。因此有:p+;p=p+3;等。a是一个数组名,就代表数组的首地址,这个地址不能改变。因此,不能有:a+;a=a+3;等。,思考,指针p与数组名a在本质上有何不同?,找出二维数组中的最大元素值。#includeintmax(inta4)inti,j,m=a00;for(i=0;im)m=aij;returnm;voidmain()intb34=12,23,8,1,10,55,36,21,9,17,11,5;printf(“Max=%dn”,max(b);,二维数组作形参时,数组的高维可以省略。例如:,该程序的弱点是只能找34数组的,不具通用性。,找出二维数组中的最大元素值。#includeintmax(inta,intn)inti,m=a0;for(i=1;im)m=ai;returnm;voidmain()intb34=12,23,8,1,10,55,36,21,9,17,11,5;printf(“Max=%dn”,max(b,3*4);,一维数组作形参时,实参可以用二维数组。例如:,该程序的功能与上一个程序相同,但具有通用性。,#includevoidreverse(inta,intn)inti,temp;for(i=1;in/2;i+)temp=ai;ai=an-1-i;an-1-i=temp;voidmain()intb=1,2,3,4,5,6,7,8,9,10,i;reverse(b,10);for(i=0;i10;i+)printf(“%4d”,bi);,例一将一维数组元素顺序倒置。,函数reverse并没有返回任何值。倒置后的b数组值是通过与形参数组a共享存储单元得到的。,#includevoidreverse(inta,intn)inti,temp;for(i=1;in/2;i+)temp=ai;ai=an-1-i;an-1-i=temp;voidmain()intb=1,2,3,4,5,6,7,8,9,10,i;reverse(b4,6);for(i=0;i10;i+)printf(“%4d”,bi);,例二只向形参传递部分数组元素。,函数reverse接受的只有b数组的后6个元素。a数组只对接受的元素进行倒置。,如果要倒置前5个元素又该怎么办?,#includevoidsort(inta,intn)inti,j,temp;for(i=0;iaj+1)temp=ai,ai=aj,aj=temp;voidmain()inti,n,a100;scnaf(“%d”,例三将一维整型数组从小到大排序。(冒泡法),说明,冒泡法的实现过程,原始数据:445682356345985729999a0a1a2a3a4a5a6a7a8a9循环:i控制比较轮数(9轮),j控制每轮比较的次数,逐轮减少。第1轮(i=0):第1次(j=1):445682356345985729999第2次(j=2):445682356345985729999第3次(j=3):448562356345985729999第4次(j=4):448235656345985729999第5次(j=5):448235656345985729999第6次(j=6):448235656345985729999第7次(j=7):448235656934585729999第8次(j=8):448235656934585729999第9次(j=9):448235656934528579999第2轮(i=1):第1次(j=2):448235656934528579999第2次(j=3):844235656934528579999,#includevoidsort(inta,intn)inti,j,temp;for(i=0;iaj)temp=ai,ai=aj,aj=temp;voidmain()inti,n,a100;scnaf(“%d”,例三将一维整型数组从小到大排序。(交换法),说明,交换法的实现过程,原始数据:445682356345985729999a0a1a2a3a4a5a6a7a8a9循环:i控制比较轮数(9轮),j控制每轮比较的次数,逐轮减少。第1轮(i=0):第1次(j=1):445682356345985729999第2次(j=2):856442356345985729999第3次(j=3):856442356345985729999第4次(j=4):856442356345985729999第5次(j=5):856442356345985729999第6次(j=6):856442356345985729999第7次(j=7):856442356345985729999第8次(j=8):256442356345985789999第9次(j=9):256442356345985789999第2轮(i=1):第1次(j=2):244562356345985789999第2次(j=3):223564456345985789999,3.二维数组的指针表示法,一个二维数组arr由若干个名字分别为:arr0,arr1,arr2,arri,的一维数组组成。在C语言中,规定一维数组名代表数组的首地址,有下式:arri=p=a;那么,指针p就指向了数组a。这样,在一般情况下,就可以用指针p来代替数组a对字符串进行处理。例如:gets(p);puts(p);scanf(“%s”,p);printf(“%sn”,p);也可以用该指针指向各字符元素,例如:pi等价于aip+3等价于a+3*(p+3)等价于*(a+3)或a3,5.字符串和指针,(1)字符串指针定义后,必须指向一个确定的对象,不能悬空。例如:charc20,*ptr;ptr=c;(2)字符串指针在定义时可以初始化。例如:char*ptr=“Chongqing”;(3)字符串指针在定义后仍可以赋值。例如:char*p;p=“Heisastudent.”;但字符数组不能这样赋值。(4)字符串的指针可以移动到字符串中的任何位置。如:chara=“Heisastudent.”,*p=a;p=p+8;则:puts(p);puts(a+8);puts(输出的内容相同。,字符串指针使用规则,#includevoidstrlink(char*ptr1,char*ptr2)while(*+ptr1);/直到*+ptr1为0while(*ptr1+=*ptr2+);/直到*ptr2为0voidmain()charstr180=“abcde”,*str2=“12345”;strlink(str1,str2);puts(str1);,例:用字符指针处理字符串。连接两个字符串。,说明,一组相关的同类型数据可以构成一个数组,同样,一组指向相同数据类型的相关指针也可以将其构成一个指针数组。指针数组中的每一个元素都是指针,其定义的一般形式为:存储类型数据类型*数组名常量表达式;例如:char*name10;就定义了一个有10个指针元素的一维指针数组,其中的每一个元素都是指向一个字符串的指针。与一般数组一样,指针数组也可以在定义时初始化,如:char*name=“Pascal”,“Fortran”,“Basic”,“C+”;由于字符型指针指向的是一个字符串,指针数组中的每个元素各自指向不同的字符串,其长度可以不同。而一个字符串又相对于一个一维字符数组。因此,一个一维字符指针数组相当于一个二维字符数组,且每一行可以不等长。,6.指针数组,#include#includevoidssort(char*a,intn)inti,j,k;char*p;for(i=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高标准农田管护协议(合同)修订版解读2025
- 曲艺家协会季度艺术研讨工作计划
- 治疗马腿方案
- 网络著作权刑事司法保护的实践思考
- 浙江省畜禽养殖业废水污染特征及环境风险评估研究-叶红玉
- 皮具研究报告皮具项目商业计划书(2025年)
- 提高生产能力的生产扩展策划方案
- 音乐推广创业项目计划书
- 新零售业态线上线下融合营销模式创新方案设计
- 某市物联网应用平台建设设计方案
- 【九牧卫浴公司考评制度问题及完善对策(6000字论文)】
- 科研伦理与学术规范课后习题
- 危险废物库房建设项目竣工环保验收监测调查报告
- (高立牌)SC型施工升降机说明书
- 中医基础理论-初级课件
- 失智失能老年人的睡眠照护(失智失能老人健康照护课件)
- (高清版)DZT 0342-2020 矿坑涌水量预测计算规程
- 中医经络养生拍打
- 人教新版英语五年级上册《UNIT4第二十二课》课件
- 血液透析患者血清白蛋白变化及其临床意义分析
- 佛教对中国社会的影响和变革
评论
0/150
提交评论