
教学课件·C语言程序设计教程.ppt
519页学时安排n总学时:64学时n周学时:4学时n理论教学:32学时n实践教学:32学时n课程类型:必修课(期中、期末均上机考试)n 平时:期中:期末=40:20:40n注意:每旷课一次从成绩中扣除6分,每迟到或早退一次从成绩中扣除3分C语言的学习内容nC语言的学习内容n专业技能(学什么知识)n基础语法知识、三大程序设计结构、数组、函数、指针、结构体、文件相关内容n以项目驱动形式组织学习过程n职业能力(掌握什么与职业相关的能力)n理解简单算法的编程思想并用C语言实现之n熟练掌握在VC环境下调试程序的能力n养成良好的编程习惯和编程风格n培养一定的团队协作及沟通能力怎样学习C语言n怎样学习C语言n 读、仿、改、编四字诀n多读—关键:理解程序思路n模仿—关键:复制程序思路n改写—关键:不改变程序思路,只改变思路中的某个具体步骤n编写—关键:重组思路,创造新的产品n通过小组合作,共同学习,多和别人交流,这样才能碰撞出思想的火花来n态度决定一切,增强信心,努力会使一切成为现实怎样学习C语言n怎样学习C语言n多读n大量阅读别人写的程序,代码量由小到大,初学时读简单的程序,慢慢过渡到读一些经典的算法程序。
关键是要边读边理解别人解决问题的思路,并记住这种思路n模仿n读完别人的程序后,模仿着写出同样的程序在模仿的过程中也是要根据你读程序时理解到的思路来写程序怎样学习C语言n怎样学习C语言n改写n能够比较熟练地模仿后,就可以自问自答,“如果要加一个什么功能,我应该怎么去编写程序?”、“如果要实现那个功能,应该怎么做?”等,写完后进行调试n编写n根据所掌握的一些常见编程思路,独立编写简单的程序,或者将几个简单的功能通过某种方法组合到一个程序中不断地训练这种能力,就能够写出越来越复杂的程序了编程环境•Visual C++ 6.0•Visual C++ 6.0环境使用演示–创建工作区–创建项目–创建.c源文件–编辑源代码,并保存–编译–链接–执行演示项目•演示项目一 –在屏幕上显示“你好,欢迎使用Visual C++ 6.0”字样/*本程序将在屏幕上显示本程序将在屏幕上显示“你好,欢迎使用你好,欢迎使用Visual C++ 6.0”字样字样*/#include
/*本程序将 在屏幕上显示本程序将 在屏幕上显示“你好,你好,欢迎使用欢迎使用Visual C++ 6.0”字样字样*/#include
/*本程序将从键盘上输入两个整数,计算并输出它们的乘积本程序将从键盘上输入两个整数,计算并输出它们的乘积*/#include
–后期还需要加上累加、阶乘等运算•本项目涉及的的C语言知识–数据类型–变量定义和引用–变量值的输出–变量值的输入–无参无返回值的函数–分支结构和循环结构数据类型C C数数据据类类型型基本类型基本类型构造类型构造类型指针类型指针类型空类型空类型void定义类型定义类型typedef字符类型字符类型char枚举类型枚举类型enum整整 型型实型实型单精度型单精度型float双精度型双精度型double数组数组结构体结构体struct共用体共用体union短整型短整型short长整型长整型long整型整型int数据类型–C语言的数据类型的常量表示•整型:–-999 10000 0 55•浮点型:–1.5 3.14159 7.8421–0. .25 •字符型:–‘A’ ‘B’ ‘X’ ‘m’ ‘t’ – ‘3’ ‘7’ –‘#’ ‘@’ ‘,’ ‘*’–‘\n’ ‘\0’ ‘\t’ ‘\b’变量定义和使用•变量:程序执行过程中,存储会改变值的标识符,称为变量。
•标识符的命名规则:–标识符仅由大小写英文字母、数字字符和下划线组合而成–数字不允许放在标识符的首位–系统提供的关键字不能作为标识符•标识符练习:–合法的标识符:•num x2 time_for_exec _minid Double For–不合法的标识符:•2m ttime.xy abc@ert •int for float double 变量定义和使用•变量定义 –单变量定义格式: 数据类型 变量名;–多变量定义格式: 数据类型 变量名1, 变量名2,变量名3;–注意:多个变量名之间用 逗号 隔开 •几种常用的基本数据类型的关键字:–整型:int–长整型:long–单精度浮点型:float–双精度浮点型:double–字符型:char变量定义和使用–变量定义•整型变量定义:–int a;//定义了一个整型变量a–int num1, num2;//定义了两个整型变量num1, num2•单精度浮点型变量定义:–float fNumber; //定义了一个单精度浮点型变量–float x, y, t, k; //定义了四个单精度浮点型变量 •字符型变量定义:–char cx; //定义了一个字符型变量–char m , n ,zck; //定义了三个字符型变量变量定义和使用–变量定义练习•定义两个 双精度浮点型 变量,变量名请自定•定义三个长整型变量,变量名自定•定义两个单精度浮点型变量hight和weight分别表示一个人的身高和体重变量定义和使用–变量初始化和赋值•初始化:在定义变量的同时,给变量赋相应的值。
–int s_c = 77; //定义了整型变量s_c,并赋初始值77–相当于以下两步操作:•int s_c;•s_c = 77; // = 代表赋值,并非数学上的“相等”•变量初始化练习:–修改前面的各个变量定义,对其初始化相应的值演示项目/*本程序在屏幕上本程序在屏幕上显示两个示两个变量的量的值*/#include
值替换对应的格式修饰符演示项目•演示项目详解 –几种基本数据类型对应的格式修饰符–整型:%d–长整型:%ld–单精度浮点型:%f–双精度浮点型:%lf–字符型:%c演示项目 –定义两个整型变量s_c, s_math,分别代表C语言和数学成绩,然后将其值显示在屏幕上/*本程序在屏幕上显示两个变量的值本程序在屏幕上显示两个变量的值*/#include
来演示项目 –定义两个整型变量s_c, s_math,分别代表C语言和数学成绩,从键盘上输入这两门成绩,然后将其值显示在屏幕上/*本程序在屏幕上本程序在屏幕上显示两个示两个变量的量的值*/#include
•教师提示:两个字符的分隔•字符输入输出的其它形式(getchar、putchar等)项目小结•小结本项目的知识点及技能要求–1:掌握基本数据类型及其变量的定义–2:掌握基本数据类型对应的关键字和格式修饰符–3:熟悉VC6.0的简单使用–4:掌握printf语句的灵活使用•评价总结项目完成质量及情况课后项目•编写程序达到以下要求:•1、定义两个整型变量a和b,从键盘上输入它们的值,并将其值显示在屏幕上•2、定义两个单精度浮点型变量m和n,从键盘上输入它们的值,试着计算它们的和(sum)、差(diff)、积(multi)、商(div),然后并将结果显示在屏幕上运算符目录•回顾•运算符总览•算术运算符•赋值运算符•类型转换•自加/自减运算符•关系运算符•逻辑运算符•项目小结•课后项目回顾•变量的定义和引用•printf函数的灵活使用•scanf函数的灵活使用项目导引•问题:要计算两个数的和、差、积、商,该怎么编写程序实现?•答案:需要使用C提供的算术运算符和赋值运算符运算符总览C运运算算符符算术运算符:(算术运算符:(+ - * / % ++ --+ - * / % ++ --))关系运算符:(关系运算符:(< <= == > >= !=< <= == > >= !=))逻辑运算符:((!逻辑运算符:((! && ||&& ||))位运算符位运算符 :(:(<< >> ~ | ^ &<< >> ~ | ^ &))赋值运算符:(赋值运算符:(= = 及其扩展)及其扩展)条件运算符:(条件运算符:(?:?:))逗号运算符:(逗号运算符:(, ,))指针运算符:(指针运算符:(* * & &))求字节数求字节数 :(:(sizeofsizeof))强制类型转换:(类型)强制类型转换:(类型)分量运算符:(分量运算符:(. ->. ->))下标运算符:(下标运算符:([][]))其它其它 :(:(( ) -( ) -))运算符总览•学习运算符应注意的问题:–运算符的功能–运算符的运算规则–运算符的优先级–运算数的个数–结合方向–运算结果的数据类型算术运算符•+、-、*、/、%–均是两个运算数,自左向右结合•注意:–/:•整数/整数 结果为整数,其余情况下为浮点数。
•例: 5/3结果为1, 2/5结果为0 12/5结果为2•5.0/3结果为1.666667 2/5.0结果为0.400000 •12.0/5.0结果为2.400000–%:求余运算•左右两边的运算数均只能是整数•例:7%4结果为3 8%4结果为0 7%5结果为2•7.2%3 错误算术运算符•= 是赋值运算符•赋值运算符的含义:将赋值运算符右边表达式的值送到左边变量名所代表的存储单元中如:a=b+1; x=x+1; •求值规则:赋值表达式的值就是赋值号右边表达式的值,如:a=(b=3*2)+1; •优先级:14 赋值运算符的优先级小于算术运算符,如:a=b+1;•结合性:赋值运算符的结合性是自右至左,如:int a,b=2; a=b=3;运算符实践•编写程序:从定义两个变量,从键盘输入它们的值,然后分别计算其和、差、积、商及余数,并输出结果include
(求余数 (int)这是什么玩意???这是什么玩意???//输出结果(自己用输出结果(自己用printf函数试试)函数试试)}强制类型转换•强制类型转换是要把某种类型的数据转换为其他类型–格式•(要转换成的类型)表达式–例如:想把一个int类型的值转换为float类型–int x=7;–x / 3 (结果为?)–(float) x / 3 (结果为?)–(float) (x/3) (结果为?)隐式类型转换•隐式类型转换是指系统根据运算规则,自动将某些数据类型转换为其他类型的处理方式 –隐式类型转换由下面的转换方向决定,隐式转换只能由低等级转换为高等级charintlongdoublefloat级别高级别高级别低级别低隐式类型转换•隐式类型转换是指系统根据运算规则,自动将某些数据类型转换为其他类型的处理方式 •float f,g;•int i, j; •f=5/2; //f的值为2.000000•i=3.5; //i的值为3•g=f+i; //g的值为5.000000•j=g/2; //j的值为2自加/自减运算符•++:自加运算符,每次给变量自增1•--:自减运算符,每次给变量自减1•使用格式–后缀用法: 变量++ 或 变量--–前缀用法: ++变量 或 --变量•例:–int m=9, x, y;–x=m++; (x为? m为? )–y= ++m; (x为? m为? )逗号运算符•语法: e1,e2,…,e3•求值规则:从左至右依次计算各个表达式的值,最后一个表达式的值是整个逗号表达式的值•优先级:15 最低•结合性:左结合•例1: 3+2,5-4,5*3•例2:int i=2 ,j=5 ;• j=(i =5,i +5,i *4);项目实践•按照要求完成以下程序: –1、求一元二次方程 3.2X2+2.1X-8.4=0 两个实根。
–2、求任意一元二次方程度两个实根关系运算符•>、<、>=、<=•==(等于)、!=(不等于)•关系运算符用于比较左右两侧运算数之间的关系,若满足关系,则比较结果为1(代表“真”),若不满足关系,则比较结果为0(代表“假”)•例:比较以下关系是否成立–int a=3,b=2,c=1,d,f;–a>b –(a>b)==c–b+cb–f=a>b>c•注意:C语言中连续比较可能会产生意想不到的结果–如:9>7>4的结果为0逻辑运算符•&&(与)、||(或)、!(非)•运算数分为两类:0即是“假”,非0即是“真”•运算结果亦两类:结果为真,用1表示;结果为假,用0表示•运算规则如下:aba&&ba||b!a!b真真真真真真真真假假假假真真假假假假真真假假真真假假真真假假真真真真假假假假假假假假假假真真真真逻辑运算符•逻辑运算符之间的优先级: !(最高) 、&&(次之)、||(低)•查看正面运算的优先级,用括号标识出来–a<=x && x<=b–a>b&&x>y–a==b||x==y–!a||a>b•计算下列各式的值–a=4;b=5;–!a–a&&b–a||b–!a||b–4&&0||2–5>3&&2||8<4-!0–‘c’&&‘d’逻辑运算符•逻辑短路特性:逻辑表达式求解时,并非所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符•例 a&&b&&c //只在a为真时,才判别b的值; 只在a、b都为真时,才判别 c的值•例 a||b||c //只在a为假时,才判别b的值; 只在a、b都为假时,才判别 c的值•例 a=1;b=2;c=3;d=4;m=1;n=1; (m=a>b)&&(n=c>d)项目小结•小结本项目的知识点及技能要求–1:掌握基本运算符–2:掌握简单程序编写的方法•评价总结项目完成质量及情况课后项目•编写程序达到以下要求:•1、编写程序求任意半径的圆的面积。
•2、定义一个身高变量hight和一个体重变量weight,从键盘上输入hight的值,根据公式 体重=(身高-100)计算weight的值,然后输出结果顺序结构及无参无返回值函数目录•回顾•顺序结构编程思路•计算器项目功能实现•无参无返回值函数实现计算器项目•项目小结•课后项目回顾•常用的运算符–算术运算–自加/自减运算符–关系运算符–逻辑运算符•各运算符的具体符号及运算规则?顺序结构编程思想•所有现实中的问题通过 顺序、选择(分支)、循环三种基本程序结构的不同组合,均可得到解决方案•顺序结构:顺序结构程序设计适合于只需要按照先后(从上到下)的顺序来执行语句,即可解决问题的情形顺序结构也是计算机编程中最基础的编程结构顺序结构编程思想•顺序结构编程的基本思想:–按照解决问题的先后顺序,写出每一步的语句•一个顺序结构的C程序的基本思路(四步曲)–定义变量(非常简单的问题也可能不需要定义变量)–输入某个(些)变量的值(也可能是用赋值语句直接赋值)–计算其他变量的值–输出计算结果分析讲解项目•项目一 计算长方形的面积和周长–项目构思:•从键盘上输入长方形的长和宽,然后计算面积和周长,最后将结果输出 –项目设计•(1)定义变量chang, kuang, mianji, zhouchang•(2)输入chang和kuang的值•(3)计算mianji和zhouchang的值•(4)输出mianji和zhouchang的值分析讲解项目•项目一 计算长方形的面积和周长–项目实现/*计算长方形的面积和周长*/#include
转化的公式为 f = 9(c+32)/5 –项目设计•(1)定义变量c和f•(2)输入变量c的值•(3)计算变量f的值•(4)输出结果分析讲解项目•项目二 温度转换–项目实现/*由摄氏温度转化为华氏温度*/#include
–在C语言中,需要用到函数来细化问题–项目构思:•用函数来实现简单计算器把加、减、乘、除、求余运算分别写成一个函数,然后再在main函数中调用它们,从而实现与之前一样的简单计算器 分析讲解项目•项目四 用函数来实现简单计算器–项目设计:•在C语言中,所有的函数与main函数的编程思路都是类似的•本项目 中,我们设计五个函数来分别计算和、差、积、商、求余,每个函数都遵循与main函数类似的“四步曲”编程思路•加法函数: void add( );•减法函数: void sub( );•乘法函数: void multiply( );•除法函数: void divide( );•求余函数: void remain( );分析讲解项目•项目四 用函数来实现简单计算器–函数基础•C语言中函数用下面的格式来定义:•返回值类型 函数名( 参数 );•返回值类型 是指这个函数执行完后,是否要带回一个指定值给调用它的函数(如main函数)返回值类型可以是任何已知类型,例如:–int代表返回整型数据–double代表返回双精度浮点型数据–char代表返回字符型数据 等–void代表没有返回值(就这个是特殊的)•函数名与变量名命名规则一样•括号中的东西称为参数:若括号里没有东西,就称为无参数。
•void add( )这类函数称为无参数无返回值函数分析讲解项目•项目四 用函数来实现简单计算器–项目实现•一个函数(如add函数)的实现(其他函数类似)/*加法函数的实现*/void add( ){int a, b, s;printf(“请输入两个整数:”);scanf(“%d%d”, &a, &b);s = a + b;printf(“%d + %d = %d\n”, a, b, s );}分析讲解项目–项目实现•一个函数(如add函数)的调用/*实现了加法函数的计算器*/#include
•2、分别编写无参无返回值的函数,实现从键盘上输入圆的半径,计算圆的面积和圆的周长–项目设计•计算圆的面积的函数可定义为:void mianji_circle( );•计算圆的周长的函数可定义为:void zhouchang_circle( );•3、编写无参无返回值的函数,实现从键盘上三角形的三边,计算三角形的面积–项目设计•计算三角形的面积的函数可定义为:void mianji_triangle( );•三角形面积计算方法为,若a,b,c为三边,则计算公式为:–s = ( a+b+c)/2, 面积=sqrt( s * ( s – a ) * ( s – b ) * ( s – c ) )–另外,因为用到了sqrt函数,需要在程序开头增加 #include
这种情况下,就要判断 除数是否为0,根据判断结果进行相应的处理这时要用到 分支结构出错!得不到正确结果!出错!得不到正确结果!分支结构•分支结构是三种程序设计结构中的一种•分支结构的形式–双分支结构( if – else )–单分支结构( if )–多分支结构( if – else – if 、switch)•分支结构主要是要判断条件,条件可以是关系表达式,也可以是逻辑表达式或其他任意的表达式分支结构•双分支结构( if – else )•格式: if ( e ) //e是一个表达式{A;//e为真时执行} else{B;//e为假时执行}eAB真真假假执行流程执行流程分支结构•单分支结构( if )•格式: if ( e ) //e是一个表达式{A;//e为真时执行} eA真真假假执行流程执行流程分析讲解项目•项目一项目一 修改计算器项目中的除法函数修改计算器项目中的除法函数–项目构思:•修改计算器项目中的除法函数,使其能够分辨出除数为0的情况,若除数为0,则输出“除数不能为0”的提示信息,若除数不为0,则输出正常的除式 –项目设计•(1)定义a,b变量•(2)输入a和b的值•(3)用表达式 0 == b判断b是否为0,若是,则输出错误提示,• 若不是,则输出除式分析讲解项目–项目实现—实现divide函数#include
–(提示:构成三角形的条件是 a + b > c && a + c > b && b + c > a )–用if – else 结构改写函数项目实践•项目四项目四 偶数输出偶数输出–项目构思:•从键盘上输入一个整数,若它为偶数,则输出在屏幕上,否则,不作任何处理–项目设计•(1)定义变量num•(2)输入变量num的值•(3)用 表达式 num % 2 == 0 判断num是否为偶数,若是则输出–项目实现#include
–项目设计•定义两个变量num1和num2•输入num1和num2的值•比较 num1 < num2的关系,若成立,则交换num1和num2的值(交换原理为:t= num1; num1 = num2; num2 = t; )•输出num1和num2的值–项目实现•用无参无返回值的函数编写代码–项目 运行•项目七项目七 三个数排序怎么实现?三个数排序怎么实现?•项目八项目八 四个数排序怎么实现?四个数排序怎么实现? 项目实践•项目九项目九 我及格了吗?我及格了吗?–项目构思•从键盘上输入一个0-100分的成绩,若成绩为60分以上,则输出“及格”字样,否则输出“不及格”•项目十项目十 解方程解方程–项目构思•从键盘上输入一元二次方程的三个系数,判断方程ax2+bx+c=0是否有实根,若有请计算并输出实根,若没有实根,请输出“无实根”的提示•项目八项目八 四个数排序怎么实现?四个数排序怎么实现? 项目小结•小结本项目的知识点及技能要求–1:掌握分支结构if、if-else的用法–2:了解一些简单的算法–3:掌握无参无返回值函数的使用方法•函数声明•函数定义•函数调用课后项目•定义一个flag变量,用于代表某天的天气情况,假设flag等于0时代表下雨,flag等于1时代表天晴。
请编写一个程序,从键盘上输入flag的值,若其值为0,则输出”天下大雨,请带伞“的提示,否则,输出”今天天晴,放心出门吧!“的提示•编写程序,从键盘输入一个年龄age,判断若age>=18,则输出”你已经是成人,应该规划好自己的未来“的提示,否则,输出“你还不到18,要准备学习如何规划自己了”的提示•(注意:以上均写成无参无返回值的函数形式)课后项目•写一程序,从键盘上输入一年份year(为十进制数),判断其是否为闰年闰年的条件是:能被4整除、但不能被100整除,或者能被400整除),条件表达式为: (0==year % 4 and 0 !=year % 100) || ( 0 == year % 400 )•从键盘输入x的值,求y的值并输出 3x3+x2+2x+5 (x < 0) y = x3-5x ( x >0)分支结构程序设计目录•回顾(if-else, if结构)•分支结构(if-else-if,switch结构)•if嵌套语句使用•switch语句使用•项目小结•课后项目94回顾•if-else结构if ( e ) //e是一个表达式{A;//e为真时执行} else{B;//e为假时执行}if结构if ( e ) //e是一个表达式{A;//e为真时执行}分支结构(if嵌套)•当某个问题用一个简单的if-else或if无法一次解决时,就可能要用到多次判断。
如:成绩等级问题从键盘上输入一个学生的成绩,判断其成绩所对应的级别是什么成绩和级别之间的对应关系如下表所示:•解决办法:用多个if-else嵌套起来判断各个对应关系(记住,一个if-else只能将问题一分为二)成绩成绩级别级别90--100A80--89B70--79C60--69D0--59E小于小于0或大于或大于100非法输入非法输入•if-else和if结构之间可以相互嵌套,嵌套可以出现在if分支中,也可以出现在else分支中嵌套形式可能出现以下几种:if ( e1 ){ if ( e2 ) { s1; }}else{s2;}if ( e1 ){ s1; }else{if ( e2 ) { s2; }}if ( e1 ){ if ( e2 ) { s1; }else { s2; }}else{s3;}if ( e1 ){ s1;}else{ if ( e2 ) { s2; }else { s3; }}if ( e1 ){ if ( e2 ) { s1; }}if ( e1 ){ if ( e2 ) { s1; }else { s2; }}分支结构(if嵌套)•if嵌套中要注意的问题:养成良好的编程习惯,在每个分支上加{}。
•若有的程序在嵌套分支上未加{},则嵌套的规则为:–else与最近的未与其他else配对的if进行配对–(这种法则实际上与()的匹配规则一样,只需要把if当成“(”,把else当成“)”就可以正确找到与某个else配对的if,从而正确理解整个程序的结构分支结构(if嵌套)例例:: if (a==b) if(b==c) printf(“a==b==c”); else printf(“a!=b”);修改: if (a==b) { if(b==c) printf(“a==b==c”); } else { printf(“a!=b”); }实现实现if ~ else if ~ else 正确配对正确配对方法:加方法:加{ }{ }分支结构(if嵌套)例 考虑下面程序输出结果: main() { int x=100,a=10,b=20; int v1=5,v2=0; if(amain( ) {int score;printf(“请输入一个成绩:请输入一个成绩:”);scanf(“%d”, &score);if( score < 0 || score > 100 ){printf(“非法输入非法输入\n”); }else if ( score >= 90 ){printf(“A\n”);} else if ( score >= 80 ){printf(“B\n”);}else if (score >=70 ) {printf(“C\n”);} else if (score >=60 ) {printf(“D\n”);} else {printf(“E\n”);}分析讲解项目•项目二 处理一元二次方程–项目构思:•从键盘输入一元二次方程的三个系数a、b、c,求方程的根。
考虑二次项系数是否为零和判别式正负的问题–项目设计•解决此问题的N-S流程图如下:定义变量定义变量a,b,c,x1,x2,p;输入输入a,b,c的值的值;a==0真真假假输出输出“这不是这不是一个二次方程一个二次方程!”求判别式求判别式p的值的值;p>=0真真假假求求x1,x2并输出并输出输出输出“no real root!”假假•项目二 处理一元二次方程(自己改写成函数形式)–项目实现#include
请参考程序流程图编写相应的程序项目实践•项目二 求分段函数的值–项目构思:•根据以下函数关系,对输入的每个x值,计算出y值 x y2
90分及以上为‘A’,80-89分为’B’,70-79分为’C’,60-69分为’D’,60以下为’E’ •项目二 发放奖金问题–项目构思项目构思•某企业需要发放奖金,奖金的发放要根据利润提成,其中发放原则如下:•利润低于或等于10万元时,奖金可提10%;•利润在10万到20万之间,低于10万的部分按10%提成,高于10万元的部分,可提成7.5%;•利润在20万到40万之间时,高于20万元的部分,可提成5%;•利润在40万到60万之间时,高于40万元的部分,可提成3%;•利润在60万到100万之间时,高于60万元的部分,可提成1.5%;•利润高于100万元时,超过100万元的部分按1%提成•要求用户从键盘上输入当月的利润,请设计解决问题的程序项目小结•小结本项目的知识点及技能要求–1:掌握if-else-if和switch的用法–2:进一步掌握无参无返回值函数的使用方法•函数声明•函数定义•函数调用课后项目•继续完成本PPT中的实践项目循环结构循环结构程序设计(循环结构程序设计(1))•循环结构•while语句•VC中程序的跟踪调试(1)•课堂实践课前回顾课前回顾 分支结构程序设计:从键盘输入一个整数,分支结构程序设计:从键盘输入一个整数,如果该数既能被如果该数既能被3整除又能被整除又能被5整除,输出整除,输出“yes”;否则输出;否则输出“no” 。
解决该问题的解决该问题的N-S盒图盒图定义变量n;从键盘给n赋值;真假输出“yes”输出“no”n既能被既能被3整除又整除又能被能被5整除整除课前回顾课前回顾 从键盘输入一个整数,如果该数既能被从键盘输入一个整数,如果该数既能被3整除又整除又能被能被5整除,输出整除,输出“yes”;否则输出;否则输出“no” include
如果要求输出100行呢?如果要求输出1万行呢?2、求s=1+2+3+…+10的结果如果是求s=1+2+3+…+200的结果呢?这类问题的共同点:重复做某种操作若干次这就需要用到 循环结构算法描述算法描述s=0,i=1s=s+ii=i+1s=s+ii=i+1s=s+ii=i+1s=s+ii=i+1s=s+ii=i+1s=s+ii=i+1输出s……s=s+ii=i+1s=0,i=1输出s当当i<=10时,循环时,循环执行这两执行这两条语句条语句……流程流程s=s+i;i=i+1;s=0,i=1;输出si<=10真真假假开始开始结束结束while语句语句while语句语句while(表达式表达式e1) { 语句语句s1; }s1; e1 真真假假表达式表达式e1的值为真的值为真循环体循环体s1while语句的语句的N-S图图例题例题: 求s=1+2+3+…+10 ;s=s+ii=i+1s=0,i=1输出s当当i<=10时,循环时,循环执行这两执行这两条语句条语句…… i<=10s=s+i;i=i+1;解决该问题的解决该问题的N-S图图 定义变量定义变量i,,s;; i=1,s=0; 输出输出s的值的值 例题例题: 求s=1+2+3+…+10 ;#include
就是循环条件2、、循环体循环体:在每个循环周期均要执行一次的语句序列在每个循环周期均要执行一次的语句序列如如while下用下用{ }括起来的语句序列括起来的语句序列3、、循环控制变量:循环控制变量:能够决定控制条件是真是假的量,能够决定控制条件是真是假的量,如上例中的变量如上例中的变量i一般来说,在循环体中要有改变一般来说,在循环体中要有改变循环变量的语句,使得循环条件可以为假,即循环可循环变量的语句,使得循环条件可以为假,即循环可以结束而不是无限循环(死循环)以结束而不是无限循环(死循环)while语句语句VC程序调试(程序调试(1))单步执行单步执行n 跟踪计算机依次执行每一条跟踪计算机依次执行每一条C语句的情况语句的情况n 可以跟踪变量或表达式的值可以跟踪变量或表达式的值n 快捷键:快捷键:F10单步执行调试例题单步执行调试例题 #include
从键盘输入2、、 输出输出1~~100内所有既能被内所有既能被3整除的数又能被整除的数又能被5整整除的整除的整数3、编写程序,用公式、编写程序,用公式∏∏/4=1-1/3+1/5-1/7+/4=1-1/3+1/5-1/7+……求求∏的近似值,直的近似值,直到最后一项的绝对值小于到最后一项的绝对值小于10-6为止4、求任意整数、求任意整数n(n>=2)是否为素数(素数即只能被是否为素数(素数即只能被1和自身整和自身整除的自然数)除的自然数)注意单步执行调试工具的运用注意单步执行调试工具的运用课堂实践课堂实践 5、求任意整数的所有位上的数之和,例、求任意整数的所有位上的数之和,例17865的所的所有位上的数之和为:有位上的数之和为:5+6+8+7+1,得,得276、、 解决数学积分问题求解决数学积分问题求f(x)=x2-3x+2在区间在区间[5,22]上的积分,即求上的积分,即求注意单步执行调试工具的运用注意单步执行调试工具的运用课后作业课后作业1、求、求1~~1000内所有能被内所有能被3整除的整数,所有数右对齐整除的整数,所有数右对齐((思考:如果程序额外要求每行输出思考:如果程序额外要求每行输出10个数,每屏输出个数,每屏输出20行应该怎么处理行应该怎么处理)。
2、从键盘上接收、从键盘上接收10个数,求和要求:个数,求和要求:((1)先提示)先提示“请输入第请输入第1个数:个数:” ,输入第一个数后再提,输入第一个数后再提示示“请输入第请输入第2个数个数”,依次类推;,依次类推;((2)输入完十个数后,输出十个数求和的结果输入完十个数后,输出十个数求和的结果要求:课下在计算机上调试程序,使之能得到正确结果课后作业课后作业3、把累加功能,即、把累加功能,即1+2+3+4+…+n((n从键盘从键盘上输入)添加到计算器应用程序中上输入)添加到计算器应用程序中 4、、把累乘功能,即把累乘功能,即1*2*3*4*…*n((n从键盘上输入)从键盘上输入)添加到计算器应用程序中添加到计算器应用程序中要求:课下在计算机上调试程序,使之能得到正确结果循环结构程序设计循环结构程序设计(循环结构程序设计(2))•回顾(while语句)•for语句•课堂实践课前回顾课前回顾求s=1+2+3+…+100 ;#include
for语句语句for语句语句语法:语法:for(e1;e2;e3) { 语句语句s1; }语法上要求语法上要求s1是一条语句,是一条语句,若有多条语句,必须用若有多条语句,必须用{ } ,使之成为一条复合语句,从使之成为一条复合语句,从而满足语法要求而满足语法要求 e2 e1;真真假假e3;s1;for语句执行流程语句执行流程#include
整除的整数 for语句实现语句实现#include
用用for语句语句实现实现注意用注意用单步执行单步执行调试工具跟踪循环调试工具跟踪循环语句的执行情况语句的执行情况课堂实践课堂实践 5、输入一组字符,统计其中大写、小写、、输入一组字符,统计其中大写、小写、数字的个数数字的个数 ;;6、输出所有的水仙花数(、输出所有的水仙花数(100-999之间满之间满足足n=a3+b3+c3的数,的数,n是数本身,是数本身,a、、b、、c为数为数n的百、十、个位上的数字)的百、十、个位上的数字) ;;7、(试一试)输出、(试一试)输出“九九乘法表九九乘法表” 用用for语句语句实现,注意用实现,注意用单步执行单步执行调试工具跟踪循调试工具跟踪循环语句的执行情况环语句的执行情况小结小结循环结构程序设计循环结构程序设计-for语句语句VC下的调试工具使用下的调试工具使用课后作业课后作业1、从键盘上输入一个正整数(VC下少于10,winTC下小于32767),求其各数位之和(如输入的是100254,则和为4+5+2+0+0+1,结果为12)用for语句实现 2、从键盘输入10个数,找出其中最大的数分别用while和for语句实现3、自学do-while结构。
要求:课下在计算机上调试程序,使之能得到正确结果课后作业课后作业思考:鸡免同笼问题思考:鸡免同笼问题有鸡和兔若干,统计后总共有脚有鸡和兔若干,统计后总共有脚100只,只,头有头有35个请输出所有可能的鸡个请输出所有可能的鸡-兔数量的兔数量的组合循环结构-自学内容循环结构程序设计(自学内容)循环结构程序设计(自学内容)•回顾(while、for语句)•while,for结构练习•课堂实践课前回顾课前回顾while语句语句 while(表达式表达式e1){ 语句语句s1; }s1; e1 真真假假表达式表达式e1的值为真的值为真循环体循环体s1while语句的语句的N-S图图课前回顾课前回顾for语句语句语法:语法:for(e1;e2;e3) { 语句语句s1; }语法上要求语法上要求s1是一条语句,是一条语句,若有多条语句,必须用若有多条语句,必须用{ } ,使之成为一条复合语句,从使之成为一条复合语句,从而满足语法要求而满足语法要求 e2 e1;真真假假e3;s1;for语句执行流程语句执行流程for( i=1; i<=n; i++; ) 输出输出1行行;e1表达式只执行表达式只执行一次,一般用于一次,一般用于循环变量初始化循环变量初始化e2表达式是循环条件表达式是循环条件表达式,决定是继续表达式,决定是继续循环还是终止循环循环还是终止循环e3表达式一般用于修改循环表达式一般用于修改循环变量的值,执行完循环体变量的值,执行完循环体s1后再执行后再执行e3,然后判断,然后判断e2s1是循环体,一是循环体,一般是一条复合语般是一条复合语句句真真假假e2为假,终止循环,为假,终止循环,执行后续语句执行后续语句1243While、、for语句练习语句练习在屏幕上输出如下图形:123456...其中行数由键盘输入。
i<=n i=1,count=0; 从键盘输入从键盘输入n;; i==1;; i++;输出一行(输出输出一行(输出i,输出回车),输出回车) 定义变量定义变量i,n;; 解决该问题的解决该问题的N-S图图#include
如下问题如何解决?如下问题如何解决?上例中每行只输出一个数,如果每行输出6个数,该如何解决?#include
中最大的数和最小的数,并输出它们课后作业课后作业把你的键盘想象成一个拨号盘,把你的键盘想象成一个拨号盘,编写程序,不断接收键盘按键,如果按下的编写程序,不断接收键盘按键,如果按下的是数字键,则在屏幕上显示该数字,如果不是数字键,则在屏幕上显示该数字,如果不是数字键,则不显示直到按下是数字键,则不显示直到按下#键结束程键结束程序序要求:课下在计算机上调试程序,使之能得到正确结果循环结构程序设计循环结构程序设计(循环结构程序设计(3))•回顾(for、while语句)•break语句•continue语句•综合练习•课堂实践课前回顾课前回顾循环的三要素:(1)循环条件(2)循环体(3)循环变量的控制语句C语言中,循环的几种形式:while语句for语句do-while语句问题问题 形如:形如:1121231234…的形式如果控制输出的形式如果控制输出多重循环的问题多重循环的问题多重循环解决的典型问题多重循环解决的典型问题 ((1)平面阵列输出)平面阵列输出((2)枚举问题)枚举问题((3)任意循环嵌套)任意循环嵌套((4)复杂逻辑推理)复杂逻辑推理…平面阵列输出平面阵列输出 解决问题:解决问题:1 * 12 ***123 *****1234 *******12345 *********…平面阵列输出平面阵列输出 问题分析:问题分析:((1)程序要一行一行输出,因此,需要一个循环来控制)程序要一行一行输出,因此,需要一个循环来控制总的要输出多少行总的要输出多少行((2)在每一行上,每一列输出的内容是什么,得由另一)在每一行上,每一列输出的内容是什么,得由另一个循环来控制个循环来控制形式如下:形式如下:for( row=1; row 试一次,符合条件的就留下,不符合的去掉用循环去试遍所有变量)(用循环去试遍所有变量)枚举问题枚举问题 –百钱买百鸡百钱买百鸡for(cock=0; cock<=20;cock++)//鸡翁的所有可能值鸡翁的所有可能值{ for(hen=0; hen<=33;hen++)//鸡母的所有可能值鸡母的所有可能值 { for(chick=0; chick<=100;chick+=3)//鸡雏的所有可鸡雏的所有可能值能值 { if( 条件条件 ) {输出输出cock、、hen、、chick的值的值 } } }}条件为:条件为:cock+hen+chick==100 && 5*cock+3*hen+click/3==100枚举问题枚举问题 –练习练习1、实践教材、实践教材P144思考题(思考题(3))2、求、求1!!+2!!+3!!+…+10!!3、教材、教材P147,项目训练(,项目训练(2)、()、(3)、()、(4)break语句语句•例子例子main() { int i=2; switch(i) { case 0: printf(" i=0 "); break; case 1: printf(" i=1 "); break; case 2: printf(" i=2 "); case 3: printf(" i=3 "); break; default: printf("default");} } 结果:结果:i=2 i=3switch 语句中的语句中的break功能:结束当前功能:结束当前switch的执行,转到该的执行,转到该switch语句的下一条语句执行。 语句的下一条语句执行循环语句中的循环语句中的break功能:功能:跳出跳出该该break所在的那层循环语句所在的那层循环语句,提前终止当,提前终止当前循环main() { int i; for(i=1;i<=10;i++) { printf(“%d “,i); if(i==5) break;} printf(“game over!”);} 结果:结果:12345game over!continue语句语句循环语句中的循环语句中的continuecontinue功能:功能:终止终止本轮循环本轮循环循环体语句循环体语句的执行,的执行,对于对于while语句语句:转去判断转去判断while循环条件循环条件对于对于for语句语句:转去执行表达式转去执行表达式3,再判断表达式,再判断表达式2whilewhile语句中的语句中的continuecontinue#include"stdio.h" main( ){int i=1;while(i<=10){printf(“i=%d\n",i);if(i==3)continue;printf(“circle %d\n", i);i++;}printf("over");}for语句中的语句中的continue#include"stdio.h" main( ){ int i;for(i=1;i<=10;i++){printf(“i=%d\n",i);if(i==3)continue;printf(“circle %d\n", i);}printf("over");}continue与与break#include"stdio.h" main( ){int i; for(i=1;i<=10;i++) { printf(“i=%d\n",i); if(i==3) continue; printf(“circle %d”,i);} printf("over");}#include"stdio.h" main( ){int i; for(i=1;i<=10;i++) { printf(“i=%d\n",i); if(i==3) break; } printf("over");}1、求1!+2!+3!+… +n!的结果不超过21350000的最大的n, 其中n由键盘输入。 2、百钱买百鸡问题如果只要一组解,程序该如何修改?课堂实践课堂实践while for语句的综合练习break continue语句的应用 小结小结带参带返回值函数目录目录•复习复习•自定义函数的分类自定义函数的分类•自定义函数的声明、调用、编写自定义函数的声明、调用、编写•带参带返回值函数的应用带参带返回值函数的应用•课堂练习课堂练习•课堂小结课堂小结教学目标教学目标应知应知•函数参数及返回值的概念应会应会•函数的声明•函数的定义(编写)•函数的调用本课内容本课内容•带参数有返回值函数的声明带参数有返回值函数的声明•带参数有返回值函数的定义带参数有返回值函数的定义•带参数有返回值函数的调用带参数有返回值函数的调用回顾与提问回顾与提问回顾计算器案例的主要内容回顾计算器案例的主要内容用无参无返回值函数分别完成了下述功能:用无参无返回值函数分别完成了下述功能:算术运算:加、减、乘--顺序结构算术运算:加、减、乘--顺序结构算术运算:除、求余--分支结构(考虑除数为算术运算:除、求余--分支结构(考虑除数为0))循环用法:累加、阶乘--循环结构循环用法:累加、阶乘--循环结构菜单显示:菜单显示:主函数:主函数:switch语句的应用、用死循环控制程序反复执行语句的应用、用死循环控制程序反复执行函数的类型函数的类型•函数定义基本格式返回返回值类型型函数名函数名(参数参数类型型参数名参数名)注:也可以没有参数或有两个(以上)的参数,两个以上的参数用逗号注:也可以没有参数或有两个(以上)的参数,两个以上的参数用逗号分隔,如:分隔,如:返回返回值类型型函数名函数名(参数参数类型型 参数名,参数参数名,参数类型型 参数名,参数参数名,参数类型型参数名参数名)----这是有三个参数的函数是有三个参数的函数返回返回值类型有:型有:void、、int、、double、、float、、char及其他及其他C语言中可以言中可以使用的使用的类型。 型如果是如果是void表示表示该函数无返回函数无返回值其他则表示有返回表示有返回值参数类型即型即是数据是数据类型、参数名即是型、参数名即是变量名,只是叫法不同而已量名,只是叫法不同而已函数的类型函数的类型–由返回值和参数是否有可构成以下四类函由返回值和参数是否有可构成以下四类函数数实际编程中,各种类型都可能遇到,但最常见的是有返回值实际编程中,各种类型都可能遇到,但最常见的是有返回值带参数的函数带参数的函数类型类型函数原型举例函数原型举例((1)无返回值无参数函数)无返回值无参数函数void f1( );((2)无返回值带参数函数)无返回值带参数函数void f2(char s );((3)有返回值无参数函数)有返回值无参数函数int f3( );((4)有返回值带参数函数)有返回值带参数函数**double f4( int n );无返回值无参数函数的编写思路无返回值无参数函数的编写思路与在与在main函数中函数中编程思路完全相同程思路完全相同例如:例如:计算器中的除法函数算器中的除法函数void divide( ){//第一步:定第一步:定义变量(用于量(用于输入运算数和保存入运算数和保存结果)果)//第二步:从第二步:从键盘上上输入两个运算数入两个运算数//第三步:第三步:计算两个数的除法(要用算两个数的除法(要用if语句考句考虑除数除数为0的特殊情况)的特殊情况)//第四步:第四步:输出出计算算结果果}无返回值无参数函数的调用无返回值无参数函数的调用假设在假设在mainmain函数中调用。 在其他函数中调用函数中调用在其他函数中调用也是一样的也是一样的main(){divide( ); //函数调用语句(直接调用)}有返回值有参数函数的编写思路有返回值有参数函数的编写思路与无返回值无参数函数略有不同与无返回值无参数函数略有不同返回返回值的数据的数据类型型函数名(数据函数名(数据类型型参数名参数名1 , 数据数据类型型参数名参数名2)){//函数的功能代函数的功能代码部分部分----略有不同略有不同//返回返回结果果值—--最大的不同之最大的不同之处}有返回值有参数函数的编写有返回值有参数函数的编写例例1 1:如果我们想定义一个函数,要求该函数能够实现计:如果我们想定义一个函数,要求该函数能够实现计算圆的面积,并将计算结果返回,则可将函数定义如下:算圆的面积,并将计算结果返回,则可将函数定义如下:double areaOfCircle( double radius ) double areaOfCircle( double radius ) //radius//radius表示半径表示半径{ {////根据根据radiusradius计算圆的面积计算圆的面积////返回圆的面积返回圆的面积} } 有返回值有参数函数的编写有返回值有参数函数的编写例例1 1:如果我们想定义一个函数,要求该函数能够实现计算:如果我们想定义一个函数,要求该函数能够实现计算圆的面积,并将计算结果返回,则可将函数定义如下:圆的面积,并将计算结果返回,则可将函数定义如下:double areaOfCircle( double radius ) double areaOfCircle( double radius ) //radius//radius表示半径表示半径{ {double area; //double area; //定义面积变量定义面积变量////根据根据radiusradius计算圆的面积计算圆的面积area = 3.14 * radius * radius ;area = 3.14 * radius * radius ;////返回圆的面积返回圆的面积return area;return area;} } 有返回值有参数函数的编写有返回值有参数函数的编写编写中注意的问题:编写中注意的问题:((1 1)不允许再次定义与参数名相同的变量)不允许再次定义与参数名相同的变量((2 2)参数的值是不需要在函数中输入的(因为是在调用的时)参数的值是不需要在函数中输入的(因为是在调用的时候传递过来的)候传递过来的)((3 3)在函数中一般不输出结果)在函数中一般不输出结果((4 4)函数要结束的位置必须用)函数要结束的位置必须用 returnreturn语句返回正确的值。 语句返回正确的值return return 语句的格式为:语句的格式为:return return 表达式(或常量值)表达式(或常量值); ;该表达式的值该表达式的值 应该与应该与 返回值的类型一致,否则程序就存在缺返回值的类型一致,否则程序就存在缺陷有返回值有参数函数的编写有返回值有参数函数的编写练习:根据三角形的三条边来计算其面积,并将面积返回计练习:根据三角形的三条边来计算其面积,并将面积返回计算公式为:算公式为: , ,其中其中s=(a+b+c)/2s=(a+b+c)/2函数定义如下:函数定义如下:double areaOfTriangle( double a, double b, double c) double areaOfTriangle( double a, double b, double c) //a,b,c//a,b,c分别表示三边分别表示三边{ {////根据三边计算三角形面积根据三边计算三角形面积////返回三角形面积返回三角形面积} } 有返回值有参数函数的调用有返回值有参数函数的调用假设在假设在mainmain函数中进行调用:思路如下函数中进行调用:思路如下((1 1)定义与被调用函数参数个数相同,且类型对应相同的变)定义与被调用函数参数个数相同,且类型对应相同的变量量((2 2)定义与被调用函数返回值类型一致的一个变量,用以保)定义与被调用函数返回值类型一致的一个变量,用以保存调用后的结果存调用后的结果((3 3)为每个实际参数赋值)为每个实际参数赋值((4 4)调用函数,并保存函数返回的结果)调用函数,并保存函数返回的结果((5 5)输出结果(或用结果进行其他运算))输出结果(或用结果进行其他运算)有返回值有参数函数的调用有返回值有参数函数的调用假假设在在main函数中函数中进行行调用用areaOfCircle ::main( ){double r; double result; //定定义变量量scanf( “%lf” , &r); //输入入实际参数的参数的值result = areaOfCircle( r ); //调用函数用函数printf(“面面积为::%lf\n” , result );//输出出结果果}有返回值有参数函数的调用有返回值有参数函数的调用result = areaOfCircle( r ); //调用函数用函数 main( ){//…调用前的代码调用前的代码result = areaOfCircle( r ); //调用时调用时//…调用后的代码调用后的代码 }double areaOfCircle( double radius){ //…函数的主要功能代码函数的主要功能代码return area; //使使用用return 语语句句返返回回结结果果值值}课堂练习课堂练习用带参数有返回值函数完成下列程序:n1、编写一个程序,完成三角形面积的计算。 n2、编写程序判断两个字符是否一致,并返回判断结果一致请返回1,不一致返回0.函数定义如下:int isEqual( char ch1, char ch2 ) //ch1,ch2表示两个字符,返回值用整型{//比较两个字符是否一样,如果一样结果记为整数1,否则结果记为整数0//返回结果} 更进一步更进一步n试着自己找一个例子,看能不能写成带参数有返回值的函数来解决,并编程实现之本次课小结本次课小结n函数类型n带参数有返回值函数的编写、调用作业作业1、用带参数带返回值的函数实现功能:、用带参数带返回值的函数实现功能:从键盘上输入一个整数从键盘上输入一个整数n,计算,计算n !.2、调用上面的程序,使之运行正确并掌握、调用上面的程序,使之运行正确并掌握调试过程调试过程作业作业※ 3、将计算器项目中的加、减、乘、除、求、将计算器项目中的加、减、乘、除、求余、累加、阶乘等运算均改写成带参数有返回余、累加、阶乘等运算均改写成带参数有返回值的函数,一周之内提交整个项目的源代码值的函数,一周之内提交整个项目的源代码提交形式:提交形式:((1)只需要提交计算器项目的)只需要提交计算器项目的.c源文件即可。 源文件即可2)源文件命名格式为:学号姓名计算器项目)源文件命名格式为:学号姓名计算器项目.c,例如:,例如:10000120105张三丰计算器项目张三丰计算器项目.c一维数组主要内容•一维数组的一维数组的定义定义•一维数组元素的一维数组元素的引用引用•一维数组的一维数组的初始化初始化和和赋值赋值•一维数组的一维数组的遍历遍历•一维数组元素的一维数组元素的查找查找•一维数组元素的一维数组元素的排序排序教学目标教学目标应知应知•一维数组的概念应会应会•一维数组的定义、输入、输出、查找•一维数组的排序一维数组的定义一维数组的一维数组的定义定义n定义数组的语法: int a[10];数据类型说明符 数组名[数组长度];注意:数组的空间分配是静态分配数组长度只能是常注意:数组的空间分配是静态分配数组长度只能是常量,长度不能在程序运行过程中发生变化量,长度不能在程序运行过程中发生变化一维数组的一维数组的定义举例定义举例int a[ ];#define SIZE 100float b[SIZE];int n=10;char c[n];int 2a[10];错误,没有指明数组的大小错误,没有指明数组的大小int a[10];正确正确 ,,SIZE是常量,相当是常量,相当于于 float b[100];错误,数组的大小不能是变量,错误,数组的大小不能是变量,应为应为 int a[10];错误,数组名错误,数组名2a 不符合标识符的不符合标识符的命名规则命名规则一维数组元素的一维数组元素的引用引用n数组就是一组变量的集合,数组就是一组变量的集合,每个数组元素相当于是一个变量每个数组元素相当于是一个变量n数组元素的表示:数组元素的表示: 数组名数组名[下标下标]如:如:int a[5];所定义的数组就是五个变量的集合,分别是:;所定义的数组就是五个变量的集合,分别是: a[0], a[1],a[2], a[3], a[4]int a[N]; 下标的取值范围:下标的取值范围:0~~N-1 ,其中,其中N为数组的大小为数组的大小下标是整型值,可以是整型下标是整型值,可以是整型常量常量、整型、整型变量变量或整型或整型表达式表达式 如:如:a[i] a[3+1] a[2*i-1]注意:下标不能越界,否则可能覆盖其他数据,造成严重后果注意:下标不能越界,否则可能覆盖其他数据,造成严重后果一维数组的一维数组的初始化初始化n定义数组之后,与普通变量一样,数组是沒有初始值的,各存储单元的值都是不定的n初始化:定义数组的同时赋初值n语法: 数据类型说明符 数组名[长度]={数值1,数值2,…}; 如 : int data[5]={1,2,3,4,5};一维数组的一维数组的初始化初始化初始化注意事项:(1) 允许初始化一部分元素,其他没有赋初值的元素初值为0; int a[5]={1,2}; 相当于 int a[5]={1,2,0,0,0};(2)允许初始化时省略数组的长度,数组的长度为赋初值的个数; int a[]={1,2,3,4,5}; 相当于 int a[5]={1,2,3,4,5}; (3)不能对整个数组初始化; int data[5]=1; 错误,应为: int data[5]={1,1,1,1,1}; 一维数组的一维数组的赋值赋值数组的赋值只能对数组元素单独操作,不能对数组整体操作。 赋值的两种方式:int a[5];1、赋值运算符 如:a[3]=8;2、输入函数 如:scanf(“%d”,&a[3]);例:a={1,3,5,7,9}; 错误,应单独为每个元素赋值例:a=1; 错误,应单独为每个元素赋值对数组的整体赋值只能在初始化时进行一维数组的遍历例:从键盘输入例:从键盘输入5个整数,保存到数组个整数,保存到数组a中;再逆序输出中;再逆序输出main(){int a0,a1,a2,a3,a4;scanf(“%d”,&a0); scanf(“%d”,&a1);scanf(“%d”,&a2);scanf(“%d”,&a3);scanf(“%d”,&a4);printf(“%d\n”,a4);printf(“%d\n”,a3);printf(“%d\n”,a2);printf(“%d\n”,a1);printf(“%d\n”,a0);}main(){int a[5];scanf(“%d”,&a[0]); scanf(“%d”,&a[1]);scanf(“%d”,&a[2]);scanf(“%d”,&a[3]);scanf(“%d”,&a[4]);printf(“%d\n”,a[4]);printf(“%d\n”,a[3]);printf(“%d\n”,a[2]);printf(“%d\n”,a[1]);printf(“%d\n”,a[0]);}例:从键盘输入例:从键盘输入5个整数,保存到数组个整数,保存到数组a中;再逆序输出。 中;再逆序输出main(){int a[5];scanf(“%d”,&a[0]); scanf(“%d”,&a[1]);scanf(“%d”,&a[2]);scanf(“%d”,&a[3]);scanf(“%d”,&a[4]);printf(“%d\n”,a[4]);printf(“%d\n”,a[3]);printf(“%d\n”,a[2]);printf(“%d\n”,a[1]);printf(“%d\n”,a[0]);}main(){int i, a[5];for(i=0;i<5;i++)scanf(“%d”,&a[i]); for(i=4;i>=0;i--)printf(“%d”,a[i]); }一维数组的一维数组的遍历遍历n数组的遍历一般用循环语句实现n注意下标的取值范围,不能越界(编译系统对下标的越界不做检查)例题:从键盘输入10个整数存放在数组中,找出其中最大的一个数,输出该最大数解法解法1:记下最大数其值:记下最大数其值main(){ { int i, max,a[10]; printf("enter data:\n"); for(i=0;i<10;i++) scanf("%d", &a[i]); max=a[0]; //假定假定a[0]的元素最大的元素最大 for(i=1;i<10;i++) if(a[i]>max) max=a[i]; printf(“最大数是最大数是%d\n", max); } 解法解法2:记下最大数相应的下标:记下最大数相应的下标main(){ { int i, max_id,a[10]; printf("enter data:\n"); for(i=0;i<10;i++) scanf("%d", &a[i]); max_id=0; //假定下标为假定下标为0的元素最大的元素最大 for(i=1;i<10;i++) if(a[i]>a[max_id]) max_id=i; printf(“最大数是最大数是%d\n",a[max_id]); } 讲解-数组名作函数参数讲解-数组名作函数参数#include include 一维数组元素的一维数组元素的查找查找例:定义一个一维数组例:定义一个一维数组num,, 再从键盘再从键盘上输入一个整数上输入一个整数x,查找数组中是否有元,查找数组中是否有元素的值与素的值与x相等如果有,输出相应的下相等如果有,输出相应的下标;如果没有,输出标;如果没有,输出“该值在数组中不存该值在数组中不存在在” 一维数组元素的一维数组元素的查找查找#include 练习题2:n从键盘上输入一串字符,存储到一个字符数组中,然后统计数组中各个英文字符的个数(统计是区分字母的大小写)课后项目-学生成绩管理系统v1.0n逐步实现学生成绩管理系统V1.0n创建一个新的项目,并建立源文件n编写输入一维数组元素的函数inputn原型:void input ( int a[ ], int n );n编写输出一维数组元素的函数outputn原型: void output( int a[ ], int n);n编写菜单函数menun原型: void menu( );n编写查找成绩x在数组中的下标的函数searchxn原型: int searchx( int a[ ] , int n, int x );n编写主函数,按照逻辑顺序调用上述函数一维数组元素的排序教学目标教学目标应知应知•知道简单的排序算法(选择法或冒泡法)应会应会•具体的排序思路及实现代码一维数组元素的一维数组元素的排序排序n排序的方法很多,主要有:选择法,冒泡法,希尔法,插入法以下解题思路均为从小到大)n选择法排序思路与实现排序过程:排序过程:((1)首先通过)首先通过n-1次比较,从次比较,从n个数中找出最小的,个数中找出最小的, 将它与第一个数将它与第一个数 交换交换—第一趟选择排序,结果最小的数被安置在第一个元素位置上第一趟选择排序,结果最小的数被安置在第一个元素位置上((2)再通过)再通过n-2次比较,从剩余的次比较,从剩余的n-1个数中找出关键字次小的记录,个数中找出关键字次小的记录, 将它与第二个数交换将它与第二个数交换—第二趟选择排序第二趟选择排序((3)重复上述过程,共经过)重复上述过程,共经过n-1趟排序后,排序结束趟排序后,排序结束分析与讲解—选择法排序例如:有如下5个整数乱序存储在数组num中,则用选择法排序的过程演示如下:(红色表示是剩下数中的最小值,蓝色表示已排好序的数)排序前: 7 3 66 90 9第一轮查找: 7 3 66 90 9 交换: 3 7 66 90 9第二轮查找: 3 7 66 90 9 交换: 3 7 66 90 9第三轮查找: 3 7 66 90 9 交换: 3 7 9 90 66第四轮查找: 3 7 9 90 66 交换: 3 7 9 66 90编写程序:将编写程序:将10个数由小到大的顺序进行排序个数由小到大的顺序进行排序#include 平均值并输出编写程序编写程序 2、从键盘输入10个整数保存到数组中,求值最小的元素,将这个值最小的元素与数组的第一个元素交换最后输出整个数组编写程序编写程序 3、从键盘输入10个浮点数保存到数组中,将这10个数逆序存放后输出项目实践项目实践在计算器项目中,添加以下功能:(1)编写函数查找数组中的最高成绩的下标getmaxid原型:int getmaxid(int a[ ], int n); (2)编写函数查找数组中的最低成绩的下标getminid原型:int getminid(int a[ ], int n);(3)编写函数将成绩按从高到低的顺序排序sort原型: void sort( int a[ ] , int n);(4) 编写函数统计成绩中各档的人数,各档分为90-100、80-89、70-79、60-69、0-59原型: void count( int a[ ], int n, int b[ ]); b数组是各档的人数,可以假设b[0]存储90-100的人数,b[1]存储80-89的人数,依此类推5)修改菜单函数,以增加对应的功能(6)修改主函数,以调用新增加的功能。 字符串及字符串函数字符串及字符串函数«字符串v字符串及其结束标志l无字符串变量,用字符数组处理字符串l字符串结束标志:‘\0’ 例 char ch[6]={“Hello”}; char ch[6]=“Hello”; char ch[]=“Hello”;用字符串常量ch[0]Helloch[1]ch[2]ch[3]ch[4]\0ch[5] 例 char ch[5]=“Boy”;ch[0]Boy\0\0用字符串常量ch[1]ch[2]ch[3]ch[4]v字符串的输入输出l逐个字符I/O: %cl整个字符串I/O: %sv字符串输入函数:lscanf函数: char st[10]; scanf(“%s”,st);说明:(1)字符串输入时无须加取地址符“&”,直接使用字符数组名即可;(2)scanf遇到空格、跳格符或回车符就认为字符串结束lgets函数: char st[10]; gets(st);说明:(1 )gets函数输入时,只有遇到回车符才认为字符串结束。 字符串v字符串输出函数:lprintf函数: printf(“%s”,st);说明:(1)输出“\0”前所有字符,输出后不自动换行lputs函数: gets(st);说明:(1 )输出“\0”前所有字符,输出后自动换行注:使用gets和puts,必须包含头文件 string.h字符串例 main( ) { char a[5]={‘H’,’e’,’l’,’l’,’o’}; printf(“%s”,a); }例 main( ) { char a[]=“Hello”; // char a[6]=“Hello”; printf(“%s”,a); }结果:Hello#-=* h e l l o02314结果:Hello用“%s”输出时,遇‘\0’结束例子main(){ char a[]={'h','e','l','\0','l','o','\0'}; printf("%s",a);}例子输出:hel h e l \0 l o \0数组中有多个‘\0’时,遇第一个结束例 字符串输入举例 H o w \0 a r e \0 y o u ? \0 #include 出•在一个在一个4×6的实型二维数组中,将各行前的实型二维数组中,将各行前5列元素的平均值分别放在同一行的第列元素的平均值分别放在同一行的第6列上编写程序编写程序–写程序:写程序: 编写一个程序统计某班编写一个程序统计某班3门课程的成绩,它们是语文、数门课程的成绩,它们是语文、数学和英语先输入学生人数,然后按照从小到大的编号顺学和英语先输入学生人数,然后按照从小到大的编号顺序依次输入学生成绩,最后统计每门课程全班的总成绩、序依次输入学生成绩,最后统计每门课程全班的总成绩、平均成绩以及每个学生课程的总成绩和平均成绩平均成绩以及每个学生课程的总成绩和平均成绩变量的存储属性变量的存储属性变量的存储属性–概述•变量是对程序中数据的存储空间的抽象内存…….main(){ int a; a=10; printf(“%d”,a);}编译或函数调用时为其分配内存单元1020002001程序中使用变量名对内存操作•变量的属性–数据类型:变量所持有的数据的性质(操作属性)–存储属性»存储器类型:静态存储区、动态存储区»生存期:变量在某一时刻存在-------静态变量与动态变量»作用域:变量在某区域内有效-------局部变量与全局变量•变量的存储类型–auto -----自动型(可省略)–static ------静态型–extern -----外部型•变量定义格式: [存储类型] 数据类型 变量表;变量的存储属性变量的存储属性n概述•变量是对程序中数据的存储空间的抽象如: int sum; auto int a,b,c; static float x,y;–局部变量与全局变量•局部变量---内部变量–定义:在函数内定义,只在本函数内有效–说明:»main中定义的变量只在main中有效»不同函数中同名变量,占不同内存单元»形参属于局部变量»可定义在复合语句中有效的变量»局部变量可用存储类型:auto static (默认为auto)运行结果:5 4 3 2 1•全局变量---外部变量–定义:在函数外定义,可为本文件所有函数共用–有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件–外部变量说明: extern 数据类型 变量表;–外部变量定义与外部变量说明不同–外部变量可用存储类型:缺省 或 static 应尽量少使用全局变量,因为:全局变量在程序全部执行应尽量少使用全局变量,因为:全局变量在程序全部执行过程中占用存储单元降低了函数的通用性、可靠性,可移植过程中占用存储单元降低了函数的通用性、可靠性,可移植性降低程序清晰性,容易出错。 性降低程序清晰性,容易出错float max,min;float average(float array[], int n){ int i; float sum=array[0]; max=min=array[0]; for(i=1;i 提供项目文档,详细说明每个功能–提出问题提出问题 :在学生成绩管理系统V1.0的基础上,如何能够做到用指针来灵活操作数组元素–引例引例:•演示交换两个数的程序swap函数,通过实际交换效果导入为什么需要用指针?指针指针–教学任务分配:根据学生成绩管理系统教学任务分配:根据学生成绩管理系统V2.0的功的功能需求,要求掌握以下各知识:能需求,要求掌握以下各知识:•指针定义、初始化、引用及指针作函数参数(2学时)•指向一维数组的指针使用(输入/输出)(2学时)•指向一维数组的指针使用(查询、排序)(2学时)•指向字符串的指针使用(2学时)•指针作函数参数应用(2学时,自学)•扩展知识:指向二维数组的指针(2学时,自学)•项目训练(课堂2学时)指针(约指针(约2学时)学时)•指针概念、定义和引用•程序分析•课堂实践•课堂小结、作业课堂目标课堂目标应知应知•了解指针的概念•掌握指针的定义和应用应会应会•指针变量的定义、引用和初始化专业英语词汇专业英语词汇英文词汇英文词汇对应的中文意义对应的中文意义pointer指针指针NULL空指针空指针&取普通变量地址取普通变量地址*取指针指向的地址取指针指向的地址中存储的值中存储的值address地址地址回顾与提问回顾与提问1.1.简单回顾一维数组的常用操作简单回顾一维数组的常用操作引入指针概念引入指针概念•数组名作函数参数的意义数组名作函数参数的意义 根据对数组的理解:数组名是一组连续存储的数据根据对数组的理解:数组名是一组连续存储的数据首个单元的地址(首地址)。 首个单元的地址(首地址) 通过这个首地址,就可以在某个函数中(如通过这个首地址,就可以在某个函数中(如input))引用另外一个函数(如引用另外一个函数(如main)中的数组的每个元素为)中的数组的每个元素为什么?什么? 因为:因为:数组名本身就是一个数组名本身就是一个“指针指针”,在,在C语言中,语言中,通过通过“指针指针”可以突破函数的界限,访问其他函数的变可以突破函数的界限,访问其他函数的变量的值分析与讲解分析与讲解p什么是指针?什么是指针? 指针,全称为指针,全称为“指针变量指针变量”,在这个变量中存储,在这个变量中存储的是内存中的另一个的是内存中的另一个变量的地址变量的地址p怎么理解?怎么理解? 通过指针,可以间接先找到某个变量的地址,从而通过指针,可以间接先找到某个变量的地址,从而再找出这个地址对应的内存单元的值(也即得到了某个再找出这个地址对应的内存单元的值(也即得到了某个变量的值)变量的值) 分析与讲解分析与讲解–指针变量的定义指针变量的定义定义形式如下:定义形式如下:数据类型数据类型 *指针变量名指针变量名;如:如: int *p1, num;表示的意思为:表示的意思为:定义了一个指针变量定义了一个指针变量p1,它可以指向的是一个,它可以指向的是一个整型数据。 或者说,这时候整型数据或者说,这时候p1中应该存储的是一个整中应该存储的是一个整型变量的地址型变量的地址 注意:指针变量定义了之后,需要给它赋一个 注意:指针变量定义了之后,需要给它赋一个确确定的变量的地址定的变量的地址,否则,就会出现严重的系统错误否则,就会出现严重的系统错误分析与讲解分析与讲解–指针变量的引用指针变量的引用#include 编写函数实现两个整型变量的交换 #include 分析swap函数交换的是什么? void swap(int *pa, int *pb); main() { int a, b; a=10; b=20; swap( &a , &b ); printf("a=%d, b=%d\n", a, b); }void swap(int *pa, int *pb) { int *temp; temp=pa; pa=pb; pb=temp; }运行结果: a=10, b=20 结论:只是交结论:只是交换了换了pa和和pb两两个指针变量的个指针变量的值,并不影响值,并不影响a和和b的值图 4 swap函数被调用时的内存分配图 图 5 swap函数调用结束时的内存分配图 例例 4 指针作函数参数 错误分析void swap(int *, int *);main() { int a, b, *p1, *p2; a=10; b=20; p1=&a; p2=&b; swap(p1, p2); printf("a=%d, b=%d\n", a, b); }void swap(int *pa, int *pb) { int *temp; *temp=*pa; *pa=*pb; *pb=*temp; } 结论:指针变结论:指针变量量temp定义后,定义后,没有赋予其值没有赋予其值为某个变量的为某个变量的地址,故地址,故*pa不不知道该存储到知道该存储到哪个内存单元哪个内存单元中。 中可以将swap函数改变成这样: void swap(int *pa, int *pb) { int *temp, t; temp=&t; *temp=*pa; *pa=*pb; *pb=*temp; }此时可以得到运行结果: a=20, b=10 小小 结结(1)当用普通变量作函数参数时,函数中无论对参数作何变化,均不会影响原来被传递过来的那个变量的值2)当用指针作函数参数时,在函数中用(*指针)的形式对参数作了修改的话,就一定会影响原来被传递过来的那个变量的值3)也就是说,用指针作为函数的参数,使我们突破了函数的界限,达到了在A函数中可以引用B函数中的变量的目的例例5:编写一个函数,求任意三个数的最大值及其平均值编写一个函数,求任意三个数的最大值及其平均值分析:如果用普通变量作函数参数,由于一个函数只能通过return语句得到一个返回值,故不能由一个函数同时得到最大值和平均值解决方法:可以通过return语句返回一个值(如最大值),另一个值(平均值)由指针作函数参数来得到。 当然,你也可以试一试,两个值均用指针作函数参数来得到)例例5:编写一个函数,求任意三个数的最大值及其平:编写一个函数,求任意三个数的最大值及其平均值include 然后在主函数中输出面积及周长2)编写一个函数,求一个圆的直径、周长和面积然后在主函数中输出直径、周长及面积 (3) 编写一个函数,将三个数按从大到小的顺序排列然后在主函数中输出排序后的三个数课堂练习(作业):课堂练习(作业):指向一维数组的指针(共指向一维数组的指针(共6学时)学时)–问题:需要从一个函数得到2-3个值,我们可以用指针变量来作函数参数,从而得到这几个值,如果需要从一个函数得到更多的值(如50个,1000个,…)该怎么办?–答案:用指向一维数组的指针数组可以存储多个值)指针使用(输入指针使用(输入/输出)(输出)(2学时)学时)•指向一维数组的指针的定义、引用•程序分析•课堂实践课堂目标课堂目标应知应知•理解指向一维数组指针的概念•理解指针指向一维数组后,如何通常指针来引用数组元素•掌握指针引用数组元素的方法应会应会•指针引用数组元素分析与讲解分析与讲解–指向一维数组的指针指向一维数组的指针n如何定义指向一维整型如何定义指向一维整型数组的指针?数组的指针?int a[8]={2};int *p;p=a;n 实质上数组名实质上数组名a就是指针,是指针常量就是指针,是指针常量n p是指针变量是指针变量n 出现出现a的地方均可以用的地方均可以用p替代。 替代指向一维数组的指针指向一维数组的指针–记住下面的用法:记住下面的用法:当指针当指针p指向了数组指向了数组a的首地址后,有下面的几个等价关的首地址后,有下面的几个等价关系:系:i=0,1,2,…,n-1, n为数组为数组a中元素个数中元素个数((1)地址等价:)地址等价:p+i a+i &a[i]((2)元素值等价:)元素值等价:a[i] p[i] *(a+i) *(p+i)a[0] a[1] a[2] a[3] a[4] a[5] a[7] a[8]apa+4p+2p+4项目功能实现项目功能实现–一维数组元素的输入一维数组元素的输入/输出输出•输入功能讲解、实现输入功能讲解、实现•输出功能讲解、实现输出功能讲解、实现•测试输入测试输入/输出功能输出功能–函数实现输入函数实现输入/输出输出•输入函数:输入函数:void input(int *p, int n)•输出函数:输出函数:void output(int *p, int n)课堂实践课堂实践–变换数据类型,同样实现一维数组元素的输入变换数据类型,同样实现一维数组元素的输入与输出与输出–将将input函数修改为带返回值的函数,返回值为函数修改为带返回值的函数,返回值为实际输入的元素个数实际输入的元素个数,完善函数完善函数•输入函数:输入函数:int input(int *p, int n)指针使用(查询、排序)(指针使用(查询、排序)(4学时)学时)•通过指针查询数组元素•通过指针排序数组元素•程序分析•课堂实践•课堂小结、作业课堂目标课堂目标应知应知•理解指向一维数组指针的概念•理解指针指向一维数组后,如何通常指针来引用数组元素•了解指针的算术运算•掌握指针引用数组元素的方法应会应会•指针引用数组元素分析与讲解分析与讲解–例:指针编写查询程序例:指针编写查询程序假设一维数组中存放互不相同的假设一维数组中存放互不相同的10个整数,要求个整数,要求从键盘上再输入另一个整数,查找与该值相同的从键盘上再输入另一个整数,查找与该值相同的数组的元素,如果存在,输出其下标值,否则,数组的元素,如果存在,输出其下标值,否则,输出不存在提示信息。 输出不存在提示信息定义数组定义数组a[10],指针,指针p,整数,整数n,及其它相关变量及其它相关变量让让p指向数组指向数组a用指针的方法查找用指针的方法查找n的位置的位置若存在输出对应的下标值,否则输出提示信息若存在输出对应的下标值,否则输出提示信息输入数组输入数组a的元素的元素 及及 整数整数n的值的值分析与讲解分析与讲解例:指针编写查询程序例:指针编写查询程序main() { int a[10], n, *p, i; p=a;//p指向数组指向数组a的首地址的首地址 for (i=0; i<10; i++) //输入数组元素输入数组元素 { scanf(“%d”, p+i); }//相当于输入相当于输入p[i],即即a[i]的值的值 scanf(“%d”, &n); //输入另一个待查找的整数输入另一个待查找的整数 for(i=0; i<10; i++) //在数组中进行查找在数组中进行查找 { if (n==*(p+i)) break; } if (i<10) //如果循环提前结束,则说明找到与如果循环提前结束,则说明找到与n相等的值了相等的值了 { printf("id=%d\n", i); } else { printf("no this number.\n"); }} 指向一维数组的指针的运算指向一维数组的指针的运算当指针p指向了数组a的首地址后:(1)p+i:代表从p位置开始的第i个位置处的元素的地址(2)p++:指针p从当前位置向后移动到数组的下一个元素地址处。 p--即移到前一个元素的地址处)(3)*(p+i):取p+i这个单元中存储的变量的值4)*p++:先取p位置处的元素值,再将p指针移到下一个元素处5)(*p)++: p位置的那个元素值增加1指针p未动)课堂实践课堂实践-查询(查询(1))–1、用指针作函数参数,编写函数,求一个整型数组中、用指针作函数参数,编写函数,求一个整型数组中的最大值的最大值–2、用指针作函数参数,编写函数,将一个整型数组中、用指针作函数参数,编写函数,将一个整型数组中的元素全部逆置的元素全部逆置–3、用指针作函数参数,编写函数,找出一个字符数组、用指针作函数参数,编写函数,找出一个字符数组中的最大字符中的最大字符–4、指针作函数参数,编写函数,找出一个字符数组中、指针作函数参数,编写函数,找出一个字符数组中出现次数最多的字符出现次数最多的字符课堂实践课堂实践-排序(排序(2))–1、用指针作函数参数,编写选择法排序的函数用指针作函数参数,编写选择法排序的函数–2、实现成绩按从高到低的排序、实现成绩按从高到低的排序指针使用(作函数参数)(指针使用(作函数参数)(2学时,自学)学时,自学)•实践课,练习灵活使用指针•课堂实践•课堂小结、作业课堂目标课堂目标应知应知•指针作函数参数的意义•掌握指针引用数组元素的方法应会应会•函数编程、指针作函数参数课堂小结、作业课堂小结、作业–完成课堂未完成的实践练习完成课堂未完成的实践练习指向字符串的指针(指向字符串的指针(2学时)学时)•了解字符串操作函数的算法思路•理解如何用指针来实现各字符串操作函数•程序分析•课堂实践•课堂小结、作业课堂目标课堂目标应知应知•字符串的概念•指向字符串的指针引用字符串元素•理解字符串操作函数的基本算法思路应会应会•用指针实现几个常用字符串操作函数指向字符串的指针(扩展知识)•指针也可以指向字符串,用指针来编程实现字符串的常用操作,通常是非常简洁的。 •本质上,指向字符串的指针也是指向一维(字符)数组的指针,故其操作方法与指向一维数组的指针类似指向字符串的指针•字符串输入/输出函数的实现•字符串求长度的函数的实现•字符串拷贝函数的实现•字符串连接函数的实现•字符串比较函数的实现指向字符串的指针指向字符串的指针•1、字符串输入函数myGets#include 如原来字符串为”AbMxyzMktMwhileMMMcd”,则删除后新字符串将变为” Abxyzktwhilecd”原型:char * delete( char *str , char ch);返回值:新串的首地址指向字符串的指针指向字符串的指针•课堂实践(作业)•2、用指针作参数,编写函数,判断一个字符串str是否为回文所谓“回文”就是中心对称的字符串,如”abcdedcba”、”1236738376321”都是回文原型:int huiwen( char *str );返回值:1----表示str是回文 0----表示str不是回文课堂小结课堂小结•指向字符串的指针•字符串的常用函数的指针实现–输入/输出–求长度–字符串拷贝–字符串连接–字符串比较指向二维数组的指针(指向二维数组的指针(2学时,自学)学时,自学)•理解二维数组•了解指向二维数组的指针•了解指向二维数组指针的用法•程序分析•课堂实践•课堂小结、作业课堂目标课堂目标应知应知•二维数组元素的引用•指向二维数组的指针的定义•引用指向二维数组的指针应会应会•引用指向二维数组的指针二维数组(扩展知识)二维数组(扩展知识)•二维数组的定义和引用•二维数组的初始化和赋值•二维数组元素的遍历•课堂实践二维数组的定义、引用二维数组的定义、引用问题的提出:问题的提出: 存储某班所有存储某班所有50名同学的名同学的《《C语言语言》》成绩,可以成绩,可以用一个一维数组来表示。 但是若要存储全班同学的用一个一维数组来表示但是若要存储全班同学的《《数学数学》》、、《《英语英语》》、、《《C语言语言》》三门课程成绩时,需三门课程成绩时,需要定义要定义3个一维数组来存储吗?个一维数组来存储吗? 答案是否定的,我们可以定义一个二维答案是否定的,我们可以定义一个二维数组来存储所有同学三门课程的成绩数组来存储所有同学三门课程的成绩二维数组的定义二维数组的定义•定义数组的语法:定义数组的语法:数据类型数据类型 数组名数组名[数组长度数组长度1][数组长度数组长度2];; int a[3][50]•一维数组元素在内存中可以看作是存储在一一维数组元素在内存中可以看作是存储在一行上;行上;•二维数组元素在内存中则可以看作是存储在二维数组元素在内存中则可以看作是存储在多行上,每行上有多个元素多行上,每行上有多个元素 3行行50列列一维数组的定义举例一维数组的定义举例1、、int x[32][5];2、、#define SIZE1 100 #define SIZE2 50 float b[SIZE1][SIZE2];3、、char name[32][20];二维数组元素在内存中存储的理解二维数组元素在内存中存储的理解如:如: int x[4][10]可以理解为有可以理解为有4行,每行上存储了行,每行上存储了10个整型数个整型数据。 图示如下:据图示如下:第第0行行第第1行行第第2行行第第3行行第第0列列第第1列列第第2列列第第3列列第第4列列第第5列列第第6列列第第7列列第第8列列第第9列列X[0][0]X[0][9]X[1][9]X[1][0]X[3][0]X[3][3]X[3][9]X2][5]二维数组元素在内存中存储的理解二维数组元素在内存中存储的理解1、、int x[32][5];//数组数组x中有中有32行行(行下标:行下标:0~31),每行可存储,每行可存储5个个(列下标:列下标:0~4)整型数据整型数据2、、#define SIZE1 100 #define SIZE2 50 float b[SIZE1][SIZE2];//数组数组b中有中有100行,每行可存储行,每行可存储50个浮点型数据个浮点型数据3、、char name[32][20];//数组数组name中有中有32行,每行可存储不大于行,每行可存储不大于20的一个字符串的一个字符串二维数组元素的引用二维数组元素的引用n二维数组元素的表示:二维数组元素的表示: 数组名数组名[下标下标1] [下标下标2]如:如:int a[2][8];;则可引用的元素为:则可引用的元素为:a[0][0]~a[0][7] a[1][0]~a[1][7]int a[N][M]; //M、、N为常量为常量行下标的取值范围:行下标的取值范围:0~~N-1 ;;列下标的取值范围:列下标的取值范围:0~M-1在引用时下标是整型值,可以是整型在引用时下标是整型值,可以是整型常量常量、整型、整型变量变量或整型或整型表达式表达式注意:下标不能越界,否则可能覆盖其他数据,造成严重后果注意:下标不能越界,否则可能覆盖其他数据,造成严重后果二维数组的初始化和赋值二维数组的初始化和赋值二维数组的初始化二维数组的初始化•语法: 数据类型数据类型 数组名数组名[长度长度1] [长度长度2] ={ {第第0行值行值1,第,第0行值行值2,,…},, {第第1行值行值1,第,第1行值行值2,,…}{第第2行值行值1,第,第2行值行值2,,…}… }; 二维数组的初始化二维数组的初始化如:如:int num[3][4] ={ {1, 2, 3, 4},, {5, 6, 7, 8}{9, 10, 11, 12} }; 二维数组的初始化二维数组的初始化如:如:char name[4][20] ={ "John Smith", "Tom Cruis", "Bill Gates", "Bush W.D" };二维数组元素的输入与输出二维数组元素的输入与输出myfunc( ){ { int num[10][5], i, j; printf("enter data:\n"); for(i=0;i<10;i++)for (j=0; j<5; j++) scanf("%d", &a[i][j]); printf(“output the data:\n”); for(i=0;i<10;i++) {for (j=0; j<5; j++) printf("%d ", a[i][j]);printf(“\n”); }} 二维数组元素的输入与输出二维数组元素的输入与输出myfunc( ){ { char name[10][20]; int i; printf("enter data:\n"); for(i=0;i<10;i++)gets(name[i]); printf(“output the data:\n”); for(i=0;i<10;i++) {puts(name[i]);printf(“\n”); }} 例:在屏幕上输出杨辉三角例:在屏幕上输出杨辉三角例:在屏幕上输出杨辉三角例:在屏幕上输出杨辉三角#define N 10main( ){ { int a [N][N], i, j; for(i=0; i 输出杨辉三角,行高定义为符号常量2、编程求两个、编程求两个3×4 ((3行行4列)矩阵之和然后输出矩列)矩阵之和然后输出矩阵元素的值从键盘输入阵元素的值从键盘输入3、输入多个字符串存储到二维数组中,对它们按字母从大、输入多个字符串存储到二维数组中,对它们按字母从大到小的顺序排序到小的顺序排序课后作业课后作业1、将上页的第、将上页的第2题作为作业可以通过题作为作业可以通过N-S图来分析整个程序图来分析整个程序的流程 2、定义一个、定义一个4行行5列的二维整型数组,对其进行赋值,然后从列的二维整型数组,对其进行赋值,然后从该数组中选择出一个最小数及该数的下标值该数组中选择出一个最小数及该数的下标值(行和列的下标值都行和列的下标值都要记录要记录)项目训练(项目训练(2学时)学时)•综合理解指针和数组之间的关系,能够灵活运用指针来引用数组元素•实现 学生成绩管理系统V2.0•课堂实践•课堂小结、作业课堂目标课堂目标应知应知•指针引用数组元素•指针作函数参数应会应会•指针引用数组元素•指针作函数参数课堂实践课堂实践–实践指向一维数组的指针实践指向一维数组的指针•1、用指针编程实现学生成绩管理系统、用指针编程实现学生成绩管理系统V1.0的基本功能,将的基本功能,将V1.0转换为转换为V2.0版:版:–用函数输入数组中的多个元素,并返回实际输用函数输入数组中的多个元素,并返回实际输入的元素个数入的元素个数–用函数输出数组中的元素用函数输出数组中的元素–查找最大值(或最小值)查找最大值(或最小值)课堂实践课堂实践–实践指向一维数组的指针实践指向一维数组的指针•2、用指针编程实现学生成绩管理系统、用指针编程实现学生成绩管理系统V1.0的基本功能,将的基本功能,将V1.0转换为转换为V2.0版:版:–用函数输入数组中的多个元素,并返回实际输用函数输入数组中的多个元素,并返回实际输入的元素个数入的元素个数–用函数输出数组中的元素用函数输出数组中的元素–查找最大值(或最小值)查找最大值(或最小值)课堂实践课堂实践–实践指向一维数组的指针实践指向一维数组的指针•3、用指针编程实现学生成绩管理系统、用指针编程实现学生成绩管理系统V1.0的其他功能:的其他功能:–用函数将成绩从高到低进行排序用函数将成绩从高到低进行排序–用函数分别统计出成绩数组中用函数分别统计出成绩数组中<60、、60-79、、80-89、、90-100各段的人数各段的人数课堂实践课堂实践–实践指向一维数组的指针实践指向一维数组的指针•4、完成学生成绩管理系统、完成学生成绩管理系统V2.0的其他功能:的其他功能:–用函数实现主菜单的显示用函数实现主菜单的显示–完成主函数完成主函数课堂小结课堂小结–未完成的功能在课后继续完成未完成的功能在课后继续完成–一周后提交整个学生成绩管理系统一周后提交整个学生成绩管理系统V2.0的项目代码。 的项目代码结构体课堂目标课堂目标应知应知•理解结构体的概念•掌握结构体类型的定义•掌握结构体变量的定义和引用应会应会•结构体类型的定义•结构体变量的定义和引用专业英语词汇专业英语词汇英文英文词汇对应的中文意的中文意义structurestructure结构体构体structstructC C语言中言中缩写了的写了的结构构体关体关键字字回顾与提问回顾与提问1、提问:定义一个整型一维数组,理解这个数组中每个元素的类型是什么?2、如果现在有一个学生成绩管理系统,要求我们要处理的数据有学号、姓名、性别、年龄、3门课程等,能否分别定义多个数组来分立存储这些数据?这样做处理起来会有些什么困难?引入结构体概念引入结构体概念学号学号 姓名姓名 性别性别 年龄年龄 S1 S2 S3 想一个办法,把每一行不同的数据类型揉合成为一个整体,这样就只需要定义一个一维数组了,每个元素就是那个整体,它包含一个学生的各项信息引入结构体概念引入结构体概念•一个可以包含其他很多种数据类型在内的数据就是一个结构体,意思为:它是由多种数据类型混合构造而成的。 •构成这个结构体的每个数据就称为它的一个成员•上页示例中的结构体中就有多个成员:学号、姓名、性别、年龄、S1、S2、S3、…•结构体是一种构造数据类型,C语言本身并不提供,但C语言提供了构造结构体的方法:即结构体类型的定义 分析与讲解分析与讲解n结构体类型定义结构体类型定义 语法格式:语法格式:struct 结构体名结构体名 {数据类型数据类型 成员名成员名1;数据类型数据类型 成员名成员名2;数据类型数据类型 成员名成员名3;数据类型数据类型 成员名成员名4;…}; n学生结构体类型可定义如下: struct studentscore {char no[12]; //学号char name[9];//姓名char gender; //性别int age; //年龄int s [3];//20门成绩}; struct studentscore 就是新就是新创建的一个数据类型注意,创建的一个数据类型注意,千万不能省掉千万不能省掉struct。 分析与讲解分析与讲解–定义结构体变量定义结构体变量在新的结构体类型创建后,需要定义属于这种类型的变量,在新的结构体类型创建后,需要定义属于这种类型的变量,然后才能引用这个变量然后才能引用这个变量定义结构体变量的语法格式:定义结构体变量的语法格式:sturct 结构体名结构体名 结构体变量名结构体变量名;结构体类型结构体类型 定义学生结构体变量:定义学生结构体变量:struct studentscore s1, s2;//定义了两个结构体变量定义了两个结构体变量分析与讲解分析与讲解–简化结构体类型简化结构体类型当结构体类型创建后,用它来定义结构体变量时,类型当结构体类型创建后,用它来定义结构体变量时,类型名写起来比较长,这时,通常会用下面的语法格式来简名写起来比较长,这时,通常会用下面的语法格式来简化结构体类型(或者说将结构体类型换成简短一点的)化结构体类型(或者说将结构体类型换成简短一点的)typedef struct 结构体名结构体名 更简短的结构体类型名更简短的结构体类型名;将学生结构体类型简化:将学生结构体类型简化:typedef struct studentscore STU;分析与讲解分析与讲解–简化注意事项简化注意事项通常简化后的别名应该全用大写字母,通常简化后的别名应该全用大写字母,简化一定要放在结构体类型创建之后。 简化一定要放在结构体类型创建之后简化后,可以用简化的类型名来定义结构体变量简化后,可以用简化的类型名来定义结构体变量例:用简化后的结构体类型名定义两个结构体变量:例:用简化后的结构体类型名定义两个结构体变量: STU s3, s4;分析与讲解分析与讲解–结构体变量的引用•每个成员必须分立开来引用引用语法格式为:结构体变量.成员名分析与讲解分析与讲解–结构体变量的引用•例:输入学生结构体变量S1的各个成员#include 扩展知识:结构体变量初始化扩展知识:结构体变量初始化•与普通变量一样,结构体变量也可以在定义的同时给每个成员分别赋相应的值(初始化)•初始化的格式如下:•结构体类型 结构体变量名={成员1的值,成员2的值,成员3的值,…};例:初始化一个学生结构体t,形式如下:STU t={“000001”,”张三”,’M’, 19, {79, 87, 69} };课堂小结课堂小结1、结构体类型的定义2、结构体变量的定义与成员引用3、扩展知识:结构体变量的初始化结构体数组元素的输入结构体数组元素的输入/输出输出(约约1学时学时)•结构体数组的定义•结构体数组元素的引用•结构体数组元素的输入与输出•程序分析•课堂实践•课堂小结、作业学生成绩管学生成绩管理系统理系统V3.0定义结构体类型和数组定义结构体类型和数组结构体数组输入结构体数组输入/输出输出结构体数组查询结构体数组查询结构体数组排序结构体数组排序数据与文件读写数据与文件读写结构体数组汇总结构体数组汇总项目组成图项目组成图课堂目标课堂目标应知应知•掌握结构体数组的定义•掌握结构体数组的输入/输出方法应会应会•结构体数组的定义•结构体数组的输入/输出回顾与提问回顾与提问1、结构体类型定义的格式是什么,能否定义一个结构体类型?2、举例说明结构体变量怎么定义,结构体变量的成员的值怎么引用?如何进行结构体变量的初始化?引入结构体数组概念引入结构体数组概念•演示项目的输入演示项目的输入/输出功能,引出:输出功能,引出:•当一个应用需要多个结构体变量来解决时,当一个应用需要多个结构体变量来解决时,就应当想到要用数组来解决问题,这就是就应当想到要用数组来解决问题,这就是结构体数组。 结构体数组 •结构体数组中的每个元素是一个结构体变结构体数组中的每个元素是一个结构体变量,其中含有该结构体类型中所定义的各量,其中含有该结构体类型中所定义的各个成员 分析与讲解分析与讲解–结构体数组的定义结构体数组的定义 语法格式:语法格式:结构体类型结构体类型 数组名数组名[元素个数元素个数]; 例如:学生成绩管理系统中的用来存储多个学生信息的数例如:学生成绩管理系统中的用来存储多个学生信息的数组定义为:组定义为:STU s[10]; //定义能够保存定义能够保存10个元素的结构体个元素的结构体分析与讲解分析与讲解–结构体数组元素的引用结构体数组元素的引用回顾一维数组元素的引用:回顾一维数组元素的引用:int a[10];//定义定义for(i=0; i<10; i++) //引用引用{//利用利用a[i]进行各种操作,如输入进行各种操作,如输入scanf(“%d”, &a[i]);}分析与讲解分析与讲解–结构体数组元素的引用结构体数组元素的引用学生结构体数组元素的引用:STU s[10];//定义for(i=0; i<10; i++) //引用{//利用s[i]的各成员进行各种操作,如输入//输入s[i]的第一个成员//输入s[i]的第二个成员//输入s[i]的第三个成员//…}分析与讲解分析与讲解–结构体数组元素的引用结构体数组元素的引用学生结构体数组元素的引用:学生结构体数组元素的引用:STU s[10];//定义for(i=0; i<10; i++) //引用{//利用s[i]的各成员进行各种操作,如输入gets(s[i].no); //输入学号gets(s[i].name); //输入姓名s[i].gender=getchar(); //输入性别scanf(“%d”, &s[i].age); //输入年龄scanf(“%d%d%d”, &s[i].s[0], &s[i].s[1],&s[i].s[2]);//上面输入了s[i]的三门课程(存到数组中)}分析与讲解分析与讲解–输入结构体数组元素的成员时要注意输入结构体数组元素的成员时要注意((1)养成习惯,每个成员输入前均要加提示信息)养成习惯,每个成员输入前均要加提示信息((2)如果下一个是输入字符串或字符,则需要要输入)如果下一个是输入字符串或字符,则需要要输入前先清除键盘缓冲区前先清除键盘缓冲区while ( getchar() != ‘\n’ ) ;结合上面的代码,演示(结合上面的代码,演示(1)和()和(2)的效果。 的效果分析与讲解分析与讲解–结构体数组元素的引用结构体数组元素的引用学生结构体数组元素的引用:学生结构体数组元素的引用:STU s[10];//定义for(i=0; i<10; i++) //引用{//利用s[i]的各成员进行各种操作,如输出//输出s[i]的第一个成员//输出s[i]的第二个成员//输出s[i]的第三个成员//…}分析与讲解分析与讲解–结构体数组元素的引用结构体数组元素的引用学生结构体数组元素的引用:学生结构体数组元素的引用:STU s[10];//定义for(i=0; i<10; i++) //引用{//利用s[i]的各成员进行各种操作,如输出printf(“%s ”,s[i].no); //输出学号 printf(“%s ”, s[i].name); //输出姓名 printf(“%c ”, s[i].gender ); //输出性别printf(“%d ”, s[i].age); //输出年龄printf(“%d %d %d\n”, s[i].s[0], s[i].s[1],s[i].s[2]);//上面输出了s[i]的三门课程}分析与讲解分析与讲解–输出结构体数组元素的成员时要注意输出结构体数组元素的成员时要注意((1)一般一个结构体元素显示在一行上)一般一个结构体元素显示在一行上((2)每个结构体元素输出完毕后应该换行输出)每个结构体元素输出完毕后应该换行输出结合上面的代码,演示(结合上面的代码,演示(1)和()和(2)的效果。 的效果课堂实践与作业课堂实践与作业–定义一个学生结构体数组,并从键盘上输入若干个学生的信息,然后列表显示出全部学生信息(将每个学生的信息显示在一行上)–模仿程序:定义生日结构体数组,从键盘上输入若干个学生的生日信息,然后列表显示出全部学生的生日信息(每行显示一个生日信息)扩展知识:结构体数组初始化扩展知识:结构体数组初始化–初始化的格式如下:–结构体类型 结构体数组[10]={{成员1的值,成员2的值,成员3的值,…}, {成员1的值,成员2的值,成员3的值,…},…};例:STU s[2]={{“000001”,”张三”,’M’, 19, {79, 87, 69} },{“000141”,”王五”, “F”, 20, {76,90,65} }};课堂小结课堂小结1、结构体数组的定义2、结构体数组元素及元素成员的引用3、扩展知识:结构体数组的初始化用函数实现结构体数组元素的用函数实现结构体数组元素的输入输入/输出(实践)输出(实践)(约约2学时学时)•结构体数组的定义•结构体数组元素的引用•结构体数组元素的输入与输出•结构体数组作函数参数•课堂实践•课堂小结、作业学生成绩学生成绩管理系统管理系统V3.0定义结构体类型和数组定义结构体类型和数组结构体数组输入结构体数组输入/输出输出结构体数组查询结构体数组查询结构体数组排序结构体数组排序数据与文件读写数据与文件读写结构体数组汇总结构体数组汇总项目组成图项目组成图回顾与提问回顾与提问1、输入/输出结构体数组元素的一般思路?(用循环解决?)2、如果不想让main函数变复杂,该怎么处理数组元素的输入与输出?课堂目标课堂目标应知应知•掌握结构体数组的定义•掌握结构体数组的输入/输出方法•掌握结构体数组作函数参数的意义应会应会•结构体数组的定义•结构体数组的输入/输出结构体数组作函数参数结构体数组作函数参数p结构体数组,本质上也是一个一维数组p一维数组作函数参数时,一般需要两个:一是数组名,二是数组中元素的个数 分析与讲解分析与讲解•结构体数组作函数参数结构体数组作函数参数 输入函数:void input(STU s[], int n),参数的意义:s是STU类型的结构体数组,n是该数组中元素的个数。 输出函数:void output(STU s[], int n),参数同输入函数分析与讲解分析与讲解–简单复习上节课的输入与输出的思路简单复习上节课的输入与输出的思路–提出新的问题:若要求在输入时,根据输入提出新的问题:若要求在输入时,根据输入的学号是否为空来决定输入是否提前结束,的学号是否为空来决定输入是否提前结束,该怎么处理输入函数?该怎么处理输入函数?课堂实践与作业课堂实践与作业–完成用函数input输入学生结构体信息的函数void input(STU s[], int n)–修改函数input,假定其有一个int类型返回值 函数原型修改为:int input(STU s[], int n),返回值代表实际输入的元素个数–完成输出函数output,void output( STU s[], int n)课堂实践与作业课堂实践与作业p模仿程序:用函数完成输入学生生日信息模仿程序:用函数完成输入学生生日信息和输出学生生日信息的功能,并在主函数和输出学生生日信息的功能,并在主函数中调用课堂课堂小结小结1、数组元素的引用2、函数实现结构体数组元素的输入与输出3、输入函数测试没问题后,可以暂不再调用,而改为数组初始化,这样避免每次都重复输入多条学生信息,耽误其他函数的运行与测试。 结构体数组元素的查询结构体数组元素的查询(约约2学时学时)•数组元素的查询•结构体数组作函数参数•课堂实践•课堂小结、作业学生成绩管学生成绩管理系统理系统V3.0定义结构体类型和数组定义结构体类型和数组结构体数组输入结构体数组输入/输出输出结构体数组查询结构体数组查询结构体数组排序结构体数组排序数据与文件读写数据与文件读写结构体数组汇总结构体数组汇总项目组成图项目组成图课堂目标课堂目标应知应知•掌握结构体数组元素查询的方法•掌握结构体数组作函数参数的意义应会应会•结构体数组的查询回顾与提问回顾与提问1、在main函数中怎么调用输入/输出函数?2、一般一维数组中查询一个给定值的思路是什么?(提示分析算法思路?)结构体元素的查询结构体元素的查询 一般思路:•首先,查找每一个结构体元素(访问方法与普通一维数组一样,用循环来控制)•其次,要用结构体元素的某个成员来进行相应的比较(不能直接用结构体元素来进行比较)•其他过程与普通一维数组中的过程一样 分析与讲解分析与讲解•按学号查询 函数原型:void searchbyno(STU s[], int n, char xh[]),参数的意义:s是STU类型的结构体数组,n是该数组中元素的个数,xh是待查询的学号。 若查找成功,将对应的学生信息(一个元素)输出,否则,输出“未找到”的提示分析与讲解分析与讲解在分析完思路的情况下,写出函数代码:void searchbyno( STU s[], int n, char xh[]){int i;for(i=0; i 分析与讲解分析与讲解•按学号升序排序按学号升序排序函数原型:函数原型:void sortbyno(STU s[], int n ),参数的意义:,参数的意义:s是是STU类型的结构体数组,类型的结构体数组,n是该数组中元素是该数组中元素的个数分析与讲解分析与讲解在分析完思路的情况下,写出选择排序函数代码:void sortbyno( STU s[], int n ){int i, j; int id; //要记住的最小学号的下标STU tmp;//交换用的临时变量for(i=0; i 一定的格式,并具有数据持久性p文件分文件分类:: (C语言中按文件里的数据言中按文件里的数据组织形式形式)可分可分为::文本文件文本文件二二进制文件制文件文件概念文件概念p 在存储空间上:文本文件所占空间较大在存储空间上:文本文件所占空间较大如:整数25168,在二进制文件中占2个字节(整型),而在文本文件中占5个字节再如:1.234567,在二进制文件中占4个字节(浮点型),而在文本文件中占8个字节p 文本文件可直接阅读,而二进制文件不能被人直文本文件可直接阅读,而二进制文件不能被人直接阅读,需要通过转换接阅读,需要通过转换分析与讲解分析与讲解•文件操作的基本过程文件操作的基本过程 1、定义文件指针 2、打开一个文件3、对文件进行相关操作(读、写、查找、定位等)4、关闭文件文件的基本操作文件的基本操作 (1)打开文件打开文件函数名称函数名称:fopen使用方式:使用方式:fp = fopen(“a.txt”, “r”); 文件指文件指针待打开文件待打开文件文件打开方式文件打开方式(只只读)例:例:FILE *fp; //定定义一个文件指一个文件指针fp = fopen(“a.txt”, “r”); //以只以只读方式打开当前目方式打开当前目录下的文件下的文件a.txtfp=fopen(“a.txt”, “w”); //以只写方式打开当前目以只写方式打开当前目录下的文件下的文件a.txtfp=fopen(“d:\\b.dat”, “r”); //以只以只读方式打开方式打开d盘根目根目录下的文件下的文件b.dat文件的基本操作文件的基本操作 (1)打开文件打开文件函数名称函数名称:fopen使用方式:使用方式:fp = fopen(“a.txt”, “r”); 文件指文件指针待打开文件待打开文件文件打开方式文件打开方式(只只读)注意:打开文件后,一定要判断文件打开注意:打开文件后,一定要判断文件打开 是否成功,方法如下:是否成功,方法如下:if( fp==NULL) //不成功不成功{printf(“文件打开不成功文件打开不成功\n”);exit( 0);//无法无法进行下面的操作,只能退出行下面的操作,只能退出(或返回上一或返回上一级)}打开方式功能说明文本文件二进制文件“r”“rb”仅为读而打开已有文件指定文件不存在时,会出错“w”“wb”仅为写信息而打开文件文件不存在时,建立新文件;文件已存在时,覆盖原文件“a”“ab”为追加信息而打开文件文件不存在时,建立新文件;文件已存在时,新数据写在原有内容之后“r+”“rb+”为读写信息而打开文件更换读写操作时不必关闭文件;“r+”读写总是从文件起始位置开始,“rb+”可由位置函数设置读写起始位置“w+”“wb+”为读写信息而打开文件先建立文件后进行写操作。 w+”可以从头开始读;”wb+”可由位置函数设置读写起始位置“a+”“ab+”为读写信息而打开文件在文件尾部添加新数据a+”可以从头开始读;”ab+”可由位置函数设置读写起始位置 文件的打开方式文件的打开方式(表表) (2)关关闭文件文件函数名称函数名称:fclose使用方式:使用方式:fclose(fp); //fp为文件指文件指针例:例:FILE *fp; //定定义一个文件指一个文件指针fp = fopen(“a.txt”, “r”); //以只以只读方式打开当前目方式打开当前目录下的文件下的文件a.txt//判断文件是否打开成功判断文件是否打开成功… //对文件文件进行一些相关操作行一些相关操作fclose(fp); //文件文件处理理结束后,必束后,必须关关闭文件文件 (3)块写文件写文件函数名称函数名称:fwrite使用方式:使用方式:fwirte(待写的内存待写的内存变量的地址,字量的地址,字节数,写的次数,文件数,写的次数,文件指指针)例如:将数例如:将数组s的第的第i个元素写入到文件个元素写入到文件fp(假定打开后假定打开后 的指的指针为fp)fwrite( &s[i], sizeof(s[i]),1,fp);//写入到文件中写入到文件中若要将数若要将数组的多个元素写入到文件,的多个元素写入到文件,则需要用循需要用循环来控制来控制分析与讲解分析与讲解将结构体数组的全部元素写入到指定文件中:将结构体数组的全部元素写入到指定文件中:void writetofile(STU s[], int n){int i;//定义循环变量FILE *fp;//定义文件指针 fp=fopen(“stuinfo.dat”,”wb”);//打开文件if(NULL= = fp)//判断文件打开是否成功{puts(“打开失败\n”); return; }//打开成功,则可以进行写操作for(i=0;i –模仿程序:在学生生日管理中,完成类似的writetofile函数,将学生的生日信息全部写入到指定的文件birthday.txt中–模仿程序:在学生生日管理中,完成类似的readfromfile函数,从文件birthday.txt中将学生生日信息读取到内存的结构体数组中,并返回实际读取的元素个数–写一个程序,完成文件复制功能即从键盘上输入一个文件名(如a.doc,该文件在硬盘上一定要存在),将该文件复制为另一个文件(如b.doc)扩展知识扩展知识–文件的其他读写函数–单个字符的读写函数:fputc( )、fgetc( )–字符串读写函数:fputs( )、fgets( )–格式读写函数:fprintf( )、fscanf( ),这两个函数可以读写各类数据–以上函数 的用法,请参照教材附录IV中的函数原型说明扩展知识扩展知识–小练习小练习–编写程序,分别用上页的各对读写函数实现文编写程序,分别用上页的各对读写函数实现文件的复制功能件的复制功能课堂小结课堂小结1、文件的操作过程2、文件的块读、写函数使用3、文件的其他读写函数项目训练(项目训练(2学时)学时)•综合理解结构体、数组的关系•实现 学生成绩管理系统V3.0•课堂实践•课堂小结、作业项目组成图项目组成图学生成绩管学生成绩管理系统理系统V3.0定义结构体类型和数组定义结构体类型和数组结构体数组输入结构体数组输入/输出输出结构体数组查询结构体数组查询结构体数组排序结构体数组排序数据与文件读写数据与文件读写结构体数组汇总结构体数组汇总课堂目标课堂目标应知应知•结构体数组元素的灵活引用•数组名作函数参数•文件基本操作应会应会•结构体数组的输入/输出、查询、文件操作•结构体数组名作函数参数课堂实践课堂实践-实现学生成绩管理系统V3.0•1、实现input和output函数•2、实现searchbyno函数及其他查询函数•3、实现sortbyno排序函数•4、实现写数据函数writetofile•5、实现读数据函数readfromfile•6、设计主菜单函数menu•7、编写main函数,完成对1-6各函数的调用,达到项目设计的功能。 •8、测试系统课堂实践-实现学生成绩管理系统V3.0课堂小结课堂小结1、未完成的功能在课后继续完成2、一周后提交整个学生成绩管理系统V3.0的项目代码链表教学目标教学目标应知应知•了解节点和链表的概念•掌握动态链表的创建和遍历应会应会•动态链表的创建•动态链表的遍历专业英语词汇专业英语词汇英文词汇英文词汇对应的中文意义对应的中文意义typedef类型重命名类型重命名list列表(线性表)列表(线性表)linklist链表链表node节点节点malloc动态申请内存动态申请内存sizeof空间大小空间大小回顾与提问回顾与提问1、如何构建一个静态链表?他有什么作用和不足?怎么使链表更实用?2、案例3种有哪几个功能,用哪些函数来实现的?3、检查学生课后实训与作业完成情况(包括小组评价)演示程序演示程序•演示成绩管理案例演示成绩管理案例V3.0模块,察看其中创模块,察看其中创建链表和遍历的函数建链表和遍历的函数•提问:如何实现对多个学生信息的存储操提问:如何实现对多个学生信息的存储操作?作?•引出动态链表引出动态链表分析与讲解分析与讲解•指向结构体本身的指针指向结构体本身的指针我们可以定义一个指针指向结构体变量,也可以将这个指针定义在某个我们可以定义一个指针指向结构体变量,也可以将这个指针定义在某个结构体的内部,作为该结构体的一个成员。 结构体的内部,作为该结构体的一个成员定义形式如下:定义形式如下:struct STUDENT { char name[20]; int age; float chinese, math; struct STUDENT *next; //定义了指针定义了指针next,它可以指向自身,它可以指向自身结构体类型的变量结构体类型的变量};利用结构体中包含的这种指针,可以构成一个利用结构体中包含的这种指针,可以构成一个链表链表分析与讲解分析与讲解–链表的概念链表的概念Alice2176.589.0Tom2081.570.5Bob2279.079.0Jerry2180.588.0head为为了了编编程程方方便便,,通通常常头头结结点点空空余余((不不存存储储信信息息)),,只只起起一一个个链链表表起起始始点点的作用如如上上图图,,链链表表的的最最开开始始一一个个结结点点称称为为头头结结点点我我们们通通过过指指向向头头结结点点的的指指针针head,就可以访问到链表中的任何结点的信息就可以访问到链表中的任何结点的信息链链表表的的最最后后一一个个结结点点称称为为尾尾结结点点,,尾尾结结点点的的指指针针必必须须为为空空((在在C中中,,用用NULL表示 空指针)。 表示 空指针)分析与讲解分析与讲解–链表结点成员的访问链表结点成员的访问当当一一个个链链表表创创建建好好了了之之后后,,我我们们可可以以通通过过指指向向链链表表的的指指针针来来访问链表中每个结点的成员访问链表中每个结点的成员如在上图中,我们想要访问第如在上图中,我们想要访问第1个结点的个结点的age成员,可以用:成员,可以用: head->next->age若想访问第若想访问第2个结点的个结点的age成员,可以用:成员,可以用: head->next->next->age若想访问第若想访问第3个结点的个结点的age成员,可以用:成员,可以用: head->next->next->next->age分析与讲解分析与讲解–动态开辟和释放空间的函数动态开辟和释放空间的函数编编写写程程序序,,先先动动态态开开辟辟结结构构体体空空间间,,然后释放它然后释放它include 成员,其他成员空闲2)让让指指针针q指指向向headq的的作作用用是是::总总指指向向当当前前链链表表的的最最后后一一个个结结点点,,即尾结点即尾结点)(3)用指针用指针p去开辟新的结点,并对新开辟的结点赋值去开辟新的结点,并对新开辟的结点赋值(4)将新开辟的结点将新开辟的结点p链到链表的末尾,即链到链表的末尾,即q的后面的后面(5)指针指针q向后移动一个结点,即指向向后移动一个结点,即指向p(6)如果需要继续申请新结点,转第如果需要继续申请新结点,转第(3)步,否则转第步,否则转第(7)步步(7)指针指针q所指的结点的所指的结点的next成员置为空成员置为空(NULL)(8)将链表的头指针将链表的头指针head返回给主调函数返回给主调函数分析与讲解分析与讲解创建函数--创建函数--create_list() STU * create_list() //定定义创义创建建链链表函数表函数{ STU *head, *p, *q; char na[20]; head = ( STU *)malloc(sizeof( STU )); //(1) q = head; //(2) gets(na); while (strlen(na)) //输输入名字不入名字不为为空空时时,申,申请结请结点点 { p =(STU *)malloc(sizeof(STU)); //(3) strcpy(p->name, na); scanf("%d%f%f", &p->age, &p->chinese, &p->math); getchar(); //滤滤掉掉scanf未未处处理的回理的回车车符符 q->next = p; //(4) q = p; //(5) gets(na); //为为下一个下一个结结点做准点做准备备 } q->next = NULL; //(7) return head;}分析与讲解分析与讲解输出函数--输出函数--print_list(head)输出过程:输出过程:根据根据head,沿着,沿着next成员向的结点,逐个输出。 成员向的结点,逐个输出1)先让指针先让指针p指向指向head的下一个结点的下一个结点(因为因为head中无数据中无数据)(2)如果如果p指向的结点为空,则说明是空链,转指向的结点为空,则说明是空链,转(6),否则转,否则转(3)(3)输出输出p指向的结点的信息指向的结点的信息(4)将将p向后移动一个结点向后移动一个结点(5)转第转第(2)步步(6)函数结束函数结束分析与讲解分析与讲解输出函数--输出函数--print_list() void print_list(STU *head) //定定义输出出链表函数,表函数,链表表头为head{ STU *p; p = head->next; //(1) while (p!=NULL) //当当链表表处理理还未未结束束时 (2) { puts(p->name); //(3) printf("%d %f %f\n", p->age,p->chinese,p->math); //(3) p=p->next; //(4) }}错中学错中学–链表和数组是一种线性表,里面的数据顺序存放,但链表和数组是一种线性表,里面的数据顺序存放,但链表的节点除了数据域,还有指针域,为操作方便还链表的节点除了数据域,还有指针域,为操作方便还单独设置了头节点,其中不存放数据。 单独设置了头节点,其中不存放数据–链表遍历操作比较简单,但必须从表头开始逐个访问链表遍历操作比较简单,但必须从表头开始逐个访问节点–链表创建过程是申请节点,链到表尾,最后为指针设链表创建过程是申请节点,链到表尾,最后为指针设置成置成NULL,返回头节点,返回头节点Head,不要弄错了,不要弄错了课堂练习课堂练习–1、试着写一个函数完成链表的创建、试着写一个函数完成链表的创建–2、写一个函数,实现链表的遍历操作、写一个函数,实现链表的遍历操作 更进一步更进一步•1、考虑案例、考虑案例3中链表是如何创建的?中链表是如何创建的?•2、案例、案例3中还涉及到对链表的哪些操作?中还涉及到对链表的哪些操作?o3、总结与评价、总结与评价本次课小结本次课小结•1、掌握链表的创建和输出原理、掌握链表的创建和输出原理•2、掌握链表创建和输出函数的编写、掌握链表创建和输出函数的编写 •3、理解创建链表和输出链表的函数的调用、理解创建链表和输出链表的函数的调用 链表操作教学目标教学目标应知应知•理解动态链表的创建和遍历•掌握链表插入、删除、查询节点的操作应会应会•动态链表的创建和遍历•链表节点的增、删、查等操作专业英语词汇专业英语词汇英文词汇英文词汇对应的中文意义对应的中文意义linklist链表链表node节点节点delete删除删除insert插入插入query查询查询回顾与提问回顾与提问1、如何创建一个动态链表?数据的访问有什么特点?2、如何遍历一个已经创建好了的链表?3、检查学生课后实训与作业完成情况(包括小组评价)演示程序演示程序•演示成绩管理案例演示成绩管理案例V3.0V3.0模块,察看其中增模块,察看其中增加学生,删除学生,查询学生,成绩排序加学生,删除学生,查询学生,成绩排序等功能。 等功能•提问:在结构体数组中如何实现对多个学提问:在结构体数组中如何实现对多个学生信息的增删查和排序操作?生信息的增删查和排序操作?•引出动态链表的其他操作引出动态链表的其他操作分析与讲解分析与讲解•链表的检索链表的检索链表的检索就是在链表中查找符合某个条件的结点是否存链表的检索就是在链表中查找符合某个条件的结点是否存在,若存在则检索成功;否则检索失败在,若存在则检索成功;否则检索失败算法思路:算法思路:从头指针开始从头指针开始遍历遍历整个链表,对每个结点进行整个链表,对每个结点进行判断是否符合指定的条件,若找到则跳出循环并输出相关判断是否符合指定的条件,若找到则跳出循环并输出相关信息;若没有找到则给出找不到的提示信息信息;若没有找到则给出找不到的提示信息分析与讲解分析与讲解–链表的检索链表的检索例例题题::新新建建一一个个链链表表,,输输入入3名名同同学学的的信信息息然然后后检检索索该该链链表表,,看看链链表表中中是是否否存存在在姓姓名名为为“Tom”的的结结点点若若存存在在,,输输出出该该同同学学的的所所有有信信息息;;若若不不存存在在,,给给出出“名名为为‘Tom’的的同同学不存在!学不存在!”的信息。 的信息–链表的检索链表的检索struct STUDENT { char name[20]; int age; float chinese, math; struct STUDENT *next;}; //注意:以后所有的注意:以后所有的结构体操作都使用构体操作都使用这个定个定义typedef struct STUDENT STU; //给结构体改个构体改个别名,可名,可让程序程序简短短 STU *create_list();//声明声明创建建链表函数表函数STU * search(STU *head,,char * who); main() { STU *head,*p; head = create_list(); //调用函数,用函数,创建建链表表 p=search(head, “Tom”); //输出以出以head为头指指针的的链表表 if(p !!= NULL) //表示找到了,是表示找到了,是经break语句跳出循句跳出循环的的 { printf(“ 找到了,找到了,该同学具体信息如下:同学具体信息如下:\n”);printf(“%s,%d,%f,%f\n”,p->name,p->age,p->chinese,p->math); }elseprintf(“没有名没有名为%s的同学!的同学!\n”); }分析与讲解分析与讲解–检索函数检索函数—search()() STU * search(STU *head, char * who){STU * p; p = head->next;while (p!=NULL) { if(strcmp(p->name,who)==0)//找到找到 break; else p=p->next; }return p; //若返回若返回值为 NULL,,则表示没有找到表示没有找到}分析与讲解分析与讲解–链表结点的删除链表结点的删除Alice2176.589.0Tom2081.570.5Bob2279.079.0Jerry2180.588.0head链表的删除就是在链表中删除某个结点。 链表的删除就是在链表中删除某个结点算法思路:算法思路:q->next=p->next;free(p);分析与讲解分析与讲解链表的删除链表的删除例例题题::新新建建一一个个链链表表,,输输入入3名名同同学学的的信信息息然然后后检检索索该该链链表表,,看看链链表表中中是是否否存存在在姓姓名名为为“Tom”的的结结点点若若存存在在,,删删除除该该同同学学结结点点;;若若不不存存在在,,给给出出“名名为为‘Tom’的的同同学学不不存存在!在!”的信息分析与讲解分析与讲解删除函数删除函数—delete()() void delete (STU *head, char * who){STU * p,*q;q=head; p = head->next;while (p!=NULL) { if(strcmp(p->name,who)==0)//找到找到 break; else { p=p->next;q=q->next; } } if(p !!= NULL) //表示找到了,是经表示找到了,是经break语句跳出循环的语句跳出循环的 {q->next = p->next;printf(“ 名为名为%s 的同学已被删除。 的同学已被删除\n”,,p->name);free(p); }elseprintf(“没有名为没有名为%s的同学!的同学!\n”);}链表节点的插入链表节点的插入链表的插入链表的插入链链表表的的插插入入就就是是在在链链表表中中的的某某个个地地方方插插入入一一个个结结点点,,操作完成之后仍是一个完整的链表操作完成之后仍是一个完整的链表算法思路:算法思路:p分析与讲解分析与讲解链表的插入链表的插入例例题题::新新建建一一个个链链表表,,输输入入3名名同同学学的的信信息息((按按姓姓名名升升序序次次序序输输入入))然然后后插插入入一一个个姓姓名名为为“Tom”的的结结点点之之后后输输出所有同学的信息出所有同学的信息分析与讲解分析与讲解链表的插入链表的插入struct STUDENT { char name[20]; int age; float chinese, math; struct STUDENT *next;}; //注意:以后所有的结构体操作都使用这个定义注意:以后所有的结构体操作都使用这个定义typedef struct STUDENT STU; //给结构体改个别名,可让程序简短给结构体改个别名,可让程序简短 STU *create_list();//声明创建链表函数声明创建链表函数void insert (STU *head , STU *newNode ); //声明插入函数声明插入函数main() { STU *head,,*newNode; head = create_list(); //调用函数,创建链表调用函数,创建链表 newNode=(STU *)(malloc(sizeof(STU))); printf(“请输入新同学的姓名、年龄、语文、数学成绩请输入新同学的姓名、年龄、语文、数学成绩”); gets((newNode->name); scanf(“%d%f%f”,&newNode->age,&newNode->chinese,&new->math); insert(head,newNode); 在链表中按姓名次序插入新结点在链表中按姓名次序插入新结点}分析与讲解分析与讲解插入函数插入函数—insert()()void insert (STU *head, STU * newNode){STU * p,*q;q=head; if(head==NULL) head=(STU)(malloc(sizeof(STU)));p = head->next;while (p!=NULL) { if(strcmp(p->name, newNode->name)>0)//升序升序 break; else { p=p->next;q=q->next; } }q->next=newNode;newNode->next=p;}错中学错中学–链表和数组是一种线性表,里面的数据顺序存放,但链表和数组是一种线性表,里面的数据顺序存放,但链表的节点除了数据域,还有指针域,为操作方便还链表的节点除了数据域,还有指针域,为操作方便还单独设置了头节点,其中不存放数据。 单独设置了头节点,其中不存放数据–链表的操作必须考虑要处理的节点的位置,链表为空链表的操作必须考虑要处理的节点的位置,链表为空与否,或表尾等特殊的情况与否,或表尾等特殊的情况–链表删除和添加节点都要注意新节点引入时的断链和链表删除和添加节点都要注意新节点引入时的断链和链入的方式和顺序链入的方式和顺序–链表操作都通过函数调用来实现,考虑函数的参数和链表操作都通过函数调用来实现,考虑函数的参数和返回值返回值课堂练习课堂练习–1、试着写一个函数完成链表查询节点的、试着写一个函数完成链表查询节点的操作操作–2、试着写一个函数完成链表增加节点的、试着写一个函数完成链表增加节点的操作操作–3、试着写一个函数完成链表删除节点的、试着写一个函数完成链表删除节点的操作操作 更进一步更进一步–1、考虑案例、考虑案例3中链表增删查节点是如何中链表增删查节点是如何实现的?实现的?–2、案例、案例3中对链表的排序操作如何实现中对链表的排序操作如何实现??–3、总结与评价、总结与评价本次课小结本次课小结 1、掌握链表的检索算法;、掌握链表的检索算法; 2、掌握链表的删除算法;、掌握链表的删除算法; 3、掌握链表的插入算法;、掌握链表的插入算法;链表与文件教学目标教学目标应知应知•理解文件的相关概念•掌握文件的读写方法应会应会•文件的保存和读写•将链表的内容保存到文件中专业英语词汇专业英语词汇英文词汇英文词汇对应的中文意义对应的中文意义file文件文件write写写回顾与提问回顾与提问1、如何创建一个动态链表?数据的访问有什、如何创建一个动态链表?数据的访问有什么特点?么特点?2、如何遍历一个已经创建好了的链表?、如何遍历一个已经创建好了的链表?3、检查学生课后实训与作业完成情况(包括、检查学生课后实训与作业完成情况(包括小组评价)小组评价)演示程序演示程序•演示成绩管理案例演示成绩管理案例V3.0模块,察看其中文模块,察看其中文件的读写功能等功能。 件的读写功能等功能•提问:如何将链表中的数据保存到文件?提问:如何将链表中的数据保存到文件?•引出文件的相关操作引出文件的相关操作分析与讲解分析与讲解•链表的内容保存到文件链表的内容保存到文件函数原型:函数原型: void writeToFile(NODE* head) 功能功能:将将链链表中的数据写到文件中表中的数据写到文件中参数:参数:head 类类型:型:NODE * 说说明:指向明:指向链链表表头结头结点的指点的指针针返回返回值值:无:无算法思路:算法思路:从头指针开始从头指针开始遍历遍历整个链表,对每个结点进行整个链表,对每个结点进行判断是否为空,若不为空则保存到文件中判断是否为空,若不为空则保存到文件中分析与讲解分析与讲解–读写文件中内容到链表中读写文件中内容到链表中函数原型:NODE* readFromFile() 功能:从文件读信息到结构体数组中参数:student[]类型:STUDENT []说明:用来存储从文件读到的学生信息返回值 类型:NODE *说明:将链表的头指针头指针作为返回值返回算法思路:先打开文件,若文件没有结束则读出制定长度的数据到链表节点中,直至结束。 错中学错中学–从文件读出数据到链表结束后,链表尾节点的从文件读出数据到链表结束后,链表尾节点的指向不为指向不为NULL,有什么后果?有什么后果?–写入文件后忘记加写入文件后忘记加fclose函数,会怎么样?函数,会怎么样?课堂练习课堂练习–1、试着编写函数完成将链表数据保存到、试着编写函数完成将链表数据保存到文件中文件中–2、试着编写函数完成将从文件中读写数、试着编写函数完成将从文件中读写数据到链表中据到链表中更进一步更进一步–考虑如何保证文件中的数据未被损考虑如何保证文件中的数据未被损坏坏.本次课小结本次课小结–1、掌握链表内容保存到文件的算法;、掌握链表内容保存到文件的算法;–2、掌握如何将文件中数据读入到链表的、掌握如何将文件中数据读入到链表的算法。
