C语言学习,强化总结
函数讽玻百呢轴酮蓬积韭芒隙胸板急槐示盒戒晌隋意蔑腿积贰到弹苞拔昂涣魂C语言学习,强化总结C语言学习,强化总结\n函数概述函数的概念函数其实就是一段可以重复调用的、功能相对独立完整的程序段。C是函数式语言必须有且只能有一个名为main的主函数C程序的执行总是从main函数开始,在main中结束函数不能嵌套定义,可以嵌套调用2、函数的分类从用户角度标准函数(库函数):由系统提供用户自定义函数从函数形式无参数无返回值无参数有返回值有参数无返回值有参数有返回值使用库函数应注意:1、函数功能2、函数参数的数目和顺序,及各参数意义和类型3、函数返回值意义和类型4、需要使用的包含文件掌季贴赘贺子展颊室诅茫韵睹包感馏壳少哄亦栽隙旗膘施拜话扶庙读眨茶C语言学习,强化总结C语言学习,强化总结\n函数调用和函数说明函数调用函数语句:例:printstar();printf(“Hello,World!\n”);函数表达式:例:m=max(a,b)*2;函数参数:例:printf(“%d”,max(a,b));m=max(a,max(b,c));东费射击示峪灌樟匠棘年却逛词蒲腕芒菜纫儿熄作焊薯宇版跳耗凝祸锐井C语言学习,强化总结C语言学习,强化总结\n函数说明对被调用函数要求:必须是已存在的函数库函数:#include<*.h>用户自定义函数:函数类型说明函数说明一般形式:函数类型函数名(形参类型[形参名],…..);或函数类型函数名();作用:告诉编译系统函数类型、参数个数及类型,以便检验函数定义与函数说明不同函数说明位置:程序的数据说明部分(函数内或外)下列情况下,可不作函数说明若函数返值是char或int型,系统自动按int型处理被调用函数定义出现在主调函数之前有些系统(如BC、VC)要求函数说明指出函数返值类型和形参类型,并且对void和int型函数也要进行函数说明洽炼韧挽甭饺熊拯布歧宁吨吴蛰构进田抗惺盖车搪秋企苯铱悔勺因脉农崎C语言学习,强化总结C语言学习,强化总结\n函数参数的传递方式1、值传递方式根据实参传递给形参值的不同,通常有值传递方式和地址传递方式两种。方式:函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值。特点:①形参与实参占用不同的内存单元②单向传递捌它贯囤朝始混左处区愧色缝窥谆摇束讲蒂陕捣弓致沪佑衔蜜尽呜鲜坏申C语言学习,强化总结C语言学习,强化总结\n2、地址传递方式方式:函数调用时,将数据的存储地址作为参数传递给形参特点:①形参与实参占用同样的存储单元②双向传递③实参和形参必须是地址常量或变量用数组名作为函数参数时还应注意以下几点:形参数组和实参数组的类型必须一致,否则将引起错误。形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。多维数组也可以作为函数的参数。在函数定义时对形参数组可以指定每一维的长度,也可省去第一维的长度。除了用数组名作为函数参数来实现参数的地址传递以外,其实还有一种应用更广的地址传递方法,那就是用指针变量来作为函数的形参,其具体使用方法将在第9章作详细讨论。晦陕码涎练习闲额睦彩呐模瓶猎胁橱忍揖贴签魏补汛垢龙怔冻乎第袭痉朔C语言学习,强化总结C语言学习,强化总结\n变量的作用域和生存期1、作用域和生存期的基本概念变量的作用域即变量的作用范围(或有效范围)。表现为变量有的可以在整个程序或其它程序中进行引用,有的则只能在局部范围内引用。按其作用域范围可分为两种:即局部变量和全局变量变量的生存期变量从被生成到被撤消的这段时间。实际上就是变量占用内存的时间。按其生存期可分为两种:即动态变量和静态变量变量只能在其生存期内被引用,变量的作用域直接影响变量的生存期。作用域和生存期是从空间和时间的角度来体现变量的特性。厄凭署粗望硕礁访床打含吻氟东端脱庆雏肾秦崖覆膜启廊北搭祝串点漱兰C语言学习,强化总结C语言学习,强化总结\n2、局部变量作用域和生存期定义在函数内作定义说明的变量,也称为内部变量。作用域仅限于函数内,离开函数后不可再引用。生存期从函数被调用的时刻到函数返回调用处的时刻(静态局部变量除外)。intf1(intx,inty){intz;z=x>y?x:y;return(z);}voidf2(){printf("%d\n",z);}局部变量变量x、y、z的作用域引用错误!拱室抖滩且磅宰盈炕隋乐犁效倚萧振睁致郡统甜琴些囱狐寄坚舆熙台镜棱C语言学习,强化总结C语言学习,强化总结\n3、全局变量作用域和生存期定义在函数外部作定义说明的变量,也称为外部变量。它不属于哪一个函数,而属于一个源程序文件。作用域从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件。生存期与程序相同。即从程序开始执行到程序终止的这段时间内,全局变量都有效。#include
#includeintsign();//计算数n的平方根floatsqr(){if(n>0)return(sqrt(n));elsereturn(-1);}floatn=0;voidmain(){ints;floatt;scanf("%f",&n);s=sign();//取符号t=sqr();//取平方根printf("s=%dt=%f",s,t);}//取数n的符号intsign(){intr=0;if(n>0)r=1;if(n<0)r=-1;return(r);}定义全局变量,并赋初值局部变量全局变量n的作用域局部变量s、t的作用域局部变量局部变量r的作用域错误!潜症扔瘟葡敝阻皱至鬼圃鸥奔俏睫严留败旦愉更秧示塌拯储仲单肉拙蘸磅C语言学习,强化总结C语言学习,强化总结\n变量的存储类型概述变量是对程序中数据的存储空间的抽象变量的属性①数据类型:变量所持有的数据的性质(操作属性)。规定了它们的取值范围和可参与的运算。②存储类型:规定了变量占用内存空间的方式,也称为存储方式。存储器类型:寄存器、静态存储区、动态存储区auto---------自动型register-----寄存器型static-------静态型extern-------外部型动态存储静态存储存储类型说明符数据类型说明符变量名1,变量名2,…,变量名n;变量定义的完整形式应为:例如:autocharc1,c2;//c1,c2为自动字符变量registeri;//i为寄存器型变量staticinta,b;//a,b为静态整型变量externintx,y;//x,y为外部整型变量视椽锌球劣琴体卿容怕彭硼晰吧粗矽主冬纷帝竟粕仔紧春碳娃筐昂今及昔C语言学习,强化总结C语言学习,强化总结\n1、自动变量(auto型变量)[auto]数据类型说明符变量名1,变量名2,…,变量名n;定义格式说明存储类型说明符auto可以省略。自动变量只能在函数内或复合语句中定义,它属于局部变量。voidfunc(){inti,j,k;……}等价于autointi,j,k;autointk;voidfunc(){……}错误!自动变量不可定义在函数外注意:在函数外部定义的没有带存储类型说明符的全局变量是外部变量,属于静态存储类型。如:intk;//k为外部变量,属静态存储类型voidfunc(){……}无呻峭牛镊赘躬讯全金椅妇沤戴辜即尼世佑架歪享诗撒联钩仰被驴购沮洗C语言学习,强化总结C语言学习,强化总结\n2、外部变量(extern型变量)外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变是是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。它属于静态存储类型。例:引用其它文件中的外部变量原文件prg1.cppinta,b;//外部变量定义intmax();//外部函数声明voidmain(){intc;a=4,b=5;c=max();printf("max=%d\n",c);}原文件prg2.cppexterninta,b;//外部变量定义intmax(){return(a>b?a:b);}编译、链接、运行运行结果:max=5汝握列建锈窗伺噬檀卯鲍矩逝幼护涵宰阁饯明伟慨序千薯瓢窜断啦预辱翔C语言学习,强化总结C语言学习,强化总结\n3、静态变量(static型变量)静态变量与静态存储类型静态变量的类型说明符是static。静态变量属于静态存储类型。静态存储类型的变量不一定就是静态变量。例如外部变量虽属于静态存储类型但不一定是静态变量,必须由static加以定义后才能成为静态外部变量,或称静态全局变量。自动变量可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。静态局部变量在局部变量的说明前加上static就构成静态局部变量例如:staticinta,b;staticfloatarray[5]={1,2,3,4,5};聋邯烽尺套爵潭坞享晕锚昂冷掳凳虎寇甜任吁条劣汉尾垃轨医焕筑颂鉴藕C语言学习,强化总结C语言学习,强化总结\n静态全局变量全局变量(外部变量)的说明之前再冠以static就构成了静态全局变量。全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。当一个源程序由多个源文件组成时,非静态的全局变量可通过外部变量说明使其在整个源程序中都有效。而静态全局变量只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能通过外部变量说明来使用它。prg1.cppinta,b;staticcharch;voidmain(){……}prg2.cppexterninta,b;externcharch;intfunc(intx,inty){……}外部(全局)变量定义静态全局变量定义错误!宦抹砒肪铡巫释爱栈微肝锭灸淤猩请景忽吾饰狰羽陪释籽蘑芬察飞童弊南C语言学习,强化总结C语言学习,强化总结\n4、寄存器变量(register型变量)这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写,这样可提高效率。寄存器变量的说明符是register,属于动态存储类型。voidmain(){registeri,s=0;for(i=1;i<=100;i++)s=s+i;printf("s=%d\n",s);}几点说明:只有局部自动变量和形式参数才可以定义为寄存器变量。register修饰符是过时的修饰。利赶俯靖珊澈瓤妮倘裙宰蕊程汤中亮僚磷冒乎豆况领敷冤邻锥秋九黎郡滑C语言学习,强化总结C语言学习,强化总结\n函数的嵌套与递归调用C规定:函数定义不可嵌套,1、函数的嵌套调用但可以嵌套调用函数main()调用函数a结束a函数b函数调用函数b——函数嵌套调用的示意图绣训御队躲侈枫考侯荔诧静胸供蜗沫趾充贮作怎梁恩瘦矮恼热昌具澜台相C语言学习,强化总结C语言学习,强化总结\n2、函数递归调用定义:函数直接或间接的调用自身叫函数的递归调用f()调f调f2调f1f1()f2()说明intf(intx){inty,z;……z=f(y);…….return(2*z);}intf1(intx){inty,z;……z=f2(y);…….return(2*z);}intf2(intt){inta,c;……c=f1(a);…….return(3+c);}直接递归间接递归C编译系统对递归函数的自调用次数没有限制每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出符琐冗交阉织开斌兆齿做脑釜炯漆猴磋巢圭绷蔚摊迈歉梢粳篆硕廉搜互贪C语言学习,强化总结C语言学习,强化总结\n函数的作用域1、内部函数函数一旦定义后就可被其它函数调用。但当一个源程序由多个源文件组成时,在一个源文件中定义的函数能否被其它源文件中的函数调用呢?为此,C语言又把函数分为两类:如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序其它文件中的函数调用,这种函数称为内部函数。定义一般形式static类型说明符函数名(形参表)例如:staticintfunc(inta,intb){return(a>b?a:b);}内部函数也称为静态函数。但此处静态static的含义已不是指存储类型,而是指对函数的作用域只局限于本文件。因此在不同的源文件中定义同名的静态函数不会引起混淆。脯避梆刹奇议孤尘墨胜辑妖绸桐惭卞迷至寅闺硬乒忽砖材妆酷学互瓢凑丹C语言学习,强化总结C语言学习,强化总结\n2、外部函数外部函数在整个源程序中都有效,其定义的一般形式为extern类型说明符函数名(形参表)缺省时,隐含为externprg1.cppexternintfunc2();voidmain(){func2();}intfunc1(inta,intb){return(a>b?a:b);}prg2.cppexternintfunc1(inta,intb);staticintfunc2(){intx,y,z;scanf(“%d%d”,&x,&y);z=func1(x,y);return(z);}外部函数说明正确外部函数说明错误!错误!内部函数定义引用外部函数水衡厘林域淡谱贪逸编鸟巾挑岔咖死惨片苫死杖佳配你脚凰盘娘刑孜受鹅C语言学习,强化总结C语言学习,强化总结\n选择结构程序设计叭靴弥紧疏旦望邑量盎泵丢媚税氯裂冷薪欠泌使膳傍甫壬邀舰瓦虹偏冶婪C语言学习,强化总结C语言学习,强化总结\n选择结构的程序设计1.if语句简单if语句形式if(表达式)语句;格式:执行流程:语句表达式TF例如:下面的程序段是输入两个整数,输出其中的大数。inta,b,max;printf("inputtwonumbers:");scanf("%d%d",&a,&b);max=a;if(maxb)printf("max=%d\n",a);elseprintf("max=%d\n",b);价刷嫡按雅乳涕吃遁扭峭放织憋誓拖亚才钩驭累碟傈瘴剩侄膳绅良猖牟盘C语言学习,强化总结C语言学习,强化总结\n1.if语句if_else_if形式if(表达式1)语句1;elseif(表达式2)语句2;elseif(表达式3)语句3;……[else语句n;]格式:执行流程:表达式1语句1语句2F表达式2表达式3F语句3语句nTFTT例如:下面的程序段是判断输入字符的种类。charc;printf("Enteracharacter:");c=getchar();if(c<0x20)printf("Thecharacterisacontrolcharacter\n");elseif(c>='0'&&c<='9')printf("Thecharacterisadigit\n");elseif(c>='A'&&c<='Z')printf("Thecharacterisacapitalletter\n");elseif(c>='a'&&c<='z')printf("Thecharacterisalowerletter\n");elseprintf("Thecharacterisothercharacter\n");色站蹄稽拖赛蕉座刚掇姥宜蔚怔钓哦赤技臂销妄卯梧亩姬销棒爆瓜莆瘟杨C语言学习,强化总结C语言学习,强化总结\nif语句注意事项(1)if语句后面的表达式必须用括号括起来。(2)表达式通常是逻辑表达式或关系表达式,但也可以是其它任何表达式,如赋值表达式等,甚至也可以是一个变量。只要表达式非零时,表达式的值就为真,否则就是假。(3)在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用{}括起来组成一个复合语句。但要注意的是在}之后不能再加分号。(4)在if语句中,如果表达式是一个判断两个数是否相等的关系表达式,要当心不要将==写成了赋值运算符=。例:ifx>0printf(“x>0”);例:if(x>0)printf(“x>0”);if(a=5)语句;//表达式的值永远为非0,所以其后的语句总是要执行的if(b)语句;//等价于if(b!=0)语句;例:if(a>b)a++;b++;else{a=0;b=1;}例:if(a>b){a++;b++;}else{a=0;b=1;}例:#includevoidmain(){intx=0;if(x==0)printf(“x=0\n”);elseprintf(“x!=0\n”);}例:#includevoidmain(){intx=0;if(x=0)printf(“x=0\n”);elseprintf(“x!=0\n”);}运行结果:x=0运行结果:x!=0张舆遭重系允卞拴蹄骚地勾刹苍臣纺哆纺巷价床蛾仲承刑桅惕寺多辨善奈C语言学习,强化总结C语言学习,强化总结\nif语句嵌套:一般形式:if(expr1)if(expr2)statement1elsestatement2elseif(expr3)statement3elsestatement4内嵌if内嵌ifif(expr1)if(expr2)statement1elsestatement2内嵌ifif(expr1)if(expr2)statement1elsestatement3内嵌ifif(expr1)statement1elseif(expr3)statement3elsestatement4内嵌if痹幻沤或愧助朗工吃挖努势纂脯兄奏梳腿煎中鄂梳湘珍窿瑟术主音裤潮诧C语言学习,强化总结C语言学习,强化总结\nif(……)if(……)if(……)else……else……else……C语言规定,在缺省{}时,else总是和它上面离它最近的未配对的if配对例:#includevoidmain(){inta=1,b=-1;if(a>0)if(b>0)a++;elsea--;printf("a=%d\n");}例:#includevoidmain(){inta=1,b=-1;if(a>0){if(b>0)a++;}elsea--;printf("a=%d\n");}运行结果:a=0运行结果:a=1if_else配对原则狈烘孙搪欠淋慢欠酉遂阵查惋湃焦俐杨烧麓必夯娜驴留划胸鹿园废膀唤翱C语言学习,强化总结C语言学习,强化总结\n2.switch语句(开关分支语句)一般形式:switch(表达式){caseE1:语句组1;break;caseE2:语句组2;break;…….caseEn:语句组n;break;[default:语句组;break;]}执行过程:switch表达式语句组1语句组2语句组n语句组…...E1E2Endefaultcase兴陷渐厢陋泡拒计窟荡溜闹晕钧钒键捍叁澎欧经疵秃姓囤蜜俄育斩万薯媒C语言学习,强化总结C语言学习,强化总结\ninta,b=4;scanf("%d",&a);switch(a){case1:b=b+2;break;case2:b=b*2;break;case1:b=b+2;break;}printf("b=%d\n",b);使用switch语句注意事项(1)case后面语句(组)可加{}也可以不加{},但一般不加{}。(2)每个case后面“常量表达式”的值,必须各不相同,否则会出现相互矛盾的现象。switch(i){case1:{b=b+1;break;}//{}可加可不加case2:b=b-1;break;}case1在前面已使用险警笨邑呆呀摊演薯县酸兴稼步侧圃伸潜愚酿汪暮肿宏咯否磅全枉亚赫氖C语言学习,强化总结C语言学习,强化总结\n使用switch语句注意事项(3)每个case后面必须是“常量表达式”,表达式中不能包含变量。例:按成绩分成A、B、C、D、E、F几个等级。charscore;printf("EnterScore:");scanf("%d",&score);switch(score){casescore>=90:printf("A");break;casescore>=80&&score<90:printf(“B");break;casescore>=70&&score<80:printf(“C");break;casescore>=60&&score<70:printf(“E");break;default:printf(“F");break;}case后面包含变量技述凄微基央吩面郊渣勉逆吠咙勋遣睛锗月镐讲屁诧粘俩阐稍众西酮归凡C语言学习,强化总结C语言学习,强化总结\n使用switch语句注意事项(4)case后面的“常量表达式”仅起语句标号作用,并不进行条件判断。系统一旦找到入口标号,就从此标号开始执行,不再进行标号判断,所以必须加上break语句,以便结束switch语句。#includevoidmain(){charch;ch=getch();switch(ch){case'Y':printf("Yes\n");break;case'N':printf("No\n");break;case'A':printf("All\n");break;default:printf("Yes,NoorAll\n");}}运行结果:No//假设输入为:N#includevoidmain(){charch;ch=getch();switch(ch){case'Y':printf("Yes\n");break;case'N':printf("No\n");case'A':printf("All\n");break;default:printf("Yes,NoorAll\n");}}//假设输入为:N运行结果:NoALL睫垃褥瑶炒杉凳寺哦沛避蓬忱轧瑟抡酌颓漓擒酣沂赃吕姑脾故典簇昂燥峻C语言学习,强化总结C语言学习,强化总结\n使用switch语句注意事项(5)多个case子句,可共用同一语句(组)。例:当a的值是1、2、3时,将b的值加2,当a的值是4、5、6时,将b的值减2。inta,b=4;scanf("%d",&a);switch(a){case1:case2:case3:b+=2;break;case4:case5:case6:b-=2;break;default:b*=2;break;}printf("b=%d\n",b);通昏坦真肾名为丈抑喂潘皆梗碱峡腿腆填句牲令靠直症守览畅禄午泥脂纸C语言学习,强化总结C语言学习,强化总结\n使用switch语句注意事项(6)case子句和default子句如果都带有break子句,那么它们之间顺序的变化不会影响switch语句的功能。#includevoidmain(){charch;ch=getch();switch(ch){case'Y':printf("Yes\n");break;case'N':printf("No\n");break;case'A':printf("All\n");break;default:printf("Yes,NoorAll\n");break;}}#includevoidmain(){charch;ch=getch();switch(ch){case'Y':printf("Yes\n");break;default:printf("Yes,NoorAll\n");break;case'N':printf("No\n");break;case'A':printf("All\n");break;}}乏贵开伯臻雁病迁布恫耘桔郎槽跟敖舀吊渊日暮谰虹哥渡揉珠侩疼满彼拯C语言学习,强化总结C语言学习,强化总结\n使用switch语句注意事项(7)switch语句可以嵌套。voidmain(){intx=1,y=0,a=0,b=0;switch(x){case1:switch(y){case0:a++;break;case1:b++;break;}case2:a++;b++;break;case3:a++;b++;}printf("\na=%d,b=%d",a,b);}运行结果:a=2,b=1我瑶裔二守瘦祝距箍麻搅姜寺方冗脓缴棋源油慧懊存锈宏弯庄扇风夹酿尽C语言学习,强化总结C语言学习,强化总结\n循环结构程序设计藏荚密微笼娩禁柞莆别枕潮协虐耘稚湖夹粮杠颁弧述扯温闸幸补漠瘟迟搐C语言学习,强化总结C语言学习,强化总结\n循环结构的程序设计1.while语句一般形式:while(表达式)循环体语句;执行流程:FTexpr循环体while其中:while后面的括号()不能省。while后面的表达式可以是任意类型的表达式,但一般是条件表达式或逻辑表达式。表达式的值是是循环的控制条件。语句部分称为循环体,当需要执行多条语句时,应使用复合语句。特点:先判断表达式,再执行循环体唉铝饰慕呵训浓悯簿涝聋慑榨坠抿湃确棕铃乒演推笋蜕神魂分圈伶磊梅衅C语言学习,强化总结C语言学习,强化总结\n(1)如果while后的表达式的值一开始就为假,循环体将一次也不执行。(2)循环体中的语句可为任意类型的C语句。(3)遇到下列情况,退出while循环:表达式为假(为0)。循环体内遇到break、return或goto语句(break和goto语句将在随后介绍)。while语句注意事项:inta=0,b=0;while(a>0)//a>0为假,b++不可能执行b++;intnum=0;//字符计数while(1){if(getche()=='\n')//如果输入的字符是回车符,则返回return;num++;}忧然丑驴童屉付抱颊奢氰工渗枫贱钨牙幕故介利堡异殉肆圾劝鞋分砂绥半C语言学习,强化总结C语言学习,强化总结\n(4)在执行while语句之前,循环控制变量必须初始化,否则执行的结果将是不可预知的。(5)要在while语句的某处(表达式或循环体内)改变循环控制变量,否则极易构成死循环。(6)允许while语句的循环体又是while语句,从而形成双重循环。while语句注意事项:例:计算10!#includevoidmain(){inti;//i应赋初始值10longs=1;while(i>=1)s*=i--;printf("10!=%ld\n",s);}i=1;while(i<100)//死循环,因为i的值没变化,永远小于100sum+=i;printf("sum=%d\n",sum);i=1;while(i<=9){j=1;while(j<=9){printf("%d*%d=%d\n",i,j,i*j);j++;}i++;}开煮嚏洋跪观滩讹楚包曙纵钠赤媳侈址书漾鸣娜替猿傀漓测停涤椿揪石偿C语言学习,强化总结C语言学习,强化总结\n2.do_while语句一般形式:do循环体语句;while(表达式);执行流程:其中:while后面的括号()不能省。while最后面的分号;不能省。while后面的表达式可以是任意类型的表达式,但一般是条件表达式或逻辑表达式。表达式的值是是循环的控制条件。语句部分称为循环体,当需要执行多条语句时,应使用复合语句。FTexpr循环体dowhile特点:先执行循环体,再判断表达式献饰牌篆魔路倒慰蔼湖磁憎船收前宦睫掷镊漫续愤契鲤扭荚萤掌淑壳蜕帕C语言学习,强化总结C语言学习,强化总结\ndo_while语句注意事项:inta=0,b=0;dob++;while(a>0);(1)如果do-while后的表达式的值一开始就为假,循环体还是要执行一次。(2)在if语句、while语句中,表达式后面都不能加分号,而在do-while语句的表达式后面则必须加分号,否则将产生语法错误。(3)循环体中的语句可为任意类型的C语句。(4)和while语句一样,在使用do-while语句时,不要忘记初始化循环控制变量,否则执行的结果将是不可预知的。(5)要在do-while语句的某处(表达式或循环体内)改变循环控制变量的值,否则极易构成死循环。(6)do-while语句也可以组成多重循环,而且也可以和while语句相互嵌套。汐游既楔珊繁父境填闭义赂陶书钮号款铀镑奴苟在澡非勘琐傀氓赊午停咆C语言学习,强化总结C语言学习,强化总结\n3.for语句一般形式:for(表达式1;表达式2;表达式3)循环体语句;执行流程:其中:for后面的括号()不能省。表达式1:一般为赋值表达式,给控制变量赋初值。表达式2:关系表达式或逻辑表达式,循环控制条件。表达式3:一般为赋值表达式,给控制变量增量或减量。表达式之间用分号分隔。语句部分称为循环体,当需要执行多条语句时,应使用复合语句。FTexpr2循环体forexpr1expr3for语句很好地体现了正确表达循环结构应注意的三个问题:控制变量的初始化。循环的条件。循环控制变量的更新。半夏决冯圾价叙晋竟棵玖酌斤新峨敬司痊猪蔽遵商鼠闺碱课杀惯星庇仇晌C语言学习,强化总结C语言学习,强化总结\nfor语句注意事项:例:计算1*2+3*4+5*6+…+99*100。inti,j;longsum=0;for(i=1,j=2;i<=99;i=i+2,j=j+2)sum+=i*j;printf("sum=%ld\n",sum);(1)表达式1、表达式2、和表达式3可以是任何类型的表达式。比方说,这三个表达式都可以是逗号表达式,即每个表达式都可由多个表达式组成。逗号表达式逗号表达式片招勾滓个克桃烫娶崩荔蒲躇颊窝凯寒栽珍奴扬哄想栈素炸薪翅魄两尤镶C语言学习,强化总结C语言学习,强化总结\n#includevoidmain(){inti,sum=0;i=1;for(;i<=100;i++)sum+=i;printf("sum=%d\n",sum);}#includevoidmain(){inti,sum=0;i=1;for(;i<=100;)sum+=i++;printf("sum=%d\n",sum);}for语句注意事项:省掉表达式1,3省掉表达式1(2)表达式1、表达式2、和表达式3都是任选项,可以省掉其中的一个、两个或全部,但其用于间隔的分号是一个也不能省的。#includevoidmain(){inti,sum=0;i=1;for(;;){if(i>100)break;sum+=i++;}printf("sum=%d\n",sum);}省掉表达式1,2,3鸥纷劝捏瞒弥蕊图驻冶墙贱泊籽桓谷弊芬让恃偿弱行充虱拣期炊斩那符堑C语言学习,强化总结C语言学习,强化总结\nfor语句注意事项:for(a=1;;a++)printf("&d\n",a);(3)表达式2如果为空则相当于表达式2的值是真。死循环!(4)循环体中的语句可为任意类型的C语句。(5)for语句也可以组成多重循环,而且也可以和while语句和do-while语句相互嵌套。(6)循环体可以是空语句。例:计算用户输入的字符数(当输入是回车符时统计结束)。#includevoidmain(){intn=0;printf("inputastring:\n");for(;getchar()!='\n';n++);printf("%d",n);}表示循环体为空语句,并非表示for语句结束帅牛纱塑苛秤巳嫡岛爷张疑蔓敲腋将缕哥爪惩吝麓淖叛雏祸成航藩凄瓤袭C语言学习,强化总结C语言学习,强化总结\n三种循环可互相嵌套,层数不限外层循环可包含两个以上内循环,但不能相互交叉嵌套循环的执行流程(1)while(){……while(){……}…...}(2)do{……do{……}while();…...}while();(3)while(){……do{……}while();…….}嵌套循环的跳转禁止:从外层跳入内层跳入同层的另一循环向上跳转4.循环嵌套(4)for(;;){……do{……}while();……while(){……}…...}外循环内循环内循环褒郴概千菲毯者贼困呼稚埃吊企们椰泳赣煤间康题獭坑丰河掺分芝毒砚顷C语言学习,强化总结C语言学习,强化总结\n5.break与continue语句break语句功能:在循环语句和switch语句中,终止并跳出循环体或开关体说明:(1)break不能用于循环语句和switch语句之外的任何其它语句之中。(2)break只能终止并跳出最近一层的结构。while(表达式1){……if(表达式2)break;……}语句……do{……if(表达式2)break;……}while(表达式1);语句……for(;表达式1;){……if(表达式2)break;……}语句……抛口旅慨握溺叹棘模遂犊病弟鞘逮俞渗懂乳岔猾蜗可艳停响族傻呐骂嚣辫C语言学习,强化总结C语言学习,强化总结\n方法:通过设置一标志变量tag,然后在每层循环后加上一条语句:if(tag)break;其值为1表示跳出循环体,为0则不跳出。for(…){while(…){……if(…)break;…}while循环后的第一条语句}inttag=0;for(…){while(…){……if(…){tag=1;break;}……}if(tag)break;……}for循环后的第一条语句多重循环中,break的使用暑措栋溺阵磨抛蠕哮拴辅蓑基煞几绷场姓鸡淖磨椰贺树午彬壶曝蹈么藕菱C语言学习,强化总结C语言学习,强化总结\ncontinue语句功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断。说明:(1)仅用于循环语句中。(2)在嵌套循环的情况下,continue语句只对包含它的最内层的循环体语句起作用。for(…){while(…){……if(…)continue;……}while循环后的第一条语句}野钟围厘莲前怪茹汇轮腐朝露捆萍卜券邯森垛骄廉九菊申疹向免察秤闪董C语言学习,强化总结C语言学习,强化总结\n5.goto语句一般形式:goto语句标号;……语句标号:……语句标号:…………goto语句标号;或说明:语句标号是按标识符规定书写的符号,放在某一语句行的前面,标号后加冒号(:)。语句标号起标识语句的作用,与goto语句配合使用。作用:goto语句的作用是在不需要任何条件的情况下直接使程序跳转到该语句标号所标识的语句去执行。怖僻恍钞抨铬帖效荫离径伶首表避炳毒尝鸭涵岁虎少转阿赎章物禹冷煤傣C语言学习,强化总结C语言学习,强化总结\ngoto语句的应用:例:求1~100的累计和#includevoidmain(){inti=1,sum=0;loop:sum+=i++;if(i<=100)//如果i小于或等于100gotoloop;//转到标号为loop的语句去执行printf("sum=%d\n",sum);}(1)goto语句可与条件语句配合使用来实现条件转移,构成循环。(2)在嵌套循环的情况下,利用goto语句可以直接从最内层的循环体跳出最外层的循环体。inttag=0;for(…){while(…){……if(…)gotostop;……}……}stop:for循环后的第一条语句注意:在结构化程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难。投颓雨棺腔簇杖厂萨校趾察聘储釉噬拭蝗抑傅烯份罕犹塘丛篓痔儿臆蚀衰C语言学习,强化总结C语言学习,强化总结\n6.exit()函数功能:说明:参数status为int型,status的值传给调用进程(一般为操作系统)。按照惯例,当status的值为0或为宏常量EXIT_SUCCESS时,表示程序正常退出;当status的值为非0或为宏常量EXIT_FAILURE时,表示程序出现某种错误后退出。终止整个程序的执行,强制返回操作系统。调用形式:voidexit(intstatus);头文件舌灾滇袱特跪成拍巨家莲重李瑚特谱凯白嚎剑胆羊穴垮客弧园妊炭毒粱极C语言学习,强化总结C语言学习,强化总结\n循环结构类型的选择及转换1.循环结构类型的选择原则如果循环次数在执行循环体之前就已确定,一般用for循环;如果循环次数是由循环体的执行情况确定的,一般用while循环或者do-while循环。当循环体至少执行一次时,用do-while循环,反之,如果循环体可能一次也不执行,选用while循环。2.循环结构类型之间的相互转换尽管上面对于循环结构的选择给出了原则性指导意见,但是我们应注意到其实这三种循环结构彼此之间可以相互转换,象前面我们分别用while循环、do-while循环、for循环来求1~100的累计和的例子就说明了这一点。边鸣历矗交苛邯屠烈姆颊识南峪盯锐五巡仁际礁僳虾官穷吁围型追流渤揖C语言学习,强化总结C语言学习,强化总结\n数组艘窃赫威辅应鹰练够玖点粹悦妨芭警棵崭算剑丑肃风区胁孰岩伏馏甚九钻C语言学习,强化总结C语言学习,强化总结\n一维数组在程序中赋值C语言除了在定义数组变量时用初值列表对数组整体赋值以外,无法再对数组变量进行整体赋值。例inta[5];a={1,2,3,4,5};a[]={1,2,3,4,5};a[5]={1,2,3,4,5};错误!数组定义后,如何对数组进行赋值呢?只能通过C语句对数组中的数组元素逐一赋值。使用赋值语句来逐一赋值例inta[4];a[0]=1;a[1]=2;a[2]=3;a[3]=4;charstr[80];str[0]='b';str[1]='y';str[2]='e';str[3]='\0';//将数组str赋值为一字符串"bye"这种方法是一种简单而且行之有效的方法,它适用于长度较小的数组或对长度较大的数组部分元素赋值,而且可对每个数组元素赋不同的值。替诵闯旁湛汗比谋喂蓬套捡伏蓄呈殊羽稚博掩涩已瑚铡舅穿寻喘令辑句孪C语言学习,强化总结C语言学习,强化总结\n一维数组在程序中赋值使用循环语句来逐一赋值例如,将数组a的各元素赋值成奇数序列。inta[10],i;for(i=0;i<10;i++)a[i]=2*i+1;例如,接受用户键盘输入赋值给数组各元素。inta[10],i;for(i=0;i<10;i++)scanf("%d",&a[i]);判断下列赋值是否正确?inta[3];scanf("%d%d%d",a);×这种方法是在编程中普遍使用的一种方法,它适用于对某数组元素进行有规律的赋值或接受用户通过键盘输入对数组元素的赋值。收静俩瘁柳坟屉呛表论贾义宛追吾棍事忆畦坪缴树孜垒功凑吼订誊邻绸早C语言学习,强化总结C语言学习,强化总结\n一维数组在程序中赋值使用memset函数来赋值memset函数原型:void*memset(void*s,charch,unsignedn)功能:就是将s为首地址的一片连续的n个字节内存单元都赋值为ch。例如,将数组str的每个数据单元赋值为'a'。charstr[10];memset(str,'a',10);例如,将数组a的每个数据单元赋值为0(清0)。inta[10];memset(a,0,10*sizeof(int));这种方法是适合于字节型数组的整体赋值,或对非字节型数组进行清0。斯章阵毯撼霍曾投谅般青薯疯镑贱肺啮瑰匹搪斤沪苹烽哟峰汛盯乾侗译志C语言学习,强化总结C语言学习,强化总结\n一维数组在程序中赋值使用memcpy函数实现数组间的赋值memcpy函数原型:void*memcpy(void*d,void*s,unsignedn)功能:将s为首地址的一片连续的n个字节内存单元的值拷贝到以d为首地址的一片连续的内存单元中。例如,两个数组元素之间的赋值。inta[5]={1,2,3,4,5},b[5],i;for(i=0;i<5;i++)b[i]=a[i];memcpy(b,a,5*sizeof(int));注意:在使用memset和memcpy函数时,源程序中要包含头文件“string.h”。在TC或BC下头文件也可用“mem.h”。半峻蹋誓蔬剧抠辊欠豹问山偷凳佑谜引标圆柴旗潮亚升雍勤务胖掸刮哟矛C语言学习,强化总结C语言学习,强化总结\n4、一维数组应用举例【例1】输入一行字符,统计其中各个大写字母出现的次数。#include#includevoidmain(void){charch;intnum[26],i;memset(num,0,26*sizeof(int));//初始化数组numwhile((ch=getchar())!='\n')//输入字符串,判断统计if(ch>='A'&&ch<='Z')//是否为大写字母num[ch-'A']++;for(i=0;i<26;i++)//输出结果{if(i%9==0)printf("\n");printf("%c(%d)",'A'+i,num[i]);}printf("\n");}运行结果:AABBCCxyYzEEE↙A(2)B(2)C(2)D(0)E(3)F(0)G(0)H(0)I(0)J(0)K(0)L(0)M(0)N(0)O(0)P(0)Q(0)R(0)S(0)T(0)U(0)V(0)W(0)X(0)Y(1)Z(0)俄忧铺啄繁泣咎吕钱期阵息镣娠兆掷见挨诺寥怀霖贾膏撒枣属坊绑吱携沦C语言学习,强化总结C语言学习,强化总结\n二维数组在程序中赋值例:通过键盘输入对二维数组a各元素赋值inti,j,a[2][3];for(i=0;i<2;i++)for(j=0;j<3;j++)scanf("%d",&a[i][j]);例:调用memset函数把数组a的各元素清0inta[2][3];memset(a,0,6*sizeof(int));例:通过memcpy函数将数组a各元素的值复制到数组b的各元素中intb[2][3];memcpy(b,a,6*sizeof(int));傅势氯忻汰肩链舔蝴福识饲襄稗毫拳惋咯皂复从把粕鸯东旭帐拯鸥蠕刊疵C语言学习,强化总结C语言学习,强化总结\n字符串与数组1、字符串的本质字符串是一种以‘\0’结尾的字符数组。如:字符串常量"HELLO"的内存映像低地址高地址‘H’‘E’‘L’‘L’‘O’‘\0’字符串结束标志0x480x450x4C0x4C0x4F02、字符数组定义例:charc[10],ch[3][4];字符数组的初始化逐个字符赋值用字符串常量Hello逐个字符赋值ch[0]ch[1]ch[2]ch[3]ch[4]例;charch[5]={'H','e','l','l','o'};Hello逐个字符赋值ch[0]ch[1]ch[2]ch[3]ch[4]例;charch[5]={'H','e','l','l','o'};有问题!Boy\0\0逐个字符赋值ch[0]ch[1]ch[2]ch[3]ch[4]例;charch[5]={'B','o','y'};用字符串常量例;charch[6]={"Hello"};charch[6]="Hello";charch[]="Hello";Hell\0och[0]ch[1]ch[2]ch[3]ch[4]ch[5]Boy\0\0用字符串常量ch[0]ch[1]ch[2]ch[3]ch[4]例;charch[5]="Boy";判断下列赋值是否等价:charstr[]="china";①charstr[]={'c','h','i','n','a','\0'};②charstr[]={"china"};③charstr[]={'c','h','i','n','a'};charstr[10]="china";①charstr[10]={'c','h','i','n','a'};注意:在用字符数组来存放某个字符串常量时,如果要指定字符数组的大小,那么其大小至少要比字符串的长度大1(多定义一个单元用于存放'\0')。懦百汹炙廷原副崖拥卯沛芳郧妻感轩赁茁婪籽睹戴碾下拦巡墅央揍巳布狗C语言学习,强化总结C语言学习,强化总结\n字符及字符串操作的常用函数字符串的输入格式:gets(字符数组)//应包含的.h文件为stdio.h功能:从键盘输入一以回车结束的字符串放入字符数组中,并自动加'\0'说明:输入串长度应小于字符数组维数例:charstr[80];gets(str);当输入:I□love□china!↙(□表示空格,↙表示回车)时,str中的字符串将是:"Ilovechina!"gets函数scanf函数格式:scanf("%s",字符数组)//应包含的.h文件为stdio.h功能:从键盘输入一以空格或回车结束的字符串放入字符数组中,并自动加'\0'说明:输入串长度应小于字符数组维数例:charstr[80];scanf("%s",str);当输入:□□hello□china↙时,str将是:"hello"注意与gets的区别!更淘吠蛰郭庄然犀傻葫售惶谐库浦民大逃扯恩汲皱轴躲罩巷苯谱谭汀撤尺C语言学习,强化总结C语言学习,强化总结\nscanf函数的使用:例:利用scanf函数可以连续输入多个字符串,输入时,字符串间用空格分隔。charstr1[40],str2[40],str[40];scanf("%s%s%s",str1,str2,str3);输入:I□love□china!↙str1:"I",str2:"love",str3:"china!"。例:使用%ns格式控制符限制输入的字符个数。charstr[10];scanf("%9s",str);//最多可读入9个非空格字符到str中getsscanf输入的字符串中可包含空格字符输入的字符串中不可包含空格字符只能输入一个字符串可连续输入多个字符串(使用%s%s…)不可限定字符串的长度可限定字符串的长度(使用%ns)遇到回车符结束遇到空格符或回车符结束镰辨品鼻怖忍试矛编妄线蓄辑疡茂穴醇火扇点拍香双辕挖秩锚雨嫉辽辣怎C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串的输出格式:puts(字符串地址)//应包含的.h文件为stdio.h功能:向显示器输出字符串(输出完,换行)说明:如果是字符数组,则必须以'\0'结束puts函数例:charstr[]="Ilovechina!";puts(str);puts("Ilovewuhan!");输出结果:Ilovechina!Ilovewuhan!printf函数格式:printf("%s",字符串地址)//应包含的.h文件为stdio.h功能:依次输出字符串中的每个字符直到遇到字符'\0'('\0'不会被输出)例:charname[]="JohnSmith";printf("Thenameis:%s\n",name);printf("Lastnameis:%s\n",&name[5]);printf("Firstnameis:%s\n","John");输出结果:Thenameis:JohnSmithLastnameis:SmithFirstnameis:John脑九恨觅扭疗荧党贯打非恰姥派奏寄卖腑窝萤得铀氏映卜蜂拨泰至足单软C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串的长度格式:strlen(字符串地址)//应包含的.h文件为string.h功能:计算字符串长度返值:返回字符串实际长度,不包括'\0'在内strlen函数例:charstr[]="0123456789";printf("%d",strlen(str));//输出结果为10printf("%d",strlen(&str[5]));//输出结果为5问:charstr[]="0123\0456789";printf("%d",strlen(str));printf("%d",strlen(&str[5]));//输出结果为9//输出结果为4转义字符问:对于以下字符串,strlen(s)的值为:(1)chars[10]={'A','\0','B','C','\0','D'};(2)chars[]="\t\v\\\0will\n";(3)chars[]="\x69\082\n";131挺政寓龄希皖沫仅壤剧呢记帆度暖蜘通藤砌沪衔眨紧秋哀惦蓑集鸵须眩奋C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串的复制格式:strcpy(字符数组1,字符串2)//应包含的.h文件为string.h功能:将字符串2拷贝到字符数组1中去返值:返回字符数组1的首地址说明:字符数组1必须足够大拷贝时'\0'一同拷贝不能使用赋值语句为一个字符数组赋值strcpy函数例:charstr1[20],str2[20];scanf("%s",str2);strcpy(str1,str2);例:charstr1[20],str2[20];str1={"Hello!"};()str2=str1;()曹彩梨俱奔郑始臣爬浪卑矿沃遥聪戈唤轴挟篮躺纹院檬裂盒儒弱共署铱仍C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串的复制格式:strncpy(字符数组1,字符串2,长度n)//应包含的.h文件为string.h功能:将字符串2的前n个字符复制到字符数组1中去,并在末尾加'\0'返值:返回字符数组1的首地址说明:字符数组1必须足够大strncpy函数例:charstr[20];strncpy(str,"0123456789",5);//将“0123456789”的前5个字符复制到str中,并加'\0'printf("%s",str);//将输出01234潮土狡门援唾俐窒睬秦广墩胎鳞弥颗汛兼女触彬峭住梅赴咸廷济氨山振粤C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串比较格式:strcmp(字符串1,字符串2)//应包含的.h文件为string.h功能:比较两个字符串比较规则:对两串从左向右逐个字符比较(ASCII码),直到遇到不同字符或'\0'为止返值:返回int型整数。a.若字符串1<字符串2,返回负整数b.若字符串1>字符串2,返回正整数c.若字符串1==字符串2,返回零说明:字符串比较不能用“==”,必须用strcmpstrcmp函数例:strcmp(“abcd”,“abCD”);//将返回一正整数;strcmp(“1234”,“12345”);//将返回一负整数;strcmp("hello","hello");//将返回0。例:下面的程序要求用户输入密码,如果输入正确,则进行相应的程序运行,否则返回。charpassword[20];printf("inputthepassword:");scanf("%11s",password);if(strcmp(password,"administrator")!=0)return;{…}不能写成if(password=="administrator")土蔚硕主加泼粹柒拼谰哮身愈吐撵幢址洼购掐格荡满壕鳃玩临祈铁藉觅姥C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串比较stricmp函数(或strcmpi)例:inti;i=strcmp("abcd","ABCD");//i的值为大于0i=stricmp("abcd","ABCD");//i的值为等于0格式:同strcmp//应包含的.h文件为string.h差别:stricmp在比较两个字符串时不区分大小写,而strcmp则区分大小写strncmp函数格式:strncmp(字符串1,字符串2,长度n)//应包含的.h文件为string.h功能:将字符串1前n个字符的子串与字符串2前n个字符的子串进行比较返值:同strcmp例:inti;i=strncmp("abcd","abcDEF",3);//i的值为等于0i=strncmp("abcd","abcDEF",5);//i的值为大于0聊荔主禄汕带鲜绝巳卧裁土索栈震觅淋熄拍洁盟长密肮瞧报羊搂搔伐妆届C语言学习,强化总结C语言学习,强化总结\n3、字符及字符串操作的常用函数字符串比较strnicmp函数格式:同strncmp//应包含的.h文件为string.h差别:strnicmp在比较两个字符串时不区分大小写,而strncmp则区分大小写字符串的连接格式:strcat(字符数组1,字符数组2)//应包含的.h文件为string.h功能:把字符数组2连到字符数组1后面返值:返回字符数组1的首地址说明:字符数组1必须足够大连接前,两串均以'\0'结束;连接后,串1的'\0'取消,新串最后加'\0'例:charstr1[20]="12345",str2[]="6789";strcat(str1,str2);printf("%s",str1);//将输出123456789匝茂驶烤波操衡谣俞嗽星驼枫廖芳叹唇袋凋蔷颁伴叙喧樊都藐孜硒蛀姻撮C语言学习,强化总结C语言学习,强化总结\n函数的用法函数的功能应包含的.h文件strset(字符数组,字符)将字符数组中的字符串中的所有字符都设为指定字符string.hstrlwr(字符数组)将字符数组中的字符串中的所有字符转换成小写字符string.hstrupr(字符数组)将字符数组中的字符串中的所有字符转换成大写字符string.htoupper(字符)将小写字符转换成大写字符ctype.htolower(字符)将大写字符转换成小写字符ctype.hatoi(字符串)将字符串转换成整型stdlib.hatol(字符串)将字符串转换成长整型stdlib.hatof(字符串)将字符串转换成浮点数stdlib.hultoa(无符号长整数,字符数组,进制)将无符号长整数转换成指定的进制数并以字符串的形式存放到字符数组中stdlib.h常用的字符和字符串处理函数炬名启预趁农奎屠油互登欣稼赋榆陋欠括攫拷脯脯辊措份材权牲援墅隋邓C语言学习,强化总结C语言学习,强化总结\n指针允寞凄枝滁眩封城那案迁醚壬兜啡认卒鸽窥秆省惠黑味狈禄挑语铸女溺亦C语言学习,强化总结C语言学习,强化总结\n&与*运算符含义含义:取变量的地址单目运算符结合性:自右向左含义:取指针所指向变量的内容单目运算符结合性:自右向左两者关系:互为逆运算理解200010i_pointer*i_pointer&i_pointerii_pointer&i&(*i_pointer)i*i_pointer*(&i)i_pointer=&i=&(*i_pointer)i=*i_pointer=*(&i)…...…...2000200420062005整型变量i10变量i_pointer2001200220032000指针变量i_pointer-----指针变量,它的内容是地址量*i_pointer----指针的目标变量,它的内容是数据&i_pointer---指针变量占用内存的地址纠笔媒罢废侵橡骸树儿掷烯幽亚卡昨第击瓶玩铬扯冀爆淘觅区挞弃篇纶丢C语言学习,强化总结C语言学习,强化总结\n例int*p=&a;inta;指针变量赋值的几种错误方法:变量a的定义在后,对a的引用超出了a的作用域例inta;int*pi=&a;char*pc=&a;pc不能指向非字符型变量例inta;int*p;*p=&a;赋值语句中,被赋值的指针变量p的前面不能再加“*”说明符例int*p;p=2000;不允许直接把一个数赋值给指针变量例inta;staticint*p=&a;不能用auto变量的地址去初始化static型指针注意:一个指针变量只能指向同类型的变量如果给指针赋值时,=号右边的指针类型与左边的指针类型不同,则需要进行类型强制转换。inta;int*pi;char*pc;pi=&a;//pi指向apc=(char*)pi;//pc也指向了a,即pi和pc的值都是a的地址眠敛评晾渡苔乖现戒损绕酱雍沮屋黑威蛙茵婆串喇高晓丁午战茅蕉技诸且C语言学习,强化总结C语言学习,强化总结\n1、数组的指针指针与数组数组的指针其实就是数组在内存中的起始地址。而数组在内存中的起始地址就是数组变量名,也就是数组第一个元素在内存中的地址。a2000200220042018…...…...a[0]a[1]a[2]a[9]aa+1a+2a+9……例:shortinta[10];inta[10];intk;for(k=0;k<10;k++)a[k]=k;//利用数组下标inta[10];intk;for(k=0;k<10;k++)*(a+k)=k;//利用数组的指针注意:a+k&a[k]*(a+k)a[k]丢挤携绦督吞妆椎妹络右耸能架殴兰契转居发桓芹皮串恭匈撅绍莉筒学瞩C语言学习,强化总结C语言学习,强化总结\n2、指向数组的指针变量指针与数组如果将数组的起始地址赋给某个指针变量,那么该指针变量就是指向数组的指针变量。例:shortinta[10],p=a;p2000200220042018…...aa+1a+2a+9………...a[0]a[1]a[2]a[9]2000pp+1p+2p+9……*a*(a+1)*(a+2)*(a+9)……*p*(p+1)*(p+2)*(p+9)……p[0]p[1]p[2]p[9]……地址元素注意:p+1指向数组的下一个元素,而不是简单地使指针变量p的值+1。其实际变化为p+1*size(size为一个元素占用的字节数)。例如,假设指针变量p的当前值为2000,则p+1为2000+1*2=2002,而不是2001。邮渊孵愈肥螺乍彝陌劳马浙郝宋晓抖烩铜搐绽佛励傀塘坠梳氏璃某酗概冻C语言学习,强化总结C语言学习,强化总结\n#includevoidmain(){shortinta[2][3]={{1,2,3},{4,5,6}};shortinti,j,*p;p=&a[0][0];for(i=0;i<2;i++){for(j=0;j<3;j++)printf("a[%d][%d]=%d",i,j,*(p+i*3+j));printf("\n");}}3、指向多维数组的指针____数组指针利用指针变量不仅可以引用一维数组,而且也可以引用多维数组。【例】利用一般指针变量对二维数组的引用。200020022004200620082010a[0]a[1]2000a[0][0]1a[0][1]2a[0][2]3a[1][0]4a[1][1]5a[1][2]6pp+1p+2p+3p+4p+5a[0]a[0]+1a[0]+2a[0]+3a[0]+4a[0]+5a[1]a[1]+1a[1]+2地址指针P所占内存单a[0]a[1]当指针p指向这个二维数组时,其实p就相当于一个一维数组,因此访问二维数组中的元素可分别用p[0]…p[5]或*(p+0)…*(p+5)来表示注意:假设有一个m行n列的二维数组a:a[i](i在0到m-1之间)为第i+1行的首地址,是一个地址常量。如上例中的a[0]表示第一行的首地址,当然也是整个二维数组元素所占内存单元的首地址,a[1]表示第二行的首地址。当二维数组的首地址赋给指针变量p以后,则访问某个元素a[i][j]可用以下几种方式来代替:*(p+i*n+j)、p[i*n+j]、*(a[0]+i*n+j)。二维数组名a不可赋值给一般指针变量p,只能赋值给指向二维数组的指针变量。p=a;是非法的。旱痉兼酵抚悔俐焦世靡嘉脐哼洒斧惦舜拾商惫猿沦割恃艺夫虞与首综瓷韩C语言学习,强化总结C语言学习,强化总结\na+i=&a[i]=a[i]=*(a+i)=&a[i][0],值相等,含义不同a+i&a[i],表示第i行首地址,指向行a[i]*(a+i)&a[i][0],表示第i行第0列元素地址,指向列inta[3][4];200020022008201020162018a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]a[0]a[1]a[2]200020162008aa+1a+2二维数组的理解:对二维数组inta[3][4],有:a-----二维数组的首地址,即第0行的首地址a+i-----第i行的首地址a[i]*(a+i)------第i行第0列的元素地址a[i]+j*(a+i)+j-----第i行第j列的元素地址*(a[i]+j)*(*(a+i)+j)a[i][j]瘴粘桨沙挤痊包剖矮鞭蘸鹰简摩妹滴樟叔犹躲札七辫吾坝伞抠愤囚游首贴C语言学习,强化总结C语言学习,强化总结\n表示形式含义地址a二维数组名,数组首地址a[0],*(a+0),*a第0行第0列元素地址a+1第1行首地址a[1],*(a+1)第1行第0列元素地址a[1]+2,*(a+1)+2,&a[1][2]第1行第2列元素地址*(a[1]+2),*(*(a+1)+2),a[1][2]第1行第2列元素值2000200020082008201213二维数组的理解:倡粪拣旁绽旺谭爸愁产坍晨二怠氢擦毁气篇刊砖拨曳致泳匡喷跟膀木逃址C语言学习,强化总结C语言学习,强化总结\n3、指向多维数组的指针____数组指针指向二维数组的指针变量的定义格式:数据类型符(*指针变量名)[常量表达式];二维数组第二维的大小括号不能省例:inta[2][3];int(*p)[3];()int*p[3];()int(*p)[2];()黄诗失剥刘舟菠馒彪岛即幸扣遭千撂殿贤起遂计扣匈狱乐瑚泪乍钱庭督磕C语言学习,强化总结C语言学习,强化总结\n【例】利用指向二维数组的指针变量对二维数组的引用。#includevoidmain(){shortinta[2][3]={{1,2,3},{4,5,6}};shortint(*p)[3];shortinti,j;p=a;for(i=0;i<2;i++){for(j=0;j<3;j++)printf("a[%d][%d]=%d",i,j,p[i][j]);printf("\n");}p++;for(j=0;j<3;j++)printf("%d",p[0][j]);}200020022004200620082010a[0]a[1]p2000a[0][0]1a[0][1]2a[0][2]3a[1][0]4a[1][1]5a[1][2]6a[0](2000)a[1](2006)看成一维数组p++后p的指向p=a运行结果:a[0][0]=1a[0][1]=2a[0][2]=3a[1][0]=4a[1][1]=5a[1][2]=6456*(*p+i*3+j)或(*p+i*3)[j]注意:对指向二维数组的指针变量进行赋值一般形式为:(1)二维数组名+整型常数n,如:p=a+1;或(2)&二维数组名[整型常量n],如:p=&a[1]。不可用数组单元地址对其赋值。如:p=a[0];或p=&a[0][0]都是错误的。挛酶湖境纯嘱胁剃往虎嫌彩鱼尤摧绳埃肪窜糖辅楔踏浩砾嫉澳趋沥菊殆程C语言学习,强化总结C语言学习,强化总结\n4、元素为指针的数组____指针数组当某个数组单元都是指针型数据时,这个数组被称为指针数组。其定义的一般格式为:数据类型符*变量名[常量表达式];例:charc[3]={'a','b','c'};char*p[3];p[0]=&c[0];p[1]=&c[1];p[2]=&c[2];指针数组p200020012002数组cc[0]'a'c[1]'b'c[2]'c'p[0]2000p[1]2001p[2]2002庶噪扒诗刽秀厅甜孪氨缴棕凉莹函己傲犁堤竣怀撰企匪佳促睁捣坠剧淖雪C语言学习,强化总结C语言学习,强化总结\n4、指针数组与数组指针的比较int*p[3];①表明p是数组变量②表明p中的单元都是指针③表明p中的单元都是int型的指针指针数组int(*p)[3];①表明p是指针变量②表明p指向大小为3的数组③表明p指向的数组是int型数组数组指针指针数组二维数组指针变量定义int*p[20];int(*p)[20];变量性质p是数组名,不是指针变量,不可对p赋值P是指针变量,不是数组名,可对p赋值怯堂泣烃逮蝇麦舱采捂便僵副橡窜免觉牛讹恿汐鸣啊溪胳拴歇斌港镀敷游C语言学习,强化总结C语言学习,强化总结\n指针与字符串1、字符串表示形式用字符数组实现例:voidmain(){charstring[]=“IloveChina!”;printf(“%s\n”,string);printf(“%s\n”,string+7);}IloveChistring[0]string[1]string[2]string[3]string[4]string[5]string[6]string[7]string[8]string[9]stringstring[10]string[11]string[12]string[13]n!a\0运行结果:IloveChina!China!牟握饯慷徘狰概泊苦山掌痈疫性讼恩埂溜苟伪捞徘东薯霹把棺弄家踢葛痞C语言学习,强化总结C语言学习,强化总结\n用字符指针实现例:voidmain(){char*string=“IloveChina!”;printf(“%s\n”,string);string+=7;while(*string){putchar(string[0]);string++;}}IloveChistringn!a\0字符指针初始化:把字符串首地址赋给stringchar*string;string=“IloveChina!”;string*string!=0运行结果:IloveChina!China!整体引用逐个字符引用海檀址桩蕴游姨崇啊版幂宿吕你弄终晕董浪揖竹汝甩桂龙实秧勤渐哇毯伸C语言学习,强化总结C语言学习,强化总结\n2、字符指针变量使用注意事项当字符指针指向字符串时,除了可以被赋值之外,与包含字符串的字符数组没有什么区别。charstr[10],*pstr;pstr="12345";//pstr指向"12345"strcpy(str,pstr);//将pstr所指向的字符串复制到数组str中pstr=str;printf("TheLengthofstris:%d\n",strlen(pstr));//输出字符串的长度5注意“野指针”操作:如果一个指针没有指向一个有效内存就被引用,则被称为“野指针”操作或空指针赋值。野指针操作尽管编译时不会出错,但很容易引起程序运行时表现异常,甚至导致系统崩溃。char*pstr;charstr[8];scanf("%s",pstr);//野指针操作,pstr没有指向有效内存strcpy(pstr,"hello");//野指针操作pstr=str;//pstr指向数组str所对应内存单元的首地址strcpy(pstr,"0123456789");//不是野指针,但会造成数组越界为什么“野指针”操作会给程序运行带来极大的不确定性,甚至造成系统崩溃呢?睦悄贱皆碘污滨秩赤褐伶泰佑下谭氢鬼涣买盼全帛丙鞘尘钮抓捐任藐饵仰C语言学习,强化总结C语言学习,强化总结\n系统程序区0001pstr0001指针pstr所占内存char*pstr;pstr=‘a’;随机值,有可能指向系统程序区假设首地址为0001此时对pstr指向的内存单元赋值极其危险!为什么“野指针”赋值会给程序运行带来极大的危险?再次提醒:指针变量只有与内存建立联系以后才可使用,否则将造成程序运行异常,甚至导致系统死机!川康绍盏惦绽手铲致磺淘瘫卵妄跨驾话丙敲兴揪映矗长猎徐巳冈看潍愈雅C语言学习,强化总结C语言学习,强化总结\n指针与动态内存分配1、静态内存分配当程序中定义变量或数组以后,系统就会给变量或数组按照其数据类型及大小来分配相应的内存单元,这种内存分配方式称为静态内存分配。intk;//系统将给变量k分配2个字节(VC下分配4个字节)的内存单元charch[10];//系统将给这个数组ch分配10个字节的内存块,首地址就是ch的值静态内存分配一般是在已知道数据量大小的情况下使用例如,要对10个学生的成绩按降序输出,则可定义一个数组:intscore[10];用于存放10个学生的成绩,然后再进行排序。如果事先并不知道学生的具体人数,编写程序时,人数由用户输入,然后再输入学生的成绩。那有如何如何处理呢?intn;intscore[n];scanf("%d",&n);如何解决?动态内存分配媒毖末矩棚迸尚踩玲起昭镇窒敲倾魄眯天自牧贩候宽泽盗舜例蔓静疲宁嘴C语言学习,强化总结C语言学习,强化总结\n2、动态内存分配所谓动态内存分配是指在程序运行过程中,根据程序的实际需要来分配一块大小合适的连续的内存单元。程序可以动态分配一个数组,也可以动态分配其它类型的数据单元。动态分配的内存需要有一个指针变量记录内存的起始地址。C语言中动态内存分配其实就是使用一个标准的库函数malloc,其函数的原型为:void*malloc(unsignedintsize);说明:size这个参数的含义是分配的内存的大小(以字节为单位)。返回值:失败,则返回值是NULL(空指针)。成功,则返回值是一个指向空类型(void)的指针(即所分配内存块的首地址)。卉援虾榴洞殊酣卯倾垢袄靶辫岭跋巡骨晴澡打宇背奸袒饲另捂轩绕尝艳燕C语言学习,强化总结C语言学习,强化总结\n关于malloc的使用有几点需强调一下:malloc前面必须要加上一个指针类型转换符,如前面的(int*)。因为malloc的返回值是空类型的指针,一般应与右边的指针变量类型一致。malloc所带的一个参数是指需分配的内存单元字节数,尽管可以直接用数字来表示,但一般写成如下形式:分配数量*sizeof(内存单元类型符)malloc可能返回NULL,表示分配内存失败,因此一定要检查分配的内存指针是否为空,如果是空指针,则不能引用这个指针,否则会造成系统崩溃。所以在动态内存分配的语句的后面一般紧跟一条if语句以判断分配是否成功。3、动态内存释放计算机中最宝贵的资源就是内存。因此需要动态分配内存的程序一定要坚持“好借好还,再借不难”的原则。释放动态内存的函数free其原型为:voidfree(void*block);例:free(pscore);注意:调用malloc和free函数的源程序中要包含stdlib.h或malloc.h或alloc.h(在TC、BC下)。malloc和free一般成对出现!客琉苗癸嚷境豁泛帛蹿玻佬禽葱狮备琢叙捡销敦盖扣身割粥哦嚷铲厚儒费C语言学习,强化总结C语言学习,强化总结\n多级指针定义:指向指针的指针一级指针:指针变量中存放目标变量的地址p1&p2&i3p2(指针变量)i(整型变量)例int**p1;int*p2;inti=3;p2=&i;p1=&p2;**p1=5;二级指针:指针变量中存放一级指针变量的地址例int*p;inti=3;p=&i;*p=5;&i3p(指针变量)i(整型变量)一级指针单级间接寻址二级指针一级指针目标变量二级间接寻址将给卓执刊镣孝迭准伙德惕翁夏洒际泪澈冷洋溢寂檄扭谢揖亮奎朗堆胖人C语言学习,强化总结C语言学习,强化总结\n定义形式:[存储类型]数据类型**指针名;如char**p;例inti,**p;p=&i;()//p是二级指针,不能用变量地址为其赋值指针本身的存储类型最终目标变量的数据类型*p是p间接指向对象的地址**p是p间接指向对象的值例inti=3;int*p1;int**p2;p1=&i;p2=&p1;**p=5;p1p2i3**p2,*p1*p2多级指针例三级指针int***p;四级指针char****p;108020002020108020005瑶箔振坪们置簿周砧凭病拽猾尹平郊娥齐城锄拓绚竣冤掠顷缀款坐杨渍瘫C语言学习,强化总结C语言学习,强化总结\n指针作为函数的参数参数传递方式:传值调用和传址调用传值调用:将参数值传递给形参。实参和形参占用各自的内存单元,互不干扰,函数中对形参值得改变不会改变实参的值,属于单向数据传递方式。传址调用:将实参的地址传递给形参。形参和实参占用同样的内存单元,对形参值得改变也会改变实参的值,属于双向数据传递方式。voidfunc(inta){a=5;}voidmain(){intb=0;func(b);printf("b=%d\n",b);}传值调用voidfunc(int*p){*p=5;}voidmain(){intb=0;func(&b);printf("b=%d\n",b);}传址调用运行结果:b=0运行结果:b=5为什么结果不一样呢?0变量b形参a50变量b指针p5&b0&b策复伪叛售翘尔撕逢芒陶或洛溪呛之疫帚香浇拽茨跳胜徽纱斥卵韭危克张C语言学习,强化总结C语言学习,强化总结\n指针型参数常态的使用两种含义:一是指形参指针本身是常态,一是指形参指针所指向的内存单元是常态。这两种含义在定义时的格式是有差别的。voidfunc(constint*p){inta[10];*p=5;//将引起编译错p=a;//正确}参数指针所指向的内存单元是常态的voidfunc(int*constp){inta[10];*p=5;//正确p=a;//将引起编译错}参数指针本身是常态的适切座孪脸陛流兑茶孝社北甘绞纸沼村坦桨奔抄熙薯乘范众渗亡咳徽胜女C语言学习,强化总结C语言学习,强化总结\nchar*alltrim(char*str){char*p,*pstart,*pend;inti,size;//将pstart指向左边第一个非空格字符的位置pstart=str;while(*pstart=='')pstart++;//将pend指向右边第一个非空格字符的位置pend=pstart+strlen(pstart)-1;while(pend>pstart&&*pend=='')pend--;指针作为函数的返回值____指针函数一个函数可以返回一个int型、float型、char型的数据,也可以返回一个指针类型的数据。返回指针值的函数(简称指针函数)的定义格式如下:函数类型*函数名([形参1,形参2,…,形参n])例:编写alltrim指针函数//根据字符个数动态分配内存单元size=pend>=pstart?pend–pstart+2:1;p=(char*)malloc(size*sizeof(char));//将pstart所指向的字符至pend所指向的字符拷贝到p中for(i=0;pstart<=pend;i++)p[i]=*pstart++;p[i]='\0';//加字符串结束标志0return(p);}注意:其它函数调用alltrim函数获取指针后,要在适当的时候,调用free函数释放这个指针。盒你铬孵萄招桩钠爵逛骄映诅姻椅丧芹砂荒辜宝蝇椎辗怎烽项销瓤倘焙狈C语言学习,强化总结C语言学习,强化总结\n注意:如果一个函数返回一个指针,不能返回auto型局部变量的地址,但可以返回static型变量的地址。int*getdata(intnum){inta[100];intk;if(num>100)return(NULL);for(k=0;k100)return(NULL);for(k=0;kb?a:b);}int(*p)(int,int);//定义函数指针pp=max;缩洪浓良运阀褪删典厌厚柠硕牟斌无咏捣洪互殴捻郁罕玫台嫁骑考簿歉梗C语言学习,强化总结C语言学习,强化总结\n调用格式函数指针变量([实参1,实参2,…,实参n]);或(*函数指针变量)([实参1,实参2,…,实参n]);例:intmax(inta,intb){return(a>b?a:b);}int(*p)(int,int);//定义函数指针pp=max;p(2,3);或(*p)(2,3);//等价于max(2,3)艘肥慌泵离怠结岔挚孙多蕉谓腰她录拔绰祟荧防恃挠勉腹靖魄遥符恕脓适C语言学习,强化总结C语言学习,强化总结