C语言程序设计案例教程(四)133



《C语言程序设计案例教程(四)133》由会员分享,可在线阅读,更多相关《C语言程序设计案例教程(四)133(133页珍藏版)》请在装配图网上搜索。
1、单击此处编辑母版文本样式,,第二级,,第三级,,第四级,,第五级,,单击此处编辑母版标题样式,,,Date:,28 November 2024,,Date:,28 November 2024,C语言程序设计案例教程,(四,),,Date:,28 November 2024,第五章C语言程序设计常用算法,,——冒泡排序,,,授课要点,冒泡排序的思想及实现,,排序算法的应用,,假设您是一位营养师,有顾客向您索取一份减肥菜谱。,,前提条件:您熟悉各种食物的热量,,,问题:保持身材之道,,列出各种食物的热量,,对各种食物的热量进行排序,,选择热量低的食物,,问题分析,,问题解决,——,冒泡排序,排序过
2、程〔假设元素存放在a[0]-a[n-1]中,按递减排序〕:,,〔1〕比较第一个数与第二个数,假设为逆序a[0]=
3、 a[j+1],位置不动;,,如果 a[j] < a[j+1],位置交换,即,,temp=a[j]; a[i]=a[j+1]; a[j+1]=temp;,,步骤3结束后 a[5-i]中的数为最小的数,,步骤4: 让i=i+1;只要i<=4就返回步骤3, 将a[5-i]的值排好。当i==5时执行步骤5,,步骤5: 输出排序结果,冒泡排序算法分析:,,#include ,,void main() /*,主函数*,/,,{,,int i, j, temp, a[6]; /*,整型变量*,/,,for (i=0; i<=5; i++) /*,键入,6,个数,放入,
4、a,数组中*,/,,{,,printf(“,请输入食物的热量,a[%d]=", i);/*,提示*,/,,scanf ("%d", /*,用键盘输入整数赋给,a[i]*/,,},,for ( i=0; i<=4; i++) /*,冒泡排序,外层循环*,/,,for ( j=0; j<=4-i; j++ ) /*,内层循环*,/,,{ /*,循环体,开始*,/,,if ( a[j] < a[j+1] ) /*,如果,a[i] > a[i+1]*/,,{,,temp = a[j]; /*,让,a[i],与,a[i+1],交换*,/,,a[j] = a[j+1];,,a[j+1]
5、= temp;,,},,} /*,循环体结束*,/,,printf(",食物按热量从高到低的顺序显示为:,\n");,,for ( i=0; i<=5; i++) /*,输出排序结果*,/,,printf("%d\n", a[i]); /*,格式输出,a[i]*/,,},,,假设将题目改为按从小到大的顺序输出,如何修改程序?,,假设排序的个数由用户指定,如何修改程序?,小组讨论并总结,,在数组排序的根底上,进一步将一个数据插入一个有序数组中。,学生进阶练习,,,a,1,a,2,,…,a,i-1,a,i,,,,…,a,n,a,1,a,2,,…,a,i-1,,…,a,i,,x,a,n,
6、数组中的元素增加,1,个,问题分析,,提示,数据初始化〔输入、排序〕,,输入待插入数据,,找到待插入位置,,将待插入位置空出,,插入数据,,输出结果,,#include ,,void main() /*,主函数*,/,,{,,int i, j, temp, a[6],x; /*,定义整型变量*,/,,for (i=0; i<=5; i++) /*,键入,6,个数,放入,a,数组中*,/,,{,,printf(",请输入待排序的数,a[%d]=", i); /*,提示*,/,,scanf ("%d", /*,用键盘输入整数赋给,a[i]*/,,},,for ( i=0
7、; i<=4; i++) /*,冒泡排序,外层循环*,/,,for ( j=0; j<=4-i; j++ )/*,内层循环*,/,,{ /*,循环体,开始*,/,,if ( a[j] > a[j+1] )/*,如果,a[i] > a[i+1]*/,,{,,temp = a[j]; /*,让,a[i],与,a[i+1],交换*,/,,a[j] = a[j+1];,,a[j+1] = temp;,,},,} /*,循环体结束*,/,,for ( i=0; i<=5; i++) /*,输出排序结果*,/,,printf("%d\n", a[i]); /*,格式输出,a[i]*/,
8、,i=0;,,printf(",请输入您要插入的整数:,\n");/*,提示*,/,,scanf("%d", /*,用键盘输入要插入的整数赋给,x*/,,while(ia[i]) /*,循环查找插入的位置*,/,,i++;,,for(j=5;j>=i;j--) /*,循环实现元素后移*,/,,a[j+1]=a[j];,,a[i]=x; /*,插入元素,x*/,,printf(",插入后的序列是:,\n");,,for ( i=0; i<=6; i++) /*,输出排序结果*,/,,printf("%d\n", a[i]); /*,格式输出,a[i]*/,,},实现,
9、,寻找你身边的一个实际问题,编写解决问题的程序,用到冒泡排序。,,例如:有N个国家参加运动会,从键盘输入代表各国运动队的国名〔国名用英文名〕和出场秩序名单,然后按出场名次从小到大的顺序输出各运动队的国名。,学以致用,,完成“学生成绩管理系统〞的“排序〞功能。,,按成绩从高到低的顺序显示,,按学号从小到大的顺序显示,,完成“学生成绩管理系统〞的“信息插入〞功能,作业,——,每人必做,,学以致用:到网上搜索资料,找出日常生活中会用到排序的例子,用,C,语言实现。例如,可以搜索一些大学图书馆的藏书量,然后按照递增或递减的顺序输出,,作业,——,小组必做,,,Date:,28 十一月 2024,第四章
10、,,模块化程序设计,,授课要点,数组元素作函数参数,,数组名作函数参数,,4,3,2,1,0,5,a,56,23,12,10,76,88,4,3,2,1,0,5,b,21,23,43,98,66,54,n=0,,m=0,,k=0,i,n=0,,m=0,,k=1,i,n=0,,m=1,,k=1,i,n=1,,m=1,,k=1,i,n=1,,m=1,,k=2,i,n=2,,m=1,,k=2,i,n=3,,m=1,,k=2,a和b为有10个元素的整型数组,,比较两数组对应元素,,变量n,m,k记录a[i]>b[i], a[i]==b[i],,,a[i]k,认为
11、数组a>b,,假设n 12、 if(,large(a[i],b[i],)==1) n=n+1;,,else if(,large(a[i],b[i],)==0) m=m+1;,,else k=k+1;,,},,,/* Output */,,},int,large(int x,int y),,{ int flag;,,if(x>y) flag=1;,,else if(x 13、个数组对应 元素的值相减后〔自定义函数实现〕显示出来〔主函数实现〕。,,2、实现两个整型变量的值的互换。〔假设两个整型变量是一个长度为2的整型数组的元素〕,,模仿1答案,,#include,,int sub(int x,int y);,,void main(),,{,,int a[]={8,9,5,8,6,4,2,8};,,int b[]={9,6,2,3,6,2,1,3};,,int result,i;,,for(i=0;i<8;i++),,{,,result=sub(a[i],b[i]);,,printf("%d\n",result);,,},,},,int sub(int x,int y 14、),,{,,return x-y;,,},,#include ,,void,swap2,(int x,,,int y,),,{ int z;,,z=x; x=y; y=z;,,},,main(),,{ int a[2]={1,2};,,,swap2(,a[0],a[1],);,,printf("a[0]=%d\na[1]=%d\n",a[0],a[1]);,,},值传递,,模仿2答案,,,1,2,a,调用前,FFAA,FFAE,,1,2,x,调用时,y,FF01,FAAC,,2,1,x,交换,y,FF01,FAAC,,1,2,a,返回,FFAA,FFAE,,授课要点,数组 15、元素作函数参数,,数组名作函数参数,,模仿1改进,,#include,,void sub(int x[],int y[],int n);,,void main(),,{,,int a[]={8,9,5,8,6,4,2,8};,,int b[]={9,6,2,3,6,2,1,3};,,sub(a,b,8);,,},,void sub(int x[],int y[],int n),,{,,int i,result;,,for(i=0;i 16、门课程总分,并将总分返回到主函数中输出。,,问题,2,解决,---,自定义函数求总分,int sum(,int,,stu[,,],,,int n,),,{ int i;,,int total=0;,,for( i=,0,; i<,n,; i++ ),,total +=,stu,[i];,,return total;,,},形参用数组定义,,,,int stu[ ],n,为数组长度,,,,#include ,,,float sum(int stu[], int n);,,void main(),,{,int score[10],, i;,,int total;,,printf("Inp 17、ut 10 scores,:,\n");,,for( i=0; i<10; i++ ),,scanf("%d", ,,total=,sum(,score,,10);,,printf(“sum is,:,%d", total);,,},int sum(,int,,stu[],, int n),,{ int i;,,int total=0;,,for( i=0; i 18、int stu[ ],,数组名作函数参数总结,地址传递,,在主调函数与被调函数分别,定义数组,,,且类型应一致,实参用,数组名,,形参用,数组定义,,形参、实参数组名是,地址变量,,,模仿练习,1、实现两个整型变量的值的互换。〔假设两个整型变量是一个长度为2的整型数组的元素〕,,2、在主函数输入8个整数保存到数组中,自定义函数对数组元素排序,并在主函数中将排序后的数组输出。,,3、在主函数输入10个整数保存到数组中,分别定义三个函数求和、平均值和最大值并返回到主函数输出。,,,1,2,a,调用前,,1,2,a,x,调用,,2,1,a,x,交换,,2,1,a,返回,#include ,,voi 19、d,swap2,(int x[],),,{ int z;,,z=x[0]; x[0]=x[1]; x[1]=z;,,},,main(),,{ int a[2]={1,2};,,,swap2(,a,);,,printf("a[0]=%d\na[1]=%d\n",a[0],a[1]);,,},地址传递,,模仿1答案,,,小组讨论并总结,数组元素作函数参数时,实参和形参间的传递方式是什么?,,数组名作函数参数时,实参和形参的写法有什么不同?,,数组元素作函数参数是,实参与形参间发生值传递。,结论,1,:,,数组名作函数参数时,实参和形参间发生地址传递;,,在主调函数与被调函数 20、分别定义数组,,,且类型应一致;,,形参数组大小,(,多维数组第一维,),可不指定,形参数组名表示,地址;,结论,2,:,,学以致用,寻找你身边的一个实际问题,用到数组名作函数参数。例如:定义一个函数,实现10个同学身高的比较,从中找出最高身高,并返回到主函数中输出。,,作业,——,每人必做,将“学生成绩管理系统〞中的“学生〞变量定义成结构体数组,学生信息的输入、输出代码做出相应的修改。,,,Date:,28 十一月 2024,第四章 模块化程序设计,,---,二维数组,,授课要点,二维数组的定义和引用,,二维数组的初始化和赋值,,二维数组的简单应用,,问题,1,:有如下表,,,在,C,程序 21、中如何表示和存储,2,4,6,8,4,8,12,16,10,12,14,18,13,15,17,19,,假定某班有,3,名学生期末考试共,5,门课程,,,要求输入每名学生各门成绩,,,计算出每名学生的总分并输出。,问题,2,,课程,,学生,C,语言,高数,英语,文化基础,体育,李军,90,75,81,95,55,陈兰,60,62,67,87,78,王芳,85,91,98,88,73,,以上两个例子有什么共同之处?,分析,:,1,、,每行,都是,4,个整数,,类型一致,,2,、,每名,学生都有,5,门课程,,成绩类型一致,,问题解决,——,二维数组,,如何定义二维数组?,,如何为数组元素赋值?, 22、,如何引用数组元素?,,二维数组的定义和引用,二维数组,——,有两个下标的数组,,类型说明符 数组名,[,常量表达式,1] [,常量表达式,2],,例如:,,int a[4][4],;,,,数组元素的存放顺序,,原因:内存是,一维,的,,二维数组:按,行,序优先,,行数,列数,元素个数,=,行数*列数,int a[3][2],a[0][1],a[1][0],a[1][1],a[2][0],a[2][1],0,1,4,5,2,3,a[0][0],a[0][0] a[0][1],,a[1][0] a[1][1],,a[2][0] a[2][1],a[0][0] 23、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[3][0] a[3][1] a[3][2] a[3][3],,二维数组理解,例,int a[3][4];,,,,,,,,2016,,17,2018,,19,2020,,21,2022,,23,2008,,9,2010,,11,2012,,13,2014,,15,2000,,1,2002,,3,2004,,5,20006,,7,a[0][0],a[0][1],a[0][2],a[0 24、][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[i],由包含,4,个元素,,的一维数组组成,二维数组,a,是由,3,个元素组成,a[0],a[1],a[2],行名,0,1,4,5,2,3,a[0][1],a[0][2],a[0][3],a[1][0],a[1][1],a[0][0],a[1][3],a[2][0],a[2][1],a[2][2],a[2][3],a[1][2],6,7,10,11,8,9,a[0],a[1],a[2],因此:二维数组中的每一行,相当于一个一维数组。或者说,,一 25、维数组是由多个简单变量组成,而二维数组是由多个一维数组组成,。,,二维数组的初始化,,二维数组元素的初始化,,分行初始化:,,,例,int a[2][3]={{1,2,3},{4,5,6}};,,,,,,,,a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],1,2,3,4,5,6,全部初始化,,,例,int a[][3]={{1},{4,5}};,,,,,,,,a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],1,0,0,4,5,0,第一维,长度省略初始化,,,例,int a[2][3]={1,2,3, 26、4,5,6};,,,,,,,,a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],1,2,3,4,5,6,全部初始化,,例,int a[2][3]={1,2,4};,,,,,,,,a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],1,2,4,0,0,0,部分初始化,,,例,int a[][3]={1,2,3,4,5};,,,,,,,,a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],1,2,3,4,5,0,第一维,长度省略初始化,,定义一二维数组,存放下表数据 27、:,模仿练习,2,4,6,8,4,8,12,16,10,12,14,18,13,15,17,19,,数组的赋值只能对数组元素单独操作,不能对数组整体操作。,,赋值的两种方式:int a[5][4];,,赋值运算符 如:a[3][0]=8;,,输入函数 如:,,for(i=0;i<5;i++),,for(j=0;j<4;j++),,scanf(“%d〞,,,单独为每个元素赋值,,对数组的整体赋值只能在初始化时进行,二维数组的赋值,,,二维数组的遍历,,数组的遍历一般用二重循环实现,,注意下标的取值范围,不能越界〔编译系统对下标的越界不做检查〕,,假定某班有,3,名学生期末考试共,5,门课程 28、,,,要求输入每名学生各门成绩,,,计算出每名学生的总分并输出。,问题,2,,#include,,void main(),,{ int a[3][6],i,j;,,for(i=0;i<3;i++),,a[i][5]=0; /*为每位学生的总分赋初值0*/,,for(i=0;i<3;i++) /*控制多少学生(多少行)*/,,{ printf("请输入第%d个学生5门课程成绩:",i+1);,,for(j=0;j<5;j++) /*控制每个学生的课程(每行的列)* 29、/,,{ scanf(“%d〞, } /*输入成绩参加总分*/,,},,printf("学号 总分\n");,,for(i=0;i<3;i++),,printf(“%3d%6d\n〞,i+1,a[i][5]); /*假设第i个学生的学号为i*/,,},问题,2,解决,—,定义,3,行,6,列的二维数组存放学生每门课程成绩和总分,每行的最后一列存放总分,,学生模仿练习,1、定义一个二维数组存放如以下图形,并输出。,,12345,,13579,,54321,,3、某班〔假设有2人〕期中考试3门成绩:,,(1)从键盘输入每个学生成绩,,(2)求每个学生的总分和平均分,,(3)按每个学生的总分求出最 30、高分,,小组讨论并总结,如何保证数组不越界?,,有二维数组,: int a[5][5];,,,其中,a[0],、,a[1],、,a[2],、,a[3],、,a[4],,表示什么?,,结论,1——,保证数组不越界,C语言编译系统并不检查数组是否越界。它只给已定义的数组元素分配内存,超过的局部那么依次往后排,至于那些位置的用途是什么,系统是不管的。读出那些单元一般不会出问题,但如果往那里面写入数据会导致不可预料的错误。,,时刻注意数组的起始元素下标值和最后元素的下标值,,结论,2——,二维数组中,a[0],、,a[1],、,a[2],、,a[3],、,a[4],表示什么?,a[0],为二维数组,a 31、,的第,1,行起始地址,,a[1],为二维数组,a,的第,2,行起始地址,,a[2],为二维数组,a,的第,3,行起始地址,,a[3],为二维数组,a,的第,4,行起始地址,,a[4],为二维数组,a,的第,5,行起始地址,,因此:二维数组中的每一行,相当于一个一维数组。或者说,一维数组是由多个简单变量组成,而二维数组是由多个一维数组组成。,,,学以致用,,寻找你身边的一个实际问题,用到二维数组。例如:编写程序实现功能:,,求一个,3×4,矩阵的所有靠外侧的元素值之和。,,设矩阵为:,3 8 9 10,,a= 2 5 -3 5,,7 0 -1 4,,,,,作业,——,每人必做,将“学生成 32、绩管理系统〞中的“学生〞变量定义成数组,学生信息的输入、输出代码做出相应的修改。,,,Date:,28 十一月 2024,第四章,,模 块 化 程 序 设 计,,授课要点,字符数组的定义及初始化,,字符串的定义及初始化,,字符串处理函数,,如何在屏幕上显示如下信息:,abcdefghij,,,问题,,字符数组的定义,,char,字符数组名称,[,字符数组的长度,],特点:字符数组的每个存储单元只能存储1个字符。,,,如: char str[10];,,那么: 数组str中可以存放10个字符。,,假设存入的字符分别为:’a’、’b’、’c’、’d’、’e’、’f’、’g 33、’、’h’、’i’、’j’,,那么这组字符在内存的存储可能如下:,a,b,c,d,e,f,g,h,i,j,str,,字符数组的初始化,与一维数组的初始化类似,我们也可以在定义字符数组的同时就对它进行赋值,即初始化。,如: char s[5]={‘a’, ‘b’, ‘c’, ‘d’, ‘e’};,,那么:数组元素在内存中的存储如下:,a,b,c,d,e,s,数组名,s,是常量,代表数组所占内存单元的首地址,,字符串的定义及初始化,字符串 是用一对双引号括起来的字符序列。双引号中可以是一个字符, 也可以是多个字符。,,在,C,中,没有专门的字符串变量,它只能通过字符数组来进行操 34、作。,可用如下形式定义一个字符串,,char str1[10]=“hello tom〞;,,字符串在内存中的表示,在,C,中,每个字符串的末尾 系统 都会自动加上一个特殊字符 ‘,\0’,, 以方便进行字符串处理。,,‘,\0’,是字符串结束标记。,如上面定义的字符串,,char str[12]=“hello tom〞;,,在内存中的存储如下:,h,e,l,l,o,,t,o,m,\0,str,数组名,str,是常量,代表数组所占内存单元的首地址,,字符串的输入与输出,1,、用,printf,和,scanf,来进行输入输出,#include ,,main,,{,,myfunc();, 35、,},myfunc(){,,char str[100];//,定义一个较大的字符数组用来存储字符串,,,,printf("Input a string:\n");,,scanf(",%s,",,str,);,,,printf("the string is:\n");,,printf(",%s,",,str,);,,},,字符串的输入与输出,2,、用,gets,和,puts,来进行输入输出,#include ,,main,,{,,myfunc();,,},myfunc(){,,char str[100];//,定义一个较大的字符数组用来存储字符串,,,,printf("Input a strin 36、g:\n");,,,gets(str);,,,printf("the string is:\n");,,,puts(str);,,},,小组讨论并总结,gets和scanf输入字符串时的差异。,,puts和printf输出字符串的差异。,,gets和scanf输入字符串时的差异,gets 是能够接收到空格的字符串,到回车字符为止;scanf,,不能接收空格,一般遇到空格或回车即停止。,,,如在执行时输入字符串“I want to learn C language well.〞,,,用gets可以接收所有字符串,,,,用scanf只能接收I。,,,故:对于字符串的处理常用字符串处理函数来操作。 37、,,puts和printf输出字符串的差异,puts,在输出字符串时,遇到’,\0’,会自动终止输出,并且将’,\0’,转换为’,\n’,来输出。,,,而,printf,在输出字符串时,遇到’,\0’,只是终止输出,并不会将’,\0’,转换为’,\n’,来输出。,,,观察以下代码的运行结果:,,void main(),,{,,char s[]="hello!";,,puts(s);,,puts(s);,,printf("%s",s);,,printf("%s",s);,,},,字符串处理函数,1,、输入函数:,gets,,,语法形式:,gets(str);,/*str,为已定义好的字符数组*, 38、/,,功能: 从键盘接收一个字符串,存储到数组,str,中,并在末尾自动添加上字符串结束标志’,\0’,。,2,、输出函数:,puts,,,语法形式:,puts(str);,/*str,为已定义好的字符数组*,/,,功能: 输出字符串,str,的内容,并将字符串结束标志’,\0’,转换成’,\n’,输出。,,模仿练习,,,从键盘输入一个字符串,输出该字符串。,,字符串处理函数,3,、求字符串长度函数:,strlen,,,语法形式:,strlen(str);,/*str,为已定义好的字符数组*,/,,功能: 求字符串,str,的有效元素的个数,不包括’,\0’,在内。,如:char 39、 str[100]=“study〞;,,int length;,,length=strlen(str);,,printf(“%d〞, length);,那么输出为:,,5,要注意字符串的长度与数组的长度的区别,,模仿练习,,从键盘输入一个字符串,求该字符串的长度。,,字符串处理函数,4,、字符串连接函数:,strcat,,,语法形式:,strcat(strSource, strTarget);,,/*strSource,和,strTarget,为已定义好的两个字符数组*,/,,功能: 将字符串,strTarget,连接,到,strSource,字符串的尾部,并在新串末尾自动添加’,\0 40、’,。,如:char strSource[100]=“study〞;,,char strTarget[20]=“C Language〞;,,strcat(strSource, strTarget);,,puts(strSource);,那么输出为:,,studyC Language,,模仿练习,,,,从键盘输入两个字符串保存到数组,a,、,b,中,将字符串,b,连接到字符串,a,的末尾。然后输出连接后的字符串。,,字符串处理函数,5,、字符串拷贝函数:,strcpy,,,语法形式:,strcpy(strSource, strTarget);,,//strSource,和,strTarget 41、,为已定义好的两个字符数组,,功能: 将字符串,strTarget,拷贝,到,strSource,字符串中。,如:char strSource[100]=“study〞;,,char strTarget[20]=“C Language〞;,,strcpy(strSource, strTarget);,,puts(strSource);,那么输出为:,,C Language,,模仿练习,,,,从键盘输入一个字符串保存到数组,a,中,定义字符串,b,,其值与字符串,a,相同。然后输出,a,、,b,两个字符串。,,字符串处理函数,6、字符串比较函数: strcmp,,语法形式: s 42、trcmp(str1, str2);,,/*str1和str2为已定义好的两个字符数组*/,,功能: 将str1与str2进行比较,假设str1大于str2,那么返回正值,假设str1与str2相等,那么返回0,假设str1小于str2,那么返回负值。,如:char str1[20]=“study〞;,,char str2[20]=“student〞;,,int result;,,result = strcmp(str1, str2);,,printf(“result=%d〞, result);,那么输出为:,,20,,模仿练习,,,,从键盘输入两个字符串保存到数组a、b中,比较这两 43、个字符串的大小。,,如果a>b,显示“a大于b〞,,如果a
44、处理函数判断用户输入的密码是否在有效长度之内。,,,Date:,28 十一月 2024,第六章 指针,,指针根底,,本章知识点,指针的概念,,,指针变量,,,指针与数组,,授课要点,指针变量的定义及使用,,变量的地址和指针,,结构体与指针,,问题1,,变量有,三要素,:,变量名、变量值、变量地址,。,,通过变量名,可以访问变量值,如果想访问该变量的地址呢?,,变量的地址存放在哪里?,,程序中,: short i;,,,,float k;,,内存中每个,存储单元,都有一个编号,-----,地址,,…...,…...,2000,2001,2002,2005,内存,0,2003,i,k, 45、编译或函数调用时为其分配内存单元,变量,是对程序中数据,,存储空间的抽象,认识指针,,指针的概念,变量的地址,:变量对应存储单元的首地址;,,指针,:即变量的地址;,,指针变量,:,专门存放变量地址的变量,即指针变量。,,变量地址与指针,,…...,2000,2004,2006,2005,短整型变量,i,1,0,2001,2002,2003,2000,,变量的,内容,,变量的,地址,指针,指针,变量地址,变量,i_pointer,指针变量,,指针变量,,,…...,…...,2000,2004,2006,2005,短整型变量,i,10,2001,2002,2003,2000,指针,,变量的, 46、内容,变量的,地址,指针变量,变量,变量地址,(,指针,),变量,值,指向,地址存入,,指针变量,变量,i_pointer,,指针变量的定义,类型说明符 *变量名;,,例如:,int *p1;,,,,对指针变量的定义包括三个内容:,,(1),指针类型说明,(,*,),,即定义变量为一个指针变量;,,(2),指针变量名,(,p1,),;,,(3),变量值,(,指针,),所指向的变量的数据类型,(,int),。,,学生模仿练习,定义整型指针变量;,,定义单精度浮点型指针变量;,,定义双精度浮点型指针变量;,,定义字符型指针变量,;,,,,问题,2,定义指针变量之后,,如何访问,该指针变量的值呢? 47、,,比照思考:,定义整型变量之后,,如何访问,该整型变量的值呢?,结论:访问变量值之前,必须先赋值。,,例,1,:如何给指针变量值?,方式一:初始化,,,int x=3;,,int *p,=&x,;,方式二:赋值语句,,int x=3;,,int *p;,,p,=&x,;,3,变量,x,2000,p,&x,p,,例,2,:将例,1,补充成完整的程序。观察指针变量的引用。,void main(),,{,,int x=3;,,int *p=,,printf(",变量值:,x=%d,p=%d\n",x,p);,,printf(",变量地址:,x=%,x,,p=%,x,\n",,&,x,p); 48、,,printf(",间接访问变量值:*,p=%d\n",x,,*p,);,,},,问题3:找人,,因为有门牌号,我们找人就有两种方法:,,直接找:由物业管理员直接带到朋友家里,,间接找:先通过物业管理员了解朋友的门牌号,然后自己找,,变量有地址,也有指向该地址的指针变量。因此,变量的访问也有两种方式,,直接访问:按照变量的地址进行存取,,间接访问:先访问变量的地址,得到变量的地址值以后再去访问该变量,,变量的访问方式,例,,i=,20,;,-----,直接访问,指针变量,,…...,…...,2000,2004,2006,2005,整型变量,x,10,变量,p,2001,2002,2003, 49、2000,3,例,*,i_pointer,=,20,;,-----,间接访问,20,按变量地址存取变量值,通过存放变量地址的变量去访问变量,i_pointer &i &(*i_pointer),,i *i_pointer *(&i),i_pointer,,=,,&i,,=,,&(*i_pointer),,i = *i_pointer = *(&i),,指针变量的引用,&,和*运算符,,*,——,指针运算符,(,间接访问运算符,),,取指针所指向的变量的内容,,&,——,取地址运算符,,取变量的地址,,,3,变量,x,2000,p,*,p,x 50、,*,p,&x,p,x=3,*,p=3,,例,3,:利用指针进行输入输出,int a;,,int *p; /*定义指针变量*/,,scanf(“%d〞, /*输入a的值*/,,p= /*将变量a的地址赋给指针变量p*/,,printf(“%d〞, *p); /*输出p的内容*/,a,b,5,2000,,2002,...,...,,3000,p,&a,,学生模仿练习,分别定义浮点数、字符型变量及其指针,并采用指针进行输入输出,,,使用指针变量,定义指针变量时应初始化或赋空值,,在,C,语言中用来表示一个空值是使用,NULL,,它是,ASCII,码值中的第一个字符,所以以下几公式等价。,, 51、P=NULL; P=’\0’;,或者,p=0;,,指针变量作为函数参数——地址传递,,特点:共享内存,“双向〞传递,void,,swap(int x,int y),,{ int temp;,,temp=x;,,x=y;,,y=temp;,,},,main(),,{ int a,b;,,scanf("%d,%d",,,swap(a,b);,,printf("\n%d,%d\n",a,b);,,},例,在内存中交换两个数,值传递,,,…...,…...,2000,2008,200A,2002,2004,2006,5,变量,a,变量,b,(main),9,运行结果:,5, 9,,v 52、oid swap(int *p1, int *p2),,{ int p;,,p=*p1;,,*p1=*p2;,,*p2=p;,,},,main(),,{ int a,b;,,int *pointer_1,*pointer_2;,,scanf("%d,%d",,,pointer_1=,,swap(pointer_1,pointer_2);,,printf("\n%d,%d\n",a,b);,,},,…...,2000,2008,200A,2002,2004,2006,200C,200E,2010,...,5,9,整型变量,a,整型变量,b,(main),指针,pointer_1,指针 53、,pointer_2,2000,2002,5,9,例,在内存中交换两个数,运行结果:,9,,,5,地址传递,,授课要点,指针变量的定义及使用,,变量的地址和指针,,结构体与指针,,定义指向结构体的指针,定义形式:,struct,结构体名 *结构体指针名,;,,例:,struct student *p;,,存放结构体变量在内存的起始地址,num,name,sex,age,stu,p,struct student,,{ int num;,,char name[20];,,char sex;,,int age;,,};,,struct student stu;,,struct 54、student *p=,,或:,,struct student *p;,,p=(struct student *)malloc(sizeof(struct student)),,通过指针引用成员变量,,例,int n;,,int *p=,,,*p,=10;,,n,=10,struct student stu1;,,struct student *p=,,stu1.num,=101,; ,(*p).num,=101,, p->num=101,结构体指针名,->,成员名,结构体变量名,.,成员名,(*,结构体指针名,).,成员名,,小组讨论 55、并总结,指针定义后为什么必须要赋值才能使用,,为什么指向变量的指针必须同变量的类型一致,,int *p;,与*,p=10,中的*有什么区别,,使用指针的意义,,结论,1——,指针定义后为什么必须要赋值才能使用?,指针如果没有赋值,那么指向一个任意的地址,如果使用没有初始化的指针,很危险,会发生一些不可预料的后果。,,结论,2——,为什么指向变量的指针必须同变量的类型一致?,指针变量用来存放地址,使用前要进行初始化,因此要知道其存放什么类型的地址。,,一个指针必须指向某一个确定的数据类型定义的变量,而不能随便更改一个指针变量所指向的数据类型。,,具体地说,一个整型指针变量只能指向一个整型变量,一 56、个实型指针只能指向一个实型变量,更不能定义一个万能型的指针变量〔void〕既可以指向一种数据类型,又可以指向另一种数据类型,,结论,3——,int *p;,与*,p=10,中的*有什么区别?,int *p,中的*表示定义指针变量,p,,*p=10,中的*表示访问指针变量,p,指向地址处存放的值,,结论,3——,使用指针的意义,使程序简洁、紧凑、高效,,有效地表示复杂的数据结构,,动态分配内存,,得到多于一个的函数返回值,,作业,——,每人必做,1.从键盘输入5个整数到动态内存区域,求出其中偶数之和。,,2. 定义一个指向“学生〞结构体的指针,通过函数malloc()为一个学生的信息分配空间, 57、通过指针为学号、姓名、4门成绩赋值并输出。,,,Date:,28 十一月 2024,第六章 指针,,---,指针与数组,,授课要点,指向数组元素的指针变量,,指针的运算,,用指针表示数组元素,,引入:数组和指针的关系,数组名,是表示数组,首地,址的,地址常量,指针变量,是存放变量,地址的变量,,指向数组元素的指针变量,例,int array[10];,,int *p;,,,p= //, p=array;,,或,int *p=,,或,int *p=array;,,array[0],array[1],array[2],array[3],array[9],...,整 58、型指针,p,&array[0],p,,授课要点,指向数组元素的指针变量,,指针的运算,,用指针表示数组元素,,指针的运算,,指针变量的赋值运算,,p= (,将变量,a,地址,p),,p=array; (,将数组,array,首地址,p),,p= (,将数组元素地址,p),,p1=p2; (,指针变量,p2,值,p1),,不能把一个整数,p,,也不能把,p,的值整型变量,如,,int i, *p;,,p=1000; (,,),,i=p; (,,),,指针的算 59、术运算,指针的算术运算:,,pi (i为整型数),,p++, p--, p+i, p-i, p+=i, p-=i等,,假设p1与p2指向同一数组,p1-p2=两指针间元素个数(p1-p2)/d,,p1+p2 无意义,,指针的算术运算,例 p指向short int型数组,且 p= 那么p+1 指向a[1],a[0,],a[1,],a[2,],a[3,],a[4,],a[5,],a[6,],a[7,],a[8,],a[9],a,数组,p,p+1,a+1,p+i,a+i,p+9,a+9,,例,int a[10];,,int 60、*p=,,p++;,,,*p=1;,,等价于,a[3]=1;,例 int a[10];,,int *p1=,,int *p2=,,那么:p2-p1=3;,,有定义:float a[10],*p=NULL; 那么:,,p=a; p、p++表示什么?,,p= p、p-3、p+3、p- - 表示什么?,,,模仿练习,,授课要点,指向数组元素的指针变量,,指针的运算,,用指针表示数组元素,,数组元素表示方法,,a[0],a[1],a[2],a[3],a[9],...,a,a+9,a+1,a+2,地址,元素,下标法,a[0,],a[1,],a[2,],,a,[,9],,a[0],a 61、[1],a[2],a[3],a[9],...,p,p+9,p+1,p,+,2,地址,元素,指针法,*,p,*(,p+1),*(,p+2),,*(,p+9),[],变址运算符,,a,[,i,],,,*(a+i),a[i], p[i] *(p+i) *(a+i),有,:int a[10],*p=a;,,有定义:float a[10],*p=NULL; 那么:,,p= *p 、*(p+1) 、*(p+3)表示什么?,,p=a; *p+1 、*(p+5)-1表示什么?,模仿练习,,用指针表示数组元素举例,1,例:定义一一维数组,从键盘输入元素值,并输出。要求用指针表示数组元素 62、,void main(),,{ int i,*p,a[7];,,p=a;,,for(i=0;i<7;i++),,scanf("%d",,p++,);,,printf("\n");,,,p=a;,,for(i=0;i<7;i++,p++),,printf("%d",,*p,);,,},指针变量可以指到,数组后,的内存单元,,用指针表示数组元素举例,2,例:输入,10,个整数,找出最大值并输出。要求用指针表示数组元素,void main(),,{ int a[10],,*p=a,*pmax=a,,i;,,for(i=0;i<10;i++),,{,,printf(",请输入第,%d,个数:, 63、",i+1);,,scanf("%d",,p++,);,,},,,p=a+1;,,for(i=1;i<10;i++,,p++,),,if(,*pmax<*p,),,pmax=p;,,printf("max=%d\n",,*pmax,);,,},,学生模仿练习,以下习题用指针方法完成:,,1,、从键盘输入一字符串,然后反序输出。,,2,、输入8个整数,找出其中最小值和最大值并输出。,,,模仿练习答案,1.,,#include,,#include ,,void main(),,{,,char str[10];,,char *p=NULL;,,gets(str);,,for(p=str+strlen 64、(str)-1;p>=str;p--),,printf("%c",*p);,,},,模仿练习答案,2.,,#include,,#include ,,int max(int *q,int n);,,void main(),,{,,int a[5],*p=a;,,int i;,,for(i=0;i<5;i++,p++),,scanf("%d",p);,,printf("max=%d",max(a,5));,,},,int max(int *q,int n),,{,,int i;,,int maxNo=*q;,,q=q+1;,,for(i=1;i 65、maxNo=*q;,,return maxNo;,,},,小组讨论并总结,1,、数组元素的表示方法有哪几种,并举例说明?,,2,、数组名和指向数组的指针有何区别?,,结论,1——,数组元素表示方法,有四种表示方法,如下:,,int a[10],*p=a;,,a[i],p[i] *(p+i) *(a+i),,它们都表示数组的第,i+1,个元素,,,结论,2——,数组名和指向数组的指针有何区别,数组名是,地址常量,,它的值不能改变,,指向数组的指针,是,指针变量,,它的值可以改变,,,作业,——,每人必做,将“学生成绩管理系统〞中的“学生〞变量定义成数组,学生信息的输入、输出代码做出相应的修改。,,
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。