郝斌C语言详细笔记附源码

上传人:cn****1 文档编号:576337669 上传时间:2024-08-19 格式:PDF 页数:125 大小:13.79MB
返回 下载 相关 举报
郝斌C语言详细笔记附源码_第1页
第1页 / 共125页
郝斌C语言详细笔记附源码_第2页
第2页 / 共125页
郝斌C语言详细笔记附源码_第3页
第3页 / 共125页
郝斌C语言详细笔记附源码_第4页
第4页 / 共125页
郝斌C语言详细笔记附源码_第5页
第5页 / 共125页
点击查看更多>>
资源描述

《郝斌C语言详细笔记附源码》由会员分享,可在线阅读,更多相关《郝斌C语言详细笔记附源码(125页珍藏版)》请在金锄头文库上搜索。

1、郝斌老师的c语言:课堂讲解全程动手敲代码,讲解细致,对于重要知识点的讲解不厌其烦,是一个难得的C语言入门教程。在这里对老师的辛勤付出表示感谢。郝斌C语言视频教程概述:课程计划为什么学习C语 言:第一代语言第二代语言I 机器语言 Fortran语言主要用于科学计算,在第三代语言中,以1980年为分水岭,分为结构化和面向对象语言。Basic语言是vb 的前生,pascal语言一般是用于教学。C 语言是最重要的,其他的语言一般很少用了。结构化的代表语言是c 语言。 结构化语言的数据和操作是分离的,导致在写大项目的时候,会出现各种各样莫名其妙的问题。在面向对象的语言中C+是最复杂的语言。由于C+语言太

2、复杂,sun公司对C+进行了改装,产生了 java语言。而c#是由微软开发的,和java相似,几乎一模一样。 高级语言: a + b 汇编语言 AD D AX, BX 机器语言 0000 0001 1101 10000在高级语言的执行速度上,C是最快的,C+其次, 而java和c#是最后的。Java和c#流行,主要的一个原因是可C语言的发展和过程:产生时间:1972-1973 产生地点:美国贝尔实验室(Bell) 创始人:D ennis.M. Ritchie和 Ken .Thompson 目的: 改写UNIX操作系统 C语言发展过程 1983年 ANSIC 1987年 ANSI C 87 19

3、94年 C99C 语言的特点:优点:代码量小,速度快,功能强大。缺点:危险性高,开发周期长,可移植性弱。危险性高:写同一个程序,在 java中会报错,而在c 中不会报错,为什么呢,因为c 认为程序你想怎么写就怎么写,c 语言认为你写的程序不是很离谱,他都认为你写的这个程序有特殊的含义。可以直接通过,而 java则不可以。开发周期长:c 语言是面向过程的语言,面向过程的语言的特点就是在开发大项目的时候,很容易崩溃,好比盖大楼, C 语言还要造大量的砖块、 钢筋等结构原材料,而 C+ C# JAVA则进行了一定的继承封装等操作,相当于原材料直接给你,你只需要用它盖楼即可、现在市场上的语言分三块C/

4、C+:单纯的学习c 是什么都做不了的。JavaC#可移植性不强:这是针对java来说的,因为java的可移植性太强了,所以就感觉说c 的可移植性不强。金山公司最主要是靠wps办公软件来发展的。Wps是 c语言开发的,其安装包比Office少了 10多倍。三大操作系统:windows, unix, linuxWindows内核是c 语言写的,而外壳是C+写的。Java永远不可能写操作系统。因为java运行速度太慢了。而 linux和 unix都是纯c 写的。操作系统控制了硬件,如果说操作系统的运行速度慢,那么当我们在运行软件的时候,运行速度会更慢。为什么使用c 语言写操作系统呢,首先是因为c 的

5、运行速度快,然后是因为c 可以直接控制硬件,而其他语言不可以。没有指针的语言是不能直接访问硬件的。C 语言的应用领域:系统软件开发 操作系统:Windows Linux、Unix 驱动程序:主板驱动、显卡驱动、摄像头驱动 数据库: D B2、Oracle、Sql Server应用软件开发 办公软件:Wps 图形图像多媒体:ACD See PhotoshopMediaPlayer 嵌入式软件开发:智能手机、掌上电脑 游戏开发:2D 、3D 游戏驱动一般是用c和汇编来写的。数据库一般是用c和C+来写的C语言的重要性: 有史以来最重要语言 所有大学工科和理科学生必修课程 最重要系统软件:window

6、s、linux、unix均使用c开发 一名合格黑客必须掌握的语言 任何一个想终身从事程序设计和开发人员必须熟练掌握的语言 大企业、外企招聘程序员必考的语言 为学习数据结构、 C+、Java、C#奠定基础虽然应用场合相对较窄,但贴近系统内核,较底层。病毒最基本的是要感染系统,数据结构,C, C+这三门语言是必须要学习的。牛人牛语:入门最基本的方法就是从C语言入手。当你成为c语言的高手,那么就你很容易进入到操作系统的平台里面去;当你进入到操作系统的平台里去实际做程序时,就会懂得进行调试;当你懂得调试的时候,你就会发现能轻而易举地了解整个平台的架构。这时候,计算机基本上一切都在你的掌握之中了,没有什

7、么东西能逃得出你的手掌心 一 编程箧言梁肇新怎样学习C语言要将编程当成一项事业来经营,而不是糊口的工具。多思考,多上机。 不能光看,光听,而要排错,调试。在犯错误中成长。参考资料 谭 浩 强 C语言程序设计清华 The C programming language 机械JL业 (C Primer Plus60元人名邮电 C和指针65元 人名邮电 C专家编程绝版 C陷阱与缺陷人名邮电30 C科学与艺术 机械工业王爽写的C+也很不错学习的目标:掌握简单的算法- 解决问题的方法和步骤。熟悉语法规则。能看懂程序并调试程序。C语言的关键字:32个 关 键 字 : ( 由系统定义,不能重作其它定义)aut

8、obreakcasecharconstcontinuedefaultdodoubleelseenumexternfloatforgotoifintlongregisterreturnshortsignedsizeofstaticstructswitchtypedefunsigned unionvoidvolatilewhileC语言程序的格式:# include int main( void)IIreturn 0:)一定要养成良好的习惯:代码规范边 写 边 保 存 ,括号成对出现,应用空格VC6.0软件操作:新 建 保 存 关 闭 ( 关闭空间).cpp是原始文件,可单独拷贝到其它电脑。第二讲

9、:(14) c语言编程必备知识1 . C p u ,内存条,硬盘,显卡,主板,显示器之间关系。Cpu不能直接处理硬盘上的数据,必须要先调入内存2 . Hello word程序是如何运行起来的。3 . 什么是数据类型数据类型- 数据的分类,对编程而言,首要考虑问题是数据的输入和存储。可以分为A:基本数据类型:整型整型int - 4 字节 一字节byte = 8 位 bit短整型 short int -2长整型long int -8浮点型单精度浮点数float:存 储 范 围 小 -4双精度浮点数double:存储范围大-8Float和 Double都不能保证将小数完全准确保存。字符char: c

10、 语言中是没有字符串string -1( 区别于JAVA、C#中有string且 C#中 char为 2 字节)B:复合类型:就是把基本类型拼凑在一起结构体枚 举 - 实用共用体一基本淘汰4 . 什么是变量变量的本质是内存中一段存储空间。Int I; i=5; I是变量,程序向系统申请了一个内存单元,在程序运行中,i的值可以改变,但程序结束后,其所占的空间不是释放,而是被系统收回权限。5 C p u ,内存条,VC+6.0,操作系统之间的关系。6变 量 为 什 么 必 须 初 始 ( 即赋值)软 件 运 行 与 内 存 关 系 ( 垃圾数据-9868598658)1 .软件在运行前需要向操作系

11、统申请存储空间, 在内存空间足够空闲时, 操作系统将分配一段内存空间并将该外存中软件拷贝一份存入该内存空间中, 并启动该软件运行。2 .在软件运行期间, 该软件所占内存空间不再分配给其他软件。3 .当该软件运行完毕后, 操作系统将回收该内存空间( 注 意 : 操作系统并不清空该内存空间遗留下来的数 据 ) , 以便再次分配给其他软件使用。 操作系统一门课中系统分配表中会讲到, 用1标记表示内在是被占用的,用 。标记表示是空闲的。综上所述, 一个软件所分配到的空间中极可能存在着以前其他软件使用过后的残留数据, 这些数据被称 之 为垃圾数据、 所以通常情况下我们为一个变量 ,为一个数组,分配好存储

12、空间之前都要对该内存空间初始化。7如何定义变量数据类型变量名称=赋予的值;等价于数据类型变量名;变 量 名 =要赋予的值;举例子:int i = 3 ;等价于 int i; i = 3;Int i, j;等价于 in ti; in tj;Inti, j=3 等价于 int i; in tj; j=3;Int I =3, j = 5;等价于 int i; in tj; I = 3; j = 5;8什么是进制- 逢几进一我们规定八进制前面加0 ( 零) ,十六进制前面加Ox。在 汇 编 中 : 在 数 学 后 加 字 母 表 示 二 吐 制 数 , 加学李 。表 示 入 盘 制 教 , 加 字 母

13、D表 示 十 迷 制 戴 , 加 字 母H表示十六进制 教 。例:1011B为二进制数1011,13570为八进制数13S7,也 记 为(1011) 2也 记 为(1357) 2049D为十进制数2049,也 记 为(2049 ) 103FB9H为十六进制数3F B 9,也i己为( 3FB9 )16什么叫n进制 八 进制 8个 基 数 逢8进一 基数: 0 1 2 345 6 7 8- 10 9- 11 10-12十六进制: 16个 基 数 逢16进一 基数: 0 1 2 3 4 5 6 7 8 9 A B C E F 或 012 3 4 5 6 7 8 9 a b e d e f 16- 1

14、0 17-11 18-12 19-13常用计数制对照表:常用计数制对十进制(D )二进制(B)八进制(0)十六进制(H)片工溟建二3987654321001101110010111011110001001101010111100110111101111711615141312110 77 6544. 3一 2d 一 10一 dC bp) 987654321。昭八、 、f表1L1JPrintf的基本用法:p r i n t f (, zi = % d n ,i ) ;/ *p r i n t f 的用法% d 表示以十进制输强% * 或% 乂表示以十六遵制输| 出% 。 表示以八进制输出9常 量

15、 在c中是如何表示的. . . , . . 9 W . 一整数十进制: 传统的写法十六进制: 前面加Ox或0X八进制: 前面0注意是数字零不是字母。浮点数传统的写法float x = 3. 2;传统科学计数法float x = 3. 213; x的值是 3200float x = 123. 45e-2; /x的值是 1.2345I字符当个字符使用单引号括起来, 多个字符串使用双引号括 起 来 ( 指 针 、数 组 ) 。i n t m a i n ( v o i d )(f lo a t x = 1 2 3 . 4 5 e - 2 F |;p r i n t f (/ z% f nv, x )

16、 ;r e t u r n 0 ;在c中,默 认 是double类 型的。在 后 面 加F表示当做flo a t来处理, 否则会有警告提示- - 丢失部分字节。10常量以什么样的二进制代码存储在计算机中?编码:整数是以补码的形式转换为二进制代码存储在计算机浮点数是以ieee754标准转换为二进制代码存储字符本质实际是与整数的存储方式相同,ASII码标准。第三次课:代码规范化 可以参考林锐 高质量C/C+编程 代码的规范化非常的重要, 是学习一门编程语言的基础,代码可以允许错误,但不能不规范。例如:成对敲括号 ( )加空格于运算符和数字之间1 = 1 + 2;加缩进分清上下级地位。换行- - 进

17、行功能区域分隔o r什括号单独成一行。 代码规范化的好处1:整齐,别人和自己都容易看懂。2:代码规范了,代码不容易出错。3: 一般的程序可以分为三块:a :定义变量b:对变量进行操作C :输出值什么是字节存储数据的单位,并且是硬件所能访问的最小单位。内存中存储的最小单位是位bit(O或 1 ) ,但是硬件控制的时候不能精确到位,只能精确到字节( 8 位) ,是通过地址总线来控制的,而精确到位是通过软件来控制的,叫做位运算符来精确到位的。1 字 节 = 8 位 1K= 1024字节1M = 1024 K 1G =1024 M 1T = 1024 G2G 的内存条的总空间: 2 *1024 * 1

18、024 *1024 * 8 =4*1032不同类型数据之间相互赋值的问题不同数据类型之间最好不要相互转换。int i = 45;long j = 102345;i = j;printf (*%ld %dn*, i , j);float x = 6. 6,double y = 8. 8,printf(*%f %lfn , x, y);int i = ;如果需要明白这个知识点,那么需要明白补码。什么是ASCII码以 char定义变量的时候,只能使用单引号括起一个字符才是正确的。力 include int main(void)_(char ch = A , 4行 OK 等价 char c h , 小

19、二 A/ char ch = AB” , /error因为AB是字符串, 我们不能把字符串赋给单个字符/ char ch - A; /error/ char ch = AB , AB是错误的/ char ch = J /error,因为ch变量已经在4行定义了, 这样会导致变量名被:ch = 。 ,printf (*%cn*, ch);在上图中注释的最后一样是重复定义了 c h 的值,是错误的, 而下面的ch = c,是指把C赋值给ch ,是正确的。U include ch );return 0;上图中输出的值是98(将字符以整数d 的形式输出)Ascii码规定了 ch是以哪个值去保存,asc

20、ii码不是一个值,而是一种规定,规定了不同的字符是以哪个整数值去表示。其它规定还有GB2312 UTF-8等。1 4 .什么是ASCIIASCII不是一个值,而是一种规定,ASCII规定r 了不同的字符是使用哪个整数值去表示它规定了 1A, 65B 66, a 97b, 98O 48字符本质上与整数的存储方式相同【 字符的存储】基本的输入和输出函数的用法:第三次课Printf ( )将变量的内容输出到显示器上。四种用法1 . printf ( 字符串 ) ;2. printf ( 输出控制符二 输出参数) ;3. printf( 输出控制符1输出控制符2。: 输出参数1,输出控制符和输出参数的

21、个数必须一一对应4. printf ( 输出控制将 非输出控制符 , 输出参数) |;输什么是输出控制符,什么是非输出控制符输出控制符包含如下:%dint%ldlong int%cchar%ffloat%lfdouble%x( 或者% X后者 #X)int 或 long int 或 short int%o同上%s I字符串1Printf为什么需要输出控制符: 0 1 组成的代码可以表示数据也可以表示指令。必须要有输出控制符告诉他怎么去解读。如 果 0 1 组成的代码表示的是数据的话,那么同样的0 1 代码组合以不同的格式输出就会有不同的输出结果,所以必须要有输出控制符。t t i n c l

22、u d e i n t m a i n ( v o i d )(i n t x = 4 7 ; / / 1 0 0 是十进制p ri n t f ( * % x n* , x ) ; 输出结果是: 2 fprintf x ) ; / / 输出结臬是: 2 Fprintf (耕X n , x ) ; 输出结果是: O X 2 F |printf ( * % # x n* , x ) ; 输出结臬是: 0 x 2 freturn 0 ;在上图中,int x = 4 7 ,如果前面加0 ( 零 ) 048表示的是八进制,如果前面加Ox ( 零x) 0X47则表示的是十六进制,而在输出的时候,则 是

23、。 ( 字母。 ) 表示八进制,ox( 字母。 ,x ) 表示十六进制。非输出控制符:非输出控制符在输出的时候会原样输出。printf (*i = %d, j = %dn*, j, k);Scanf ( ) 通过键盘将数据输入到变量中有两种用法:用 法一:scan f ( 输入控制符二 输入参数) ;功 能 : 将从键盘输入的字神转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中|示例:# inc lud e int ma in( void )(int i;sc a nf(V, & i) ; / / & i表示i的地址&是一个取地址符printf ( i = % d n”

24、, i) ;)return 0 ; |非输入控制符:在输入的时候也会原样输入。用法二:scan f ( 非施入控制符愉入控制符 , 输入参数) ;功能: 将从键盘输入的字符转化为检入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中非输入控制符必须原样输入# include int m ain(void)(int i ,scanf(m%d, & i),p rin tf (*i = %dn, i)return 0;但是强烈建议:在使用scanf的时候,不使用非输入控制符。给多个变量赋值:# include int main (void)(int i, j;scanf (*%d %d”,

25、 &i, &j) ; Tp rin tf (*i - j = %dn”, i, j);return 0;)需要记住,非控制符需要原样输入。如何使用scanf编写出高质量代码如何使用s c a n f编写出高质量代码1 .使用s c a n f之前最好先使用p r in t f提示用户以什么样的方式来输入2 . s c a n f中尽量不要使用非输入控制符, 尤其是不要用n|S inc lud e int ma in( void )int i;% c a nf( / d n ,& i) ; 非常不好的格式,不 要 加 nprintf ( i = % d n” , i) ;return 0 ;3.

26、应该编写代码对用户的非法输入做适当的处理【 非重点】whi le ( (ch = getchar () ) ! = n )cont in u e ; |S inc lud e int ma in( void )int i;c ha r c h;sc a nf( % d , & i) ;printf ( i = % d n” , i) ;I /A .while ( ( c h= getc ha r ( ) ) ! = n ), / c ontinue;int j;sc a nf( % d , & j) ;printf ( j = 9 G d M , j) ;return 0 ;)运算符:算术运算

27、符:加 ( + ) , 减 ( 一 ) 乘 ( * ) 除 ( / ) 取 余 ( )关系运算符: , = , , 二,! 二 ,逻辑运算符:!( 非) ,& & ( 且) ,| | ( 或)真真假假假真真真假!(非)&也(并且)|(或)!真 假!假真也也真真也也假假也&真假&假真II假假II真真II真假I I假C语言对真假的处理非零是真零是假 T真是1表示假是。表示底也左边的表达式为假 右边的表达式肯定不会执行I |左边的表达式为真|右边的表达式肯定不会执行赋值运算符: I _ * /, T一 , 一,/一例如:a+=3是等价于a=a+3, a/=3等价于a=aR其优先级别是算术关系逻辑赋值

28、。 除法与取模运算符除法/ 的运算结果和运算对象的数据类型有关,两个数都是hit,则商就是in t,若商有小数,则截取小数部分; 被除数和除数中只要有一个或两个都是浮点型数据,则商也是浮点型,不截取小数部分。如:16/5 = 3 16/5.0 = 3.20000 -13/4 = -4-131-3 = 4 3/5 = 0 5/3 = 1最典型的例题就是求s=1+1/2+1/3+1/4+1/5。. +1/100的值( 具体程序我们以后再讲) .取余的运算对象必须是整数,结果是整除后的余数,其余数的符号与被除数相同如 13%3 =j=1 13%-3 = 1 -13%3 = -1-13%23 =-13

29、 3 % 5 = = 3测试取模运算符的例子 .1 . # include 2. int main(void)3. (4. printf(%d %d %d %d %d %d 13%-31 13%3, 3%5);5. return 0;6. 7. r8. 输出结果是:9 *10. 0 1 -1 -1 -13 3it Press any key to continueI) * *13. 总结,取余的运算对象必须是斟t结果是瞬后的余数,其余数的符号与祓I线 相 同14. */取余的结果的正负只和被除数有关。第四节流程控制( 第一个重点) :1 .什么是流程控制程序代码执行的顺序。2 .流程控制的分类

30、顺序执行选择执行定义:某些代码可能执行,可能不执行,有选择的执行某些代码。分类:if1 .2 .3 .4 .5 .6 .7 .建最简单的用法if的范围问题if. . else.的用法if. . else if. . . else.的用法C语言对真假的处理if举例一求分数的等级if的常见问题解析If最简单的用法:1 . if最简单的用法格式:if ( 表达式)语句功能:如果表达式为真,执行语句如果表达式为假,语句不执行# i n c l ud e i n t m a i n ( vo i d )i f ( 3 )p ri n tf ( A A A A n ) ; / / 会输出i f ( 0 )

31、p ri n tf ; 不会输出i f ( 0 = = 0 )p ri n tf ( C C C C n ) ; 会输出re turn 0 ;2. i f的范围问题1 .i f ( 表达式)语句A;语句B ;解释:i f默认只能控制语句A的执行或不执行i f无法控制语句B 的执行或不执行或者讲:语句B 一定会执行i f 林认的只能控制一个语句的执行或不执行i f ( 表达式)(语句A;语句B ;)此时i f可以控制语句A和语句BI由此可见:i f默认只能控制一个语句的执行或不执行如果想控制多个语句的执行或不执行就必须把这些语句用 括起来|如果想控制多个语句的执行或者不执行, 那么需要使用 括起

32、来。3.i f. else.的用法:# i n c l ud e i n t m a i n ( vo i d )i n t i j ;sc a n f ( % d % d T , & i , & j ) ;i f ( i j )p ri n tf ( i大于 j n ) ;e l sep ri n tf ( i小于 j n ) ;re turn 0 ;)# i n c l ud e i n t m a i n ( vo i d )i f ( 1 | 2 )p ri n tf ( A A A A n ) ;e l sep ri n tf ;p ri n tf ( C C C C n ) ;re

33、 turn 0 ;if.else if.else 的用法:if (1)A;else if (2)比else if (3)C;elseD;# i n c l ud e i n t m a i n ( vo i d )(d o ub l e d e l ta = 3 ;i f ( d e l ta 0 ) Ip ri n tf ( 看两个解八n ) ;e l se i f ( d e l ta = = 0 )p ri n tf ( 有一个唯一解! n * ) ;e l sep ri n tf ( 无解! n f ) ;re turn 0 ;C 错误的 if.else if.else 语句:S i

34、n c l ud e i n t m a i n ( vo i d )d o ub l e d e l ta = 1 ;i f ( d e l ta 0 )p ri n tf ( 看两个解! 、 n ) ; p ri n tf ( 哈哈! n ) ;e l se i f ( d e l ta = = 0 )p ri n tf ( 有一个唯一解! n ) ;e l sep ri n tf ( 无解! 、 n ) ;re turn 0 ;在上图中,当执行到哈哈那句时, 下面的else将会被算作另外一个语句来执行,而在我们的c 语言中,没有以else开头的语句。所以会出错。I f 实例:# i n

35、c l ud e i n t m a i n ( vo i d )(f l o a t sc o re ; / / sc o re分数p ri n tf ( 请输入您的考试成绩: );sc a n f ( % f ” , f e sc o re ) ;i f ( sc o re 1 0 0 )p ri n tf ( 这是做梦! n) ;e l se i f ( sc o re = 9 0 & & sc o re = 1 0 0 ) / / 不能写成 9 0 = sc o re = 8 0 & & sc o re = 60 & & sc o re = 0 & & sc o re 60 )p ri

36、 n tf( 不及格!继续努力! n T ) ;I f常见的问题:变量的替换:i n t t: 定义临时变显, / 6和7行代码无法完成i和j的互换7 i = j ; / / 6i r i = 5 ; j = 5 ;/ / j = i : , 行 i = 5 : j = 5 :I正确的/ |: 换1和) 的方法|t = i :i = j :j = t;p ri n tf ( i = % d , j = % d n ” , i , j ) ;re turn 0 ;求三个数字的大小:in t a, b, c; 等价于: in t a; in t b; in t c;in t t ;P rin tf

37、(, , 请输入三个整数(巾间以空格分隔):“ );scanF(%d %d, &a, &b, &c);编写代码完成a是 最 大 值b是 中 间 值c是最小值i f (a b)i f (a c)i f (b c)printFC d %d Zdn,a, b, c );return 0;c语言常见误区:纸老虎素数:只能被1和自己整除的数,如1,5,9等。回文数:正着写和倒着写一样的数。如1221,121,等编程实现求一个十进制数字的二进制形式:求一个数字的每位是奇数的数字取出来组合形成的新数字。求一个数字到过来的数字。1:如果不懂,那么就看答案。看懂答案在敲。没错误T,在尝试改。如何看懂一个程序:1

38、 .流程:2 . 每个语句的功能:3 .试数:对一些小算法的程序:1 .尝试自己编程结局。2 . 解决不了,看答案。3 .关键是把答案看懂。4 .看懂之后尝试自己修改程序,且知道修改之后程序的不同输出结果的含义。5 . 照着答案去敲6 . 调试错误7 . 不看答案,自己独立把程序编出8 . 如果程序实在是彻底无法了解,就把他背会。空语句的问题:7 . i f 的常见问题解析1 . 空语句的问题i f ( 3 2 ) ;等 价 于 Ii f ( 3 2 ); 这是一个空语句i n t m a i n ( v o i d )i f ( 1 2 ) .p n n tf ( A A . n ) ;p

39、r i n tf ( B B B B r T ) ;r e tur n 0 ;1在上图中,最终的结果会是AAAA,BBBB,程序也不会报错,为什么呢,因为在程序执行的时候,会在;哪里认为是一个空语句。也就是说,如果if成立,那么执行空语句。If常见错误解析( 重点)S i n c l ud e i n t m a i n ( v o i d )(i f ( 3 2 ) 4 行 如果这里加分号,则会导致程序编译到6 行时就会出错p r i n tf (哈哈! n ) ; l se 6 行p r i n tf (嘿嘿! n ) ;r e tur n 0 ;)上面这个程序是错误的,为什么呢,在该程序

40、中,总的有4个语句, 而在以else开头的那个语句中是有错误的,因为在c语言中是没有以else开头的这种语法。i f ( 表达式1 )A;e lseB ;是正确的i f ( 表达式1 ) ; | IA :e lseB ;是错误的# i n c l ud e i n t m a i n ( v o i d )(i f ( 3 2 )p r i n tf ( A A A A n ) ;e l se i f ( 3 1 )p r i n tf ( B B B B n ) ;e l se Ip r i n tf ( C C C C n ) ;r e tur n 0 ;在上面这个程序中,最终的值是AAA

41、A,虽说后面的31也满足条件, 但是当32满足条件后,该 if语句就会终止,后面的语句是不会在执行的。if ( 表达式1)A;else if ( 表达式2)B;else if ( 表达式3)C;这样写语法不会出错,但逻辑上有漏洞if ( 表达式1)A else if ( 表达式2)B;else if ( 表达式3)C;else1( 表达式4) 7行D;这样写是不对的,正确的写法是:要么去掉7行的( 表达式4)要么在else后面加if|既然7行要写表达式,就要写if。if ( 表达式1)A else if ( 表达式2)B;else if ( 表达式3)C; Telse ( 表达式4) ; 1D

42、;这样写语法不会出错,但逻辑上是错误的e lse ( 表达式4 );D ;等价于e lse( 表达式4 );D ; I循环的定义、分类。定义:某些代码会被重复执行。分类:for while do.while# include int main(void)(int i ;int sum = 0, 一I H 3for (i = l , i=4|, +i)sum = s / + i;牛printf(*sum = %dn*, sum),return 0,在上图中,先执行1 , 在执行2, 2 如果成立,标志着循环成立,那么在执行4 , 最后在执行3, 3 执行完后代表一次循环完成,然后在执行2. 以此

43、类推。1 永远只执行一次。+ + I等 价于i+1求 1-10的所有奇数的和:# i n c l ud e i n t m a i n ( v o i d )i n t i ;i n t sum = 0 ;f o r ( i = l ; i 1 0 ; i + = 2 ) / / i + = 2 ;等价于 i = i + 2 ;(sum = sum + i | ;r e tur n 0 ;)求 1-12之间的所有能被3 整除的数字之和:i n t sum = 0 ;f o r ( i = 3 ; i = 1 2 ; + + i )(i f ( i % 3 = = 0 ) / / 如 果 i 能

44、被3 整除sum = sum + i ,p r i n tf ( * sum = % d n , sui r |) ;r e tur n 0 ,For所控制的语句:h i n c l ud e i n t m a i n ( v o i d ) Ii n t i ;f o r ( i = l ; i 4 ; + + i )(p r i n tf ( A A A A n ) ;p r i n tf ( B B B B n ) ;r e tur n 0 ;)在上图中,fo r默认只能控制一个语句,但是如果要控制多个语句时候,那么需要使用 把语句括起来。求 14-1/2+1.V100 的和# i n

45、 c l u d e i n t m a i n ( v o i d )i n t i ;f l o a t s u m = 0 ;f o r ( i = l ; i i= l 1 i=2 2 i=3 3=100 1sum=l+l/2. 0+1/3. 0 +i i=4-L浮点数存取:浮点数的存错所带来的问题f lo a t和double都不能保证可以精确的存储一个小数举例:|有个浮卓型变量X, 如何判断x的值是否是零i f (|x -0 . 0000011 0. 000001)是零e lse不是零为什么循环中更新的变量不能定义成浮点型求1-100之间所有奇数的和:# include int m

46、ain(void)int i;int sum = 0;for (i = l; i101; +i) Iif (i%2 = 1)sum += i;/ sum = sum + i;),printf(sum = %dn” , sum);return 0;求1-100之间的奇数的个数:# i n c l u d e i n t m a i n ( v o i d )(i n t i ;i n t e n t = 0 ; / / 个数一般用e n t表示f o r ( i = l ; i 1 0 1 ; +i )i f ( i %2 = = 1 )+c n t ;)p r i n t f ( e n t

47、= %d n ” , e n t ) ;求1 - 1 0 0之间奇数的平均值:int i;int sum =int ent =float avg,oo/average的缩写for (i=l; i/ / 奇数和/ / 偶数和oO)=i12ommV;uu(Xissitttannntfor (i=l; i101; +i) Iif (i%2 = 1)(suml += i;)else(sum2 += i ; |)printf ( 套数 和 =%dn, suml);printf ( 隅数加=%dn, sum2);多个for循环的嵌套使用:多个for猛环加版需使用for (1; 2; 3) /Ifor (4

48、; 5; 6) /2A, /3B; /4整体是两个语句,1 2 3是第一个语句4是第二个语句整体是两个语句。上图中,先执行1,在执行2 , 如果2 成立,执行4,在执行5 , 如果5 成立执行A,在执行6 , 在执行5 , 如果 5 不成立,意味着里面的循环结束,然后执行3 , 在执行2 , 如果2 成立又执行4 , 在执行5 , 如果5 成立在执行6 , 在执行5 , 如果5 不成立,在执行3 , 在执行 2 , 如果2 不成立,意味着本次循环结束,在执行B,在上图中,需要注意的是,如果2 成立的话,那么每次4 都需要执行。for (1; 2; 3)for (4; 5; 6)A;B;)整体是

49、L个语句for (4; 5 ; 6)C;)整体是一个语句|进制之间的转换:如 234为 5 进制,那么转换成10进制是多少:2x5x5+3x54-4的值就是转换成的10进制。234e是 16进制,转换成2 进制是多少:2x16x16x16+3x16x16+4x16+12 的值就是转换成 10 进制的值。注意上面的规律。那么把十进制转换成r 进制呢, 其实很简单, 就是把10进制数除以r,直到商是。的时候。然后取余数,余数倒序排列:(185) 0 = ( ? ) 2 2 1 8 5 余数( 3 9 8 l ) i a = ( ? )1 616 3981 余数16 2 4 8 .13(D)16 1

50、5 .80 . 15 (F )(3 9 8 1 ) io= (F 8 D ) I。琐碎的运算符:自增:自培 或若百减分 类 :前自增 一+i后自增 一i+前自培和后自培的异同:相同:最终都使i的值加1不同前自增整体表达声的值是i加1之后的值后自增整体表达K的值是i加1之前|的值# include int main(void)(int i ;int j;int k,int m;i = j = 3; 等 价 于 i = 3, j = 3,k =-i+;m = +j;p rin tf (* i = %d, j = %d, k = %d, m = %dn, i, j, k, m);return 0;在

51、Vc+6. 0中 的 检 出 结 果 是 :4, j = 4, k = 3, m = 4总 结 :前 自 增 整 体 表 达 式 的 值 是i加1之 后 的 值后 自 增 整 体 表 达 式 的 值 是i加1之 前 的 值学习自增要明白的几个问题1. 我们编程时应该尽量屏蔽掉前自增和后自增的差别2. 自增表达式最好不要作为一个更大的表达式的一部分来使或者说i+ +和+ + i单独成一个语句,不要把它作为一个完整复合语句的一部分来使用自减:和自增一样。三目运算符:A ? B : t等价于i f ( A)B ;e lseC ; |# i n cl ude i n t m ai n ( v oi d

52、)(i n t i ;i = ( ( t 2 ? 5 : 1 ) ;pri n tf ( % dn , i ) ,return 0 ,)最终的输出结果是1 .逗号表达式:格式( A, B , C , D )功Rr 从 左 到 右 执 行I最终表达式的值是最后一项的值Ig i n cl ude i n t m ai n ( v oi d)(i n t i ,i = ( 3 , 2 , 5 , 6 ) ; tpri n tf ( * % dn * , i ) ; Ireturn 0 ,)最终结果是6 .# i n cl ude i n t m ai n ( v oi d)(i n t i ;i n

53、 t j = 2 ; Ii = ( j + + , + + j , j + 2 j - 3 ) ;pri n tf ( * % dn * , i ) , |return 0 ,上图中,逗号是个顺序点,即所有的副作用必须在下个语句前生效,其最后结果为1, j+ 2 只是产生临时值,并没有把j+2的值赋个j。 如果写成j+=2,那最后的值则变为5.For的嵌套使用举例:# i n cl ude i n t m ai n ( v oi d)i n t i , j ;f or ( i = 0 ; i 3 ; + + i )f or ( j = 2 ; j 5 ; + + j )pri n tf ( 哈

54、哈! n ) ;pri n tf ( 嘻嘻! n ) ; |return 0 ;)上例中输出的结果是9 个哈哈,1 个嘻嘻。# i n cl ude i n t m ai n ( v oi d)(i n t i , j ;f or ( i = 0 ; i 3 ; + + i )pr i n tf ( 嘿嘿! n ) ;f or ( j = 2 ; j 5 ; + + j ) 丁pri n tf ( 哈哈! n 9 ;pri n tf ( 嘻嘻! 、 n ) ;return 0 ;)在上图中, 整个程序分成3个语句, 输出的结果是3个嘿嘿,3个哈哈,1个嘻嘻。# i n cl ude i n t

55、 m ai n ( v oi d)i n t i , j ;f or ( i = 0 ; i 3 : + + i )pri n tf ( * 1 1 1 ! n ) ;f or ( j = 2 ; j 5 ; + + j ) Ipri n tf ( 2 2 2 ! n ) ;pri n tf ( 3 3 3 ! n ) ;)pri n tf ( 4 4 4 | ! n ) ;)return 0 ;其结果是:(ill?222?333?222?333?到444?111?522?333?222?3331222?333?444?111?222?S33?222?333?222?333?|444!Whil

56、e1:( 先付钱后吃饭)执行的顺序:格 式 :while ( 表达式)语 句 ;2:与 for的相互比较:用 for来求1-100之和:h i n cl ude i n t m ai n ( v oi d)i n t sum = 0 ;i n t i ;f or ( i = l ; i 1 0 1 ; + + i )sum = sum + i ,pri n tf ( * sum = % dn ” , sum ) ;return 0 ;用wh i l e实现1 - 1 0 0之和。只需要把f or语句替换为:i = 1 ;wh i l e ( i 1 0 1 )至um = sum + i ;+

57、+ i ;For和wh i l e是可以相互转换的,可以用下面的表达式来表示:for ( IT 2; 3 )A;等价于1 ;w h i 1 e ( 2)A;3 ;DWh i l e和f or在逻辑上完全等价, 但是f or在逻辑上更强。更容易理解,更不容易出错。推荐多使用f or。3: while 举例:从键盘愉入一个数字,如果该数字是回文数,则返回y e s ,否则返回no回文数:正着写和倒着写都一样比如:121 12321|。include in t main(uoid)in t ual; 存放待判断的数字in t m;in t sum = 0;p rin tfL请输入您需要判断的数字:”

58、) ;sucoacnUf(,%, d , P& u -a1 l) ;n = ual;while (n) 111=1234 成立sum-0*10+1234%10-4m-B/10=123;2 0=123 成立sum=4*l0+123%10=43=123/10=123 B=12成立sun=43*l0+12*10=432B=12/10=14 n=lSUB=432*10+1%10=4321m=l/10=05 m=0 不成立最终 sum = 4321通过上面的试数,应该能很快的理解回文数的算法。/*菲波拉契序列1 2 3 5 8 13 21 34/It include in t main(uoid)(in

59、 t n;in t F1, F2, F3;in t i;F1 = 1;F2 = 2;p r in tf(“请输入您需要求的想的序列:“ );scanf(%d, &n);F3 = 1;else i f (2 = n)elseFor (i= 3 ; i=n; +i)printFCdXn, F3);return 0;1 i=3 3 i=4 4 i=5 5 i=6 6 i=7 7=6不成立4:什么时候使用w hile,什么时候使用for:没法说,用多了就自然而然知道了Do.while ( 先吃饭后付钱)格式d o w h i le ( 表达式) ;( J o. . . w h i le .并用等价于f

60、or ,当然也不等价于w h i l主要用于人机交互元二次方程:tt include tt include in t main(uoid)double a, by c;double delta;double x1, x2;char ch;dop rin tfC 1请输入一元二次方程的三个系数p rin tf(a = );scanFCUF, &a);p rin tf(b = );scanF(%lf, &b);p rin tF fc = );scanf(% lf, &c);delta = b*b - 4*a*c;i f (delta 6)else i f (0 = delta)x1 = x2 =

61、(-b ) / (2*a);有唯一解,x1 = x2 = %lFn, x1, x2);elsep rin tf(无实数解八n“);p rin tf(“ 您想继续么(Y/N): “);scanf(“ %c, &ch); 乳前面必须得加一个空格 原因略 while (y=ch | ,V=ch);return 0;Switch的用法:电梯程序:,include in t main( uoid)in t ual;p rin tf( “请输入您要进入的楼层: ) ;scanF( %d, &ual) ;switch ( ual)return 0;Case是程序的入口,当进入程序后, 程序会从上往下执行,如

62、果有break,那么会中断程序,如果没有,那么会一直执行。 switch( 表达式) case常量表达式1 : 语句1; case常量表达式2 : 语句2; case常量表达式n : 语句n; default :语 句 n+1;Break的用法:breakflcont inuebreakbreak如果用于循环是用来终止循环break如果用于sw itch ,剜是用于终( I-switchbreU 不能直接用于i f , 除非i f 属于循环内部的一个子句# i n c l u d e irn t m a i n ( voi d )i n t i ;/ *srw i tc h ( 2)ic a

63、se 2:pri n tf (哈哈! n ) ;b re a k ; /OK, b re a k可以用于sw i tc h)f or ( i =0; i 2)b re a k ; /b re a k虽然是i f内部的语句,但b re a k ”止的稿是外部的f or循环pri n tf (嘿嘿 ! n ) ;re tu rn 0;)# i n c l u d e i n t m a i n ( voi d )(i n t i , j ;f or ( i =0, i 3; + + i )(f or ( j =l ; j 4, + + j )b re a k ; /b re a k只 能 终 止

64、距 离 它 最 近 也 ;婚 坏pri n tf ( 同 志 们 好 ! 、n ) ;)在多层循环中,Break只能终止他最近的循环。在 多 层 switch中,break也是只能终止距离他最近的switch o, i n c l u d e i n t m a i n ( )(i n t x =l , y =0, a =0, b =0;sw i tc h ( x ) / 第一个sw i tc h(c a se 1:sw i tc h ( v) 第二个 sw i tc hc a se 0:a + + ;b re a k ; / / 终止的是第二个sw i tc hc a se 1:b + +

65、;b re a k ;b = 100;b re a k ; / / 终止的是第一个sw i tc hc a se 2:a + + ;b + + ;b re a k ;)pri n tf (/z% d a , b ) ; 26行re tu rn 0;)Break只能用于循环和switch,不能用于if。 如果用于if,必须要当循环中嵌套if的时候。Continue的用法:cont inue用于跳过本次循环余下的语句,转去判断是否需要执行下次循环1.fo r ( 1; 2 ;(A;B;continue; /如果执行该语句,则执行完该语句C;D;)C上图中,如果执行continue,那么C,D将不会

66、被执行,会执行3.while i ( 表达式)(A;B;cont i nue;C;D;)在上图中,如果执行了 continue,那么后面的C,D将不再执行,而会去执行表达式。技 i n c l u d e i n t m a i n ( voi d )(i n t i ;c h a r c h ;sc a n f & i ) ;pri n tf (/zi = % d n ” , i ) ;w h i l e ( ( c h =g e tc h a r ( ) ) ! = n )c on ti n u e ;i n t j ;sc a n f & j ) ;pri n tf ( j = % d

67、n * , J) ;re tu rn 0;)数组:- 非重点数组的使用:t t i n c l u d e i n t m a i n ( voi d )(i n t a 5 = tl , 2, 3, 4, 5 ;/a是数组的名字,5表示数组元素的个数,并且这5过热元素分别用这0 a a i n t i ;f or ( i =0; i 5; + + i )pri n tf (/ ,% d n/ ,, a i ) ; |re tu rn 0;)为什么需要数组1:为了解决大量同类型数据的存储和使用问题。2:用数组可以模拟现实世界。lnta25:一维数组,可以当做一个线性结构。Int a:可以当做一

68、个平面,意思是8 行 6 列。有 48个元素。Inta :可以当做一个三维立体。Inta :可以当做一个四维空间。数组的分类一维数组怎样定义一维数组: 为n个变量分配存储空间:数组内存空间是连续的。 所有的变量类型必须相同:数组不可能第一个元素是整形,第二个元素是浮点型。 所有变量所占用的字节必须相等。例子: int 5数组不是学习重点的原因?数组一旦定义,其长度是死的。有关一维数组的操作- 都需要自己另外编程序实现而我们通常用第三方软件( 工具)如数据库等方便直接地实现。对数组的操作:初始化赋值排序求最大/小值倒置查找插入删除,初始化:初始化完全初始勺int 4 5 = 1, 2, 3, 4

69、, 5;不完全初始化, 未被初始化的元素自动为零int a5 = 1,2,3;不初始化, 所有元素是垃圾值int a 5 ;清零int a5 = 0;错 误写法:i n t a 5 ;a 5 = |1J 2, 3, 4, 5; 错误只有在定义数组的同时才可以整体赋值,其他情况下整体赋值都是错误的i n t a 5 = 1, 2, 3, 4, 5;a 5 = 100; /e r r o r因为没有a 5这个元素,上图中a5前面如果没有加上数据类型, 那么这里的a5不是指一个数组,其中的5只的是下标。i n t a 5 = 1,2, 3, 4,5;i n t b 5 ;如果要把a数组中的值全部复制

70、给b数组错误的写法:b = a ; / e r r o r正确的写法f o r ( i = 0; i i = a i l ;上图中,数 组 的5个元素不是用a来代表的,是用aOzal.a4来代表的, 所以说数组名a代表的不是数组的5个元素,数组名代表的是数组的第一个元素的地址。 赋值t t include int main(void)int a;int i;scanf &a0);printf (*a0 = %dn*, a0);scanf &a3);printf (*a3 = %dn, a3);for (i=0; i5; +i)printf (%d , ai);return 0;)把一个数组元素

71、给全部倒过来:g i n c l u d e 1 = 0;j = 7;wh i l e ( i j )(t = a i ;a i = a j ;a iji = t ;i +;-J ;f o r ( i = 0; i nn15944ftrtrirLrL1J33rLrLaattnn 1 1输出二维数组内容:# include int main(void).int a3 4 = (1, 2, 3, 4,5, 6, 7, 8),9, 10, 11, 12);int i, j;/ / 瞬 出 数 组 内 容for (i=0; i3; +i)(for (j=0; j4; +j)printf (*%d ”,

72、 ai j);printf(*n*) :|return 0:多维数组:是否存在多维数组:不存在因为内存是线性一维的,在内存中是不分行不分列的。N维数组可以当做每个元素是n - 1维数组的一维数组。,a - w多维数组是否存在多维数组不存在因为内存是线性一维的n维数组可以当做每个元素是n-1维数组的一维数组比 如 : Iint a 3 4 ;该数组是含有3个元素的一维数组只不过每个元素都可以再分成4个小元素int a 3 4 5 ;该数组是含有3个元素的一维数组只不过每个元素都是4行5列的二维数组函 数 ( 第二个重点) :# i n c l u d e /ma x是函藜的名字? i和j是形式参

73、数,v o i d ma x( i n t i , i n t j )(i f ( i J )p r i n t f ( d n ,e l s ep r i n t f ( % d n ,)i n t ma i n ( v o i d )i n t a , b , c , d , e , f ;a = 1, b = 2; c = 3, dma x ( a , b ) ;ma x ( c , d ) ;ma x ( e , f ) ;*i f ( a b )p r i n t f ( 飞 d n ” ,e l s ep r i n t f ( 飞 d n ” ,i f ( c d )p r i

74、n t f ( 飞 d n ,e l s ep r i n t f ( 飞d n ” ,i f ( e f )p r i n t f ( % d n ,e l s ep r i n t f ( % d n ,*/为什么需要函数:避免了重复性操作。有利于程序的模块化。( 自上而下,逐步细化,简 称 形 参v o i d表示函数没有返回值i );J );= 9 , e = -5, f = 100;a ) ;b ) ;c ) :d ) :e ) ;f ) ;大问题分解成小问题)用它作为参照,可以对比JAVA和C#面向对象的思想。C语言基本单位是函数,C#、C+和JAVA基本单位是类。什么叫做函数#

75、i n c l u d e i n t f ( v o i d ) / / 括号中的v o i d 表示该函数不能接受数据i n t 表示函数返回值是i n t 类型的数据r e t u r n 10; 向主调函数返回10)v o i d g ( v o i d ) 8行函数名前面的v o i d 表示该函数没有返回值./ r e t u r n 10; /e r r o r 与8行行首的v o i d 相矛盾)i n t ma i n ( v o i d )(i n t j = 88;J = f 0 ;p r i n t f ( % d n , j );/ j = g ( ); /e r r

76、 o r 因为g 函数没有返回值r e t u r n 0 ;) 逻辑上:能够完成特定功能的独立的代码块。物理上:能够接收数据【 也可以不接收数据】 ,能够对接收的数据进行处理【 也可以不对数据进行处理】 ,能够将数据处理的结果返【 也可以没有返回值】 。 总结:函数是个工具,他是为了解决大量类似问题而设计的,函数可以当做黑匣子( 内部原理不用管) 。如何定义函数 函数的返回值,函数的名字( 函数的形参列表)(函数的执行体 函数定义的本质:详细描述函数之所以能够实现某个特定功能的具体方法。函数中的变量叫做形参;数组中的变量叫元素。一旦函数执行完毕,其内部的形参所占空间就被收回。, return

77、表达式的含义:Return是终止被调函数,向主调函数返回表达式的值,如果表达式为空,则只终止函数,不向被主函数返回任何值。例子:v oi d f ( )(r e t u i j i ; / / r e t u r n只用来终止函数,不向主调函数返回任何值i nt f ( )r e t u r n 1 0 ; / / 第一: 终止函数, 第二:向主调函数返回1 0Break是用来终止( 就近的) 循环和switch语句。 而 return是用来终止被调函数的。性 inc lud e void f ( void )(int i;for ( i= 0 ; i 5 ; + + i)(printf (

78、大家辛苦了! n ) ;return;printf ( 同志们好! n ) ;)int ma in( void )f( ) ;return 0 ;函数返回值的类型,也称为函数的类型,因为如果函数名前的返回值类型和函数执行体中的return表达式中表达式的类型不同的话, 则最终函数返回值的类型以函数名前的返回值类型为准。例:# inc lud e int f ( )return 1 0 . 5 ; / / 因为函数的返回值类型是int所以最终f返回的是1 0 而不是1 0 . 5ntd1 -int i = 9 9 ;d oub le x = 6 . 6 ;x = f ( ) ;p r i n t

79、 f x ) ;return 0 ;)在上图中,函数的返回值以函数前的数值类型为准。函数的分类, 有参函数和无参函数。 有返回值和无返回值。 库函数和用户自定义函数。 普通函数和主函数(main函数)1: 一个程序有且只有一个主函数。2:主函数可以调用普通函数,普通不能调用主函数。3:普通函数可以相互调用。4:主函数是程序的入口,也是函数的出口。5:值传递函数和地址传递函数。i t inc lud e / / ma x是函婺的名.字,.i和J 是形式参数,简称形参void 表示函数没有返回值void ma xi( int i, int j)(if ( i J )printf i) ;elsep

80、rintf ( % d n , j) ;int ma x2 ( int i, int j)if ( i J )return i;elsereturn j;int ma in( void )(int a , b , c , d , e, f;a = 1 , b = 2 ; c = 3 , d = 9 , e = - 5 , f = 1 0 0 ;printf ( 飞d n” , ma x2 ( a , b ) ) ;printf C % d nz/, ma x2 ( c , d ) ) ;printf ( 飞d n ,ma x2 ( e, f) ) ;/ * / |ma xi ( a , b )

81、ma xi ( c , d )ma xi ( e, f)return 0 ;判断一个数是否是素数:tt include int main (void)(int v a l;int i ;scanf(%d”, feval);for (i=2; i val; +i)(if (val%i = 0)break;)if (i = val)prin tf(Y es!n * );elsep rin tf(N o !n );return 0;)使用函数判断一个数是否是素数:/ *2 0 0 9 年1 1 月4 日1 1 : 1 8 : 5 1判断一个数字是否是素数用单独的函数来实现,代码的可重用性提高* /#

82、 inc lud e b ool I sP rime( int va l)int i;for (i=2; i va l; + + i)(if ( 0 = = va l% i)b rea k;)if ( i = = va l)return true;elsereturn fa lse;nt 1n-1lam t v a l;in t i ;sc a nf & va l) ;if ( I sP rime( va l) )printf( Y es! n ) ;elseprintf ( N o! n ) ;return 0 ;)函数和程序的调用应该注意的地方:# inc lud e int f( int

83、 i)(return 1 0 ;int ma in( void )(int i = 9 9 ;printf( % d n, i) ;i 二 f ;printf ( 缄d n , i)return 0 ;函数的声明:# inc lud e void f( void )|printf ( 哈哈! n) ;int ma in void )f( ) ;Ireturn 0 ,)当函数没有返回值时, 那么规范的写法是要在函数中写明void的。在上图中, 第一个void表示没有返回值, 而第二个void表示不接收形参,也就是函数不接收数据。如果想把函数写在程序的后面,那么需要写函数声明:ff include

84、 koid f(void); / / 函数声明, 分号不能丢掉int main(void)f();return 0;)void f (void)p rin tf ( 哈哈! n );)函数声明的含义是告诉编译器f()是个函数名。 如果不加函数声明,那么编译器在编译到f的时候,不知道f是个什么,如果加了函数声明,那么编译器编译到f的时候,就知道f是个函数。 需要注意的是,调用语句需要放在定义语句的后面,也就是说,定义函数的语句要放在调用语句的前面。*I 2 0 0 9年1 1月4日1 1 : 0 1 : 3 5一定要明白该程序为什么是错误的一定要明白该程序第9行生效之后程序为什么就正确了*/#

85、inc lud e / / void f ( void ) ; 9行void g( void )(f O; / / 因为函数f的定义放在了调用f语句的后面,所有语法出错void f ( void ) .printf ( 哈哈! n ) ;)int ma in( void )(g( ) ;return 0 ;如果函数调用写在了函数定义的前面, 则必须加函数前置声明,函数前置声明的作用是:1:告诉编译器即将可能出现的若干个字母代表的是一个函数。“ 打招呼”2:告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况。3:函数声明必须是一个语句,也就是在函数声明后需加分号。4:对库函数

86、的声明也就是系统函数。是通过#include来实现的。如 stdio.h形参和实参要求:1:形参和实参个数是一一对应的。2 :形参和实参的位置也是- - -对应的。3 :形参和实参的数据类型需要相互兼容。 如何在软件开发中合理的设计函数来解决实际问题。求1到某个数字之间的数是否是素数,并将他输出:合理设计函数1/*2009年11月4日11:18:51判断一个数字是否是素数只用一个函数实现,不好,代码的利用率不高*/t t include int main(void)int val;int i;scanf &val);for (i=2; ival; +i)if (0 = val%i)break;

87、)if (i = val)printf(Yes!n);elseprintf (No!n);return 0;)合理设计函数2 :*2 0 0 9 年 n 月 4 日1 1 : 1 8 : 5 1判断一个数字是否是素数用单独的函数来实现,代码的可重用性提高* /# i nc lud e bool IsP ri me ( i nt va l)i nt i ;f or ( i = 2 ; i va l: + + i )i f ( 0va l)re turnre turn=va l% i )bre a k ;true ;f a lse :i nt ma i n( voi d )i nt va l;i

88、nt i ;sc a nf & va l) ;i f ( IsP ri me ( va l) )pri ntf ( Y e s! n ) ;e lsepri ntf ( N o! n ) ;re turn 0 ;)合理设计函数3 :/ *2 0 0 9 年1 1 月4 日1 1 : 1 8 : 5 1求1 到某个数字之间( 包括该数字) 所有的素数,并将其输出只用ma i n函数实现,有局限性:1 .代码的重用性不高2 .代码不容易理解* /# i nc lud e i nt ma i n( voi d )i nt va l;i nt i ;i nt j ;sc a nf ( 飞d ” , &

89、 va l) ;f or ( i = 2 ; i = va l; + + i )判断i 是否是素数,是输出,不是不输出f or ( j = 2 ; j i ; + + j )fi f ( 0 = = i % j )bre a k ;i f ( j = = i )pri ntf ( % d n” , i ) ;re turn 0 ;)合理的设计函数4 :2 0 0 9年1 1月4日1 1 : 1 8 : 5 1求1到某个数字之间( 包括该数字) 所有的素数,并将其输出用1个函数来判断一个数字是否是素数饶 占代码比 如何设计函数_ 3 . c p p更容易理解代码的可重用性比如何设计函数_ 3 .

90、 c p p高缺点:可重用性仍然不是非常高,比如有1 0 0 0个数字,求它们每个数字从1到它本身的素数则f or ( i = 2 ; i = va l; + + i )i f ( IsP ri me ( i ) )pri ntf ( 飞d n” , i ) ;)要写1 0 0 0次* /# i nc lud e bool IsP ri me ( i nt m)i nt i ;f or ( i = 2 ; i m; + + i )(i f ( 0 = = m% i )bre a k ;i f ( i = = m)re turn true ;e lsere turn f a lse ;)i nt

91、 ma i n( voi d )i nt va l;i nt i ;s c a n f & va l) ;f or ( i = 2 : i = va l; + + i )i f ( IsP ri me ( i ) )pri ntf ( 飞d n” , i ) ;re turn 0 ;合理设计函数5 :2009年11月4日11:56:29用两个函数来实现求1到某个数字之间所有的素数,并将其输出本程序和如何合理设计函数_4. c p p相比较代码量更少,可重用性更高一*/# include 本函数的功能是:判断m是否是素数,是返回true,不是返回falsebool IsPrime(int m)(

92、int i;for (i=2; im; +i)if (0 = m%i)break;)if (i = m)return true;elsereturn false;/ / 车函数的功能是把1到n之间所有的素数在显示器上输出void TraverseVal(int n)(int i;for (i=2; i=n; +i)(if ( IsPrime( i ) )printf (%dn, i);)t.1 fnlmain (void)int val;scanf ( 飞d”, &val);TraverseVal(val);return 0;)常用的系统函数和如何通过书籍来学习函数:Turboc2.0实用大全

93、一机械工业出版社常用的系统函数Idouble Jqrt(double x);求扁x的平方根int abs(int x)求x的绝对值double fabs(double x)求x的绝对值递归:( 略)栈:相当于一个杯子( 容器)变量的作用域和存储方式:变员的作用域和存储方式:按作用域分:I全局变量局部变量按变量的存储方式静态变量自动变量寄存罂变量全局变量和局部变量:局部变量:局部变量在一个函数内部定义的变量或者函数的形参都统称为局部变量void f(int i)(int j = 20; Ii和j都属于局部变量局部变量的使用范围只能在本函数内部使用。全部变量:全局变量在所有函数外部定义的变量叫全局

94、变量全局变量使用范围力 从定义位置开始到整个程序结束/*2 0 0 9年1 1月6 日9 : 3 3 : 0 2一定要明白该程序为什么是错的,也要明白把9到1 2行代码放在1 4行后面,为什么程序就0 K 了*/# i nc lud e voi d g ( ) / / 9(pri ntf ( k = % d n” , k ) ; / / 1 2i nt k = 1 0 0 0 ; 1 4行voi d f ( voi d )(g ( ) ;pri ntf ( k = % d n” , k ) ;i nt ma i n( voi d )(f ( ) ;re turn 0 ;)1全局变量和局部变量命

95、名冲突的问题:在同一个范围之内不能定义两个一样的局部变量:B i nc lud e voi d f ( i nt i ) I + .i nt i ;pri ntf ( * i = % d n” , i ) ;i nt ma i n( voi d )(f ( 8 ) ;在一个函数内部, 如果定义的局部函数的名字和全局变量名一样时,局部变量会屏蔽掉全局变量:t t i nc lud e i nt i = 9 9 ;voi d f ( i nt i ) _ Ipri ntf ( i = % d n” , i ) ;i nt ma i n ( voi d )f ( 8 ) ;re turn 0 ;上例

96、中最终的输出结果是8 ,因为局部变量把全局变量给屏蔽掉了。指针:(C语言的灵魂)内存的存储是以一个字节为一个编号, 也就是8位合在一起给一个编号,不是0 1就给编号。内存分为很多个单元,每个单元就会分配一个编号。地址: 内存单元的一个编号。 而指针和地址一个概念的。也就是说指针就是地址。# i n c l u d e i n t m a i n (v o i d ) ,i n t * p ; /p 是变量的名字,i n t * 表示p 变量存放的是i n t 类型变量的地址i n t i = 3;p = &i ; /OK p = i ; /e r r o r ,因为类型不一致,p 只能存放i

97、n t 类型变量的地址,不能存放i n t 类型变量的值/p = 55; /e r r o r 原因同上r e t u r n 0;)普通变量:只能存放一个值。指针变量:同样是一个变量,但是指针变量存放其他变量的地址。# i n c l u d e i n t m a i n (v o i d )(i n t * p : /是变量的名字,i n t *表示p变量存放的是i n t类型变量的地址/i n t * p ;不表示定义了一个名字叫做*p的变量i n t * p ;应该这样理解:p是变量名,p变量的数据类型是i n t * 类型!/ 所谓i n t *类型实际就是存放i n t变量地址的

98、类型i n t i =3;i n t j ;p = &i ; *1. p保存了i的地址,因此p指向i2. p不是i , i也不是p ,更准确的说: 修改p的值不影响i的值,修改i的值也不会影响P的值3 . 如果一个指针变量指向了某个普通变量,则* 指针变量就完全等同于普通变量例子:如果P是个指针变量.并且p存放了普通变量i的地址则P指向了普通变量i*P 就 完 全 等 同 于i或者说: 在所有出现*P的地方都可以替换成i在所有出现i的地方都可以替换成*P* P就是以P的内容为地址的变量j 二*P: 等价于 j 二 i ;p r i n t f (*i = %d , j = %d n ” , i

99、 , j );r e t u r n 0;*P 代表 的 是 p 所指向的那个变量。在上图中*p 和 i 是同一个东西,但是*P和 P 不是同一个东西。在上图中,int * p 是一个声明,开头的in t * 是他的数据类型。P是变量的名字。不能理解我定义了一个整形变量,这个整形变量的名字叫做*p。所谓int*类型,实际就是存放in t变量地址的类型。*p代表的是以p的内容为地址的变量。解析:p的内容是一个地址,在上图中,p的内容就是i的地址,*p其指向的变量当然就是i变量了。指针和指针变量:指针就是地址,地址就是指针。地址就是内存单元的编号。指针变量:存放地址的变量。而指针只是一个值,这个值

100、是内存单元的一个编号。指针变量才是一个变量,他里面才可以存放数据。指针和指针变量是两个不同的概念,但是需要注意的是, 通常我们在叙述时会把指针变量简称为指针,实际他们含义并不一样。指针的重要性:指针:表示一些复杂的数据结构快速的传递数据使函数返回一个以上的值能直接访问硬件能够方便的处理字符串是理解面向对象语言中引用的基础11总结:指针是c语言的灵魂指针的分类:指针的分类1 .1 基本类型指针2 .指针和数组3 .指针和函数4 .指针和结构体5 .多级指针指针的定义:地址:内存单元的编号, 是一个从。开始的非负整数。范围:cp u对内存是通过控制、数据、地址三条总线来进行控制的。能直接访问能够方

101、便的指针的定义地址内存单从零开范 围 :指针 I、 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _指针的分类控制:cu p会先把内存中的数据读入,进行处理后,在返回给内存,然后内存在把数据写入硬盘。数据:用于数据的传输,不管是把内存中的数据发送给c p u ,还 是 把c p u的数据写如内存条,都是由数据线来完成的,但是数据传输的方向则是由控制线来控制的。地址:地址线则是确定数据要写入内存中的那个单元。所谓的一个单元就是一个字节。地址线,最终能够控制2 的 32个单元,而每个单元是八位,而最终我们的内存能够存储2 的 32次方*8 位

102、。则换算为G 的话,最终大小为4G.那么地址总线的范围则 是 4G 大。指针:指针就是地址,地址就是指针。指针变量就是存放内存单元编号的变量。指针变量和指针是两个不同的概念。指针的本质就是一个操作受限的非负整数。指针不能进行算术运算-相力口乘除。但是能相减。如果两个指针变量指向的是同一块连续空间的不同存储单元,则这两个指针变量才可以相减。类似于同一个小区同一楼层六牌号相减表示两房间隔。这时才有现实意义。基本类型的指针:S i n c l u d e i n t m a i n (v o i d )(i n t * p ;i n t i =5;*P = i ;p r i n t f *p );r

103、 e t u r n 0;| T)Int *p: p只能存放int类型的地址。P = & i:把i的地址赋给p。然后p就指向了 i, *p就等于i。其实就是1:该语句保存了 i的地址。2: p保存了 i的地址,所以p指向i。3: p既然指向i, *p就是i。*p:表示以p的内容为地址的变量。*p: p是有指向的,p里面是个垃圾值,*p则是说以p的内容为地址的变量。因为不知道p的值是多少,所以不知道*p到底代表的是那个变量。而*p = i, i= 5 ,最终的结果就是把5赋给了一个所不知道的单元。i n c l u d e i n t m a i n ( v o i d )(i n t i =

104、5 ;i n t * p ;i n t * q ;p = & i ;* q = p ; / / e r r o r 语法编译会出错/ / * q = * p ; / / e r r o rP = q : / / Q是垃圾值,q 赋给P, _ P也变成垃圾值p r i n t f ( 飞d n , * q ) ; / / 1 3 行/ *q 的空间是属于本程序的,所以本程序可以读写q 的内容,但是如果q 内部是垃圾值,则本程序不能读写* q 的内容因为此时* q 所代表的内存单元的控制权限并没有分配给本程序所以本程序运行到1 3 行时就会立即出错*/r e t u r n 0 ;)上图中,第一个

105、error是数据类型不符合,不能相互转换。* q 代表的是整形,因为* q 代表的是以q 的地址为内容的变量。而 p 是地址(int * ) 类型。第二个error同样有错,因为q 没有赋值。经典指针程序- 互换两个数字:1:先用函数来互换:fi include void huhuan(int a, int b)(int t;| jt = a;a = b;b = t ;return;int main(void)(int a = 3 ;int b = 5;huhuan (a, b );p rin tf (*a = %d, b = %dn”, a, b);最终的输出结果没有互换,因为函数的a, b

106、已经执行完成,分配给内存的空间已经释放了,所以最终a, b的值还是主函数a, b的值。互换的是形参的a, b o和主函数没有关系。囱 w hP 4 唱 BE - - u 砂 石 少 | (Globals) |(AH global member 引 .huhuan.ZJ! U i n c l u d e 平v o i d h u h u a n _ 2 ( i n t * p , i n t * q )i n t * t ;如果要互换p和q的值,则是i n t ,否则会出错i n t m a i n ( v o i d ) / O X ) ”2口叫i n t a = 3 ;i n t b = 5

107、 ;h u h u a n 2 ( f e a , , / / h u h u a n _ 2 * q );是错误的,h u h u a n _ 2 ( a , b ),也是错误Ep r i n t f 7 * a = b = % d n ” , a , b) ;r e t u r n 0 ;k h JD :share09A01cdk15指针保典指针程序 互换两个数字.cpp savedLn 9, Col 11 :; I )VR HF At在上图中,输出的值也是没有互换的,输出的同样是3, 5 ,需要注意的是,互换的只是p、q的内容,局部函数变化了,但是主函数是没有变化的。最终正确的程序:#

108、include void huhuan_l(int , int);void huhuan_2(int *, int *);void huhuan_3 (int *, int *);irnt main(void)int a = 3;int b = 5;huhuan_3 (&a, &b) ; /huhuan_2 (*p, *q);是错误的,/huhuan_2 (a, b);也是错误的printf (z ,a = %d, b = %dn” , a, b);return 0;)不能完成互换也能vroid huhuan_l(int a, int b)Iint t;t = a;a = b;b = t;re

109、turn;)/ / 不能完成互换也能void huhuan_2(int * p, int * q)int * t;/如果要互换p和q的值,贝 !Jt必须是int *,不能是int,否则会出错t = p;P = Q;Q = t;可以完成互换功能vf oid huhuan-_3(int * p, int * q)int t; / / 如果要互换*p和*q的值,贝 !Jt必须定义成int,不能定义成int * ,否则语法出错)t = *p; /p是int *, *pint*P = *Q;*Q = t;* 号的三种含义:1 : 乘法2:定义指针变量。Int * p ,定义了一个名字叫p 的变量,int

110、 * 表示p 只能存放int变量的地址。3:指针运算符。该运算符是放在已经定义好的指针变量的前面。如果p 是一个已经定义好的指针变量,贝 HP 表示以p 的内容为地址的变量。注意理解形参,实参,和局部变量的关系。# include int main(void)(int * p:/、价 , int * p : 也:;价卜 int* p:int i = 5:char ch = A:p = &i: / * p )的内容为地址的 i ;*p = 99:printf ( i = %d, *p = % 小n” , i. *p):/p = &ch:/p = ch: /error/p = 5: /errorr

111、eturn 0:指针可以是函数返回一个以上的值:* i n c l u d e i n t f ( i n t i , i n t j )(ir e t u r n 1 0 0 :/ / r e t u r n 8 8 :)i n t m a i n ( v o i d )ti n t a = 3 , b = 5 :a = f ( a , b ):b = f ( a , b ):不使用指针的话,只能使用用return来返回一个值。如何通过被调函数修改主调函数普通变量的值如何通过被调函数修改主调函数普通变量的值1 .卖参必须为该普通变量的地班2 .形参必须为指针变且3 .在被调函数中通过* 形

112、参 名 = . . . . . |的方式就可以修改主调的数相关变良的值v o i d g ( i n t * p , i n t * q )Qi )= i :* q = 2 :)Ii n t m a i n ( v o i d )(Ii n t a = 3 , b = 5 :g ( & a , & b ):y r i n t f ( % d % d n , a , b ):r e t u r n 0 ;指针和数组:指针和一维数组:( 数组名 下标与指针关系 指针变量的运算)一维数组名:一维数组名是个指针常量,他存放的是一维数组第一个元素的地址。# i n c l u d e i n t m a

113、 i n ( v o i d )i n t a 5 ; / / a是 数 组 名5是数组元素的个数 元 素 就 是 变 量a 0 a 4 / / i n t a 3 4 ; 7 / 3行4列 a 0 0 是余一个兀素 匕第i + 1 行j + 1 列i n t b 5 ;/ / a = b ;/ / e r r o r a是常量p r i n t f (z ,% # Xnz ,, & a 0 );p r i n t f C% # Xn, z, a );r e t u r n 0 ;)*在Vc + + 6 . 0中的输出结果是:0 X1 2 FF6 C0 X1 2 FF6 CPr e s s a

114、 n y k e y t o c o n t i n u e总结:一维数组名一维数组名是个指针常量它存放的是一维数组第一个元素的地址常量是不能被改变的,也就是说,一维数组名是不能被改变的。数组名a存放的是一维数组第一个元素的地址, 也就是a = &a。printf(#Xn,&aO); = printf(%#Xn,a);指针和二维数组:下标和指针的关系: 如果p是个指针变量, 则pi永远等价于*(p+i)# include int main (void)(int a5 = 1,2,3, 4,5;int i ;for (i=0; i5; +i) Iprintf C%dn*, a i); /a i

115、= *(a+i)return 0;)|确定一个一维数组需要几个参数,【 如果一个函数要处理一个一维数组, 则形参需要接收该数组的哪些信息。 】确定一个一维数组需要两个参数,1 : 数组名,从数组的名称就可以知道数组的第一个值,因为一维数组的名称就是数组的第一个元素的地址。2:是数组的个数。来计算该数组有多少个值。区别于 字符串( 只需要一个参数一首地址)因为字符串默认其后面都有一个“ Q”作为结束标志。而数组并没有相关约定。# include / / f 函数可以输出任何一个一维数组的内容void f (int * pArr, int len)(*pArr * (pArr+1) 1Tint m

116、ain(void)(int a5 = 1, 2, 3, 4, 5.int b6 = (-1, -2, -3, 4, 5, -6,int c100 = 1, 99, 22, 33;f (a, 5); Iia良 int *return 0;)在上图中,a是个指针变量, 所以上面局部函数f的pArr则要定义成指针函数才可以,而le n则是in t类型。代表接收的是整型的数字。1 # include / / f函数可以输出任何二个一维数组的内容void f ( int * pA rr, int len)int i;for ( i=0 ; ilen; + + i)printf (/ z% d , * (

117、 pA rr+ i) ) ; / / * pA rr * ( pA rr+ 1 ) * ( pA rr+ 2)printf (z , n) ;int main( void)int a 5 = 1 , 2, 3 , 4 , 5) ;int b 6 = - 1 , - 2, - 3 , 4 , 5, - 6 ;int c 1 0 0 = 1 , 9 9 , 22, 3 3 ) ;a ,bczl/i/(xfff5) ; e 是 int *6 ) ;1 0 0 ) ;return 0 ;*20 0 9年1 1月1 4日1 0 : 4 5: 51一定覆明白1 0行的pA rr 3 和1 7行1 9行的a

118、 3 是同一个变量* /# include void f( int * pA rr, int len)rpA rr 3 = 8 8 ; 1。 行)int main( void)int a 6 = 1 , 2, 3 , 4 , 5, 6 ;printf ( 飞d n, a 3 ) ; 1 7行f ( a, 6 ) ;printf (z/% d nz ,, a 3 ) ; / / 1 9行return 0 ;)/ *在V c+ + 6 .0中的输出结果是:48 8P ress any key to continue在上图中因为数组a的名称代表的是a的第一个元素的地址, 所以在函数f中所定义的指针变

119、量p A rr和a是相同的,因 为a也是指针类型。也就是说pArr=a=a0,pArrl=al=*(pArr+l)=*(a+l),pArr2=a2=*(pArr+2)=*(a+2).所以在f函数中pAir3=a3,所以第二个printf输出的结果是88.总结:pArri = ai = *(pArr+i) = *(a+i)在没有学习指针时, 可将a3认为是数组中第4个元素,但现在应该对其内部原理有更深刻认识。这里下标也当成指针了,从首元素开始向后移动3个,即指向第4 个元素。# include void f(in t * pArr, int len)int i ;for (i=0; ilen;

120、+i)printfC%d , pArrEi) ; /*(pA rr+ i)等价于 pArri| / / 也等价于b i 也等 价 于*(b+i)printf (n);)int main(void)Iint b6 = -1, -2, -3,4, 5, -6;f(b, 6);bireturn 0;在上图中因为数组a 的名称代表的是a 的第一个元素的地址, 所以在函数f 中所定义的指针变量pArr和 a 是相同的, 因为a 也是指针变量类型。 也就是说pArr=a=a0,pArrl=al=*(pArr+l)=*(a+l),pArr2=a2=*(pArr+2)=*(a+2).通过上图,我们知道,我们在

121、f 函数中修改数组的值,相当于修改主函数中相对应的值。何谓变量地址/ 一个指针占几个字节Sizeof( 变量名/ 数据类型) 其返回值就是该变量或数据类型所占字节数。一个指针变量无论其指向变量占几个字节, 其本身所占大小都是4 字节。*P具体指向几个字节,要靠前面类型确定,如果为int则为4 字 节 , 如 果 double则占8 字节。C P U 与内存 交互时 有 32根线,每根线只能是1 或0两个状态,所有总共有232个状态。1 个状态对应一个单元。如全为0 全为1 等。内存中第一个单元,即 32根线状态全为0。0000 0000 0000 0000 0000 0000 0000 000

122、0其大小为4 字节所有每个地址( 硬件所能访问)的用4 个字节保存( 而不 是 一 位 bit)一个变量的地址一用该变量首字节的地址表示。 这也就是为什么指针变量始终只占4 字节的原因。接下来是:138课 动态分配内存( 很重要)专题:138讲动 态 内 存 分 配 ( 所有高级语言,没有C里深刻,对JAVA、C#理解有益)传统数组的缺点:L数组长度必须事先指定,而且只能是常整数,不能是变量例 J子 int a5; 必须事先指定,而且只能是常整数int len = 5; int alen;/error2. 传统形式定义的数组,该数组的内存程序员无法手动释放数组一旦定义,系统为数组分配的内存空间

123、就会一直存在,除非数组所在的函数运行终止。在一个函数运行期间,系统为该函数中的数组分配的空间会一直存在。直到该函数运行完毕时,数组的空间才会被系统自动释放( 不是清零) 。例子:void f ( void) int a5=l, 2, 3,4, 5)数组a 占20个字节的内存空间, 程序员无法手动编程释放它, 数组a只能在f ( ) 函数结束被系统释放3 .数组的长度一旦定义,数组长度就不能再更改。数组的长度不能在函数运行的过程中动态的扩充或缩小4 .传统方式定义的数组不能跨函数使用A函数定义的数组,只有在A函数运行期间才可以被其他函数使用,但A函数运行完毕后,A函数中的数组将无法在被其他函数使

124、用。# i nc l ud e voi d g ( i nt * pA rr, i nt l e n)(pA rr 2 = 8 8 ; / / pa rr 2 = = a 2 等价于)voi d f ( voi d )(i nt a 5 = 1 , 2 , 3 , 4 , 5 ; 数组a只在f ( ) 执行时有效g ( a , 5 ) ;pri ntf (z ,% d nz/, a 2 ) ;)i nt ma i n( voi d )(fO; / / 结果: 8 8/ / pri ntf C a 0 = % d n , a 0 ) ; / / e rrorre turn 0 ;)为什么需要动态

125、分配内存很好的解决的了传统数组的4个缺陷动态内存分配举例 动态数组的构造 难点A 2 0 1 1 - 0 5 - 0 1ma l l oc 是me mory ( 内存) a l l oc a te ( 分配) 的缩写动态内存空间是怎么造出来的?* / # i nc l ud e f ti nc l ud e i nt ma i n( voi d )(i nt i = 5 ; 分配了4 个字节,静态分配i nt * p = ( i nt * ) ma l l oc ( 1 0 0 ) ;/ *1 . 要使用ma l l oc 函数,必须要添加ma l l oc . h 头文件2 . ma l l

126、 oc 函数只有一个形参,并且形参是整型3 . 1 0 0 表示请求系统为本程序分配1 0 0 个字节4 . ma l l oc 函数只能返回第一个字节的地址,但此时并不能确定该变量的类型,只有将这个地址被强制类型转化成存放整型变量的地址,这时才传达出指向整型变量的信息。5 . 系统总共分配了 1 0 4 个字节的内存空间, p变量本身占4 个字节( 静态分配) ,p所指向的内存占1 0 0 个 字 节 ( 动 态 分 配 ) 若 为 i ni 则可存2 5 个,若为c h a r则可存1 0 0 个变量。6 . p本身所占的内存是静态分配的,p所指向的内存是动态分配的* /f re e (

127、p) ;/ / f re e ( p) 表示把p说指向的内存空间给释放掉,P 本身的内存不能释放,只有ma i n函数终止时,由系统自动释放* p = 5 ;* * P 代表的就是一个这i nt变量,* p这个整型变量的内存分配方式和i nt i = 5 ; 不同。2 0 1 1 - 0 5 - 0 1目的: ma l l oc 使用. 2* /f ti nc l ud e # i nc l ud e voi d f ( i nt * q) / / q是p的拷贝或副本q等价于p * 4 等价于* p * q= 2 0 0 则* p= 2 0 0(/ / * p = 2 0 0 ; / / e

128、rror f ( ) 没有p变量,p是在ma i n。函数定义的/ / q = 2 0 0 ; / / e rror q是指针变量( 地址) ,2 0 0 是整数i nt* q = 2 0 0 ; / / 0 K ! 类型一致/ / * *q 语 法 错 误 ! * q整型变量, 只有指针变量前可以加*/ / f re e ( q) ; 把q指向的内存释放掉i nt ma i n( voi d )i nt * p = ( i nt * ) ma l l oc ( si ze of ( i nt) ) ; / / si ze of ( i nt) = 4 ;* p = 1 0 ;* p是内存是动

129、态分配的, i nt i 是静态的。pri ntf ( 同志们好! n ) ;re turn 0 ;pri ntf C % d n, z, * p) ; / / I Of ( p) ;pri ntf C % d n, z, * p) ; / / 2 0 0/ / f ( ) 函 数 中 f re e ( q) 作用后, 则输出- 5 7 2 6 6 2 3 0 7 ( 垃圾值)r e t u r n 0 ;2 0 1 1 - 0 5- 0 2目的:动态- 维数组示例r e a l l o c ( p Ar r , 1 0 0 )扩充动态内存空间( 原来50 变1 0 0 ;原来1 50 变1

130、0 0 )保留原来动态内存中未被截取的内容* /f t i n c l u d e # i n c l u d e i n t m a i n ( vo i d )(/ / i n t a 5 ; 系统静态地分配2 0 个字节的空间给数组ai n t l e n ;i n t * p Ar r ;p r i n t f ( 请输入你要存放的元素个数:) ;s c a n f & l e n ) ; / / 5p Ar r 二 ( i n t * ) m a l l o c ( 4* l e n ) ; p Ar r 指向这2 0 个字节动态空间的前4个字节/ *动态的构造了一个一维数组,该数组

131、的长度l e n , 数组名是p Ar r , 数组元素类型是i n t类似与i n t p Ar r l e n ; l e n 可以根据需要变化* /对一维数组进行操作,如:对动态一维数组进行赋值f o r ( i n t i =0 ; i l e n ; + + i )scanf&pA rr i ) ;p r i n t f ( 动态数组元素为: n ) ;对一维数组进行输出f o r ( i =0 ; i l e n ; + + i )p r i n t f ( % d n ” , p Ar r i ) ;f r e e ( p Ar r ) ; 动态空间被释放p r i n t f

132、( % d n ” , * ( p Ar r + l ) ) ;动态空间被释放,原来动态数组数元素内容为垃圾值- 572 662 30 7r e t u r n 0 ;/ * - - - - - - - - - - - - 在VC + + 6. 。 输出结果:请输入你要存放的元素个数:44 6 8 1 0动态数组元素为:4681 0* /使用动态数组的优点:1 . 动态数组长度不需要事先给定;2 . 内存空间可以手动释放:3 . 在程序运行中,动态内存空间大小可以通过r e a l l o c 函数手动扩充或缩小静态内存和动态内存的比较静态内存是由系统自动分配,有系统自动释放静态内存是在栈分配

133、的动态内存是由程序员手动分配、手动释放动态内存是在堆分配的/ *2 0 1 1 - 0 5- 0 2目的: 多 级 指 针 一 自 己 画 几 个 示 意 图 就 会 豁 然 开 朗 。t t i n c l u d e i n t m a i n ( vo i d )(i n t i = 1 0 ; / / ii n t * p = & i ; / / 最终 * p 就是 i ;i n t * * q = & p ; / / q只能存放i n t * 类型的地址即p的地址& pi n t * * * r = & q ; / / r只 能 存 放 i n t * * 类型的地址即q的地址& q

134、/ / r = & p ; / / e r r o r ! 因为r 是i n t * * * 类型, 只能存放i n t * * 类型变量的地址p r i n t f (, zi = % d nz ,, * * * r ) ; * r = q ; * * r = * qp r i n t f (, zi = % d n ” , * * q ) ; * q = p ; * * q 二 * pp r i n t f C i = % d n, z, * p ) ; * p = i ;p r i n t f ( i = % d nz/, i ) ;r e t u r n 0 ;)/ - - - - -

135、 - - - - - - 在VC + + 6. 0输出结果:i = 1 0i = 1 0i = 1 0i = 1 0* /t t i n c l u d e 多级指针在函数中的应用vo i d f ( i n t * * q )(* * q = 1 0 0 ; * q 就是 p)vo i d g ( )(i n t i = 1 0 ;i n t * p = & i ;p r i n t f (, zi = % d * p = % d n ,i , * p ) ;f ( & p ) ; P是i n t * 类型 & p就是i n t *类型) * * * r = * * q = * p = i

136、;= = ip r i n t f (z ,i = % d * p = % d n ” , i , * p ) ;i n t m a i n ( vo i d )(g ( ) ;r e t u r n 0 ;)一在VC + + 6. 0输出结果:i = 1 0 * p = 1 0i = 1 0 0 * p = 1 0 0*/t t i n c l u d e # i n c l u d e vo i d f ( i n t * q ) / / q 是p 的拷贝副本(* q 二 1 ;vo i d g ( i n t * * r )(* * r - 2 ;)vo i d h ( i n t *

137、* * s )* * * s - 3;vo i d i ( i n t(* * * * t = 4;要想修改函数变量的值,只能发送该变量的地址, 修改一个以上的值,必须用指针i n t m a i n ( vo i d )(i n t * p = ( i n t * ) m a l l o c ( 4) ;p r i n t f ( * p = % d n ,* p ) ; 垃圾值f ( p ) ; 调用的是指针p r i n t f ( * p 二% d n , * p ) ; / / Ig ( & p ) ; 调用的是指针变量的地址p r i n t f = % d n ,* p ) ;

138、/ / 2h ( & ( & p ) ) ; e r r o r C 2 1 0 2 : r e q u i r e s 1 - va l u ei n t * * p p = & p ; p p 是存放p 地址的指针, i n t * * 整型指针的指针类型h ( & p p ) ; 调用的是存放p 指针的指针的地址i n t * * * 整型指针的指针的指针类型p r i n t f C * p = % d n, z, * p ) ; / / 3i n t * * * p p p = & p p ;i ( & p p p ) ;调用的是一个三级指针的指针的地址,i n t * * * *

139、整型四级指针p r i n t f ( * p = d n , * p ) ; / / 4r e t u r n 0 ;跨函数使用内存的问题难点/ *2 0 1 1 - 0 5- 0 2目的:跨函数使用内存函数内的静态空间,不能被其他函数调用访问* / i n c l u d e vo i d f ( i n t * * q ) / / 理 解 为 i n t * * qi n t i =5;/ / * q 等价于p* q = i ;* q = & i ;i n t m a i n ( vo i d )(i n t * p ;* p 和* * q 都不等价于p/ / e r r o r * q

140、 等价于p推 出 p =i :错!/ / * * q = * p = i ;f ( & p ) ;p r i n t f ( % d n , * p ) ;r e t u r n 0 ;/ * 结果:5本语句语法没有问题,但逻辑上有问题内存越界:程序访问了个不该被访问的内存函数内的静态空间,不能被其他函数调用访问函数中的内存空间,随函数终止而被释放。内存空间释放后的内容不属于其他函数,其他函数无权限访问。但释放后的内存空间的地址是可以被其他函数读取的。但指针变量可以存贮任何函数中静态内存空间的地址, P 都能存垃圾, p 想存谁存谁。只是它此时已经没有权限读取( 访问) i 这个地址的数据了,

141、出错。*/*2 0 1 1 - 0 5- 0 2目的:动态内存可以跨函数访问程序运行在栈顶进行静态空间是在栈里面分配的,函数终止本质叫做出栈,所以静态空间随着函数终止而释放,动态空间是在堆里面分配的, 与栈无关,与函数终止无关,不随着函数终止而糅放。堆和栈相关深入知识就需要 数据结构和 操作系统两门课学习,而这两门课难度大,理论性强, 短期内收不到立竿见影的成效, 属于内功心法, 因此大多培训班已经取消了学习。可以用free。释放* /# inc lud e ttinc lud e void f( int * * q) * q等价p已经声明了q的类型为int * *(* q = ( int *

142、 ) ma lloc ( sizeof ( int) ) ; sizeof ( 整数类型)/*不要用4 ,因为c语言只规定short int字 节 数 小 于int字 节 数 小 于long int字节数,没有规定明确的字节数,无统一硬性规定。不同软件系统可能出现不同,统 用sizeof( int)来获取实际值int * p;在p声明的情况下,构造动态空间也可以写成p = ( int * ) ma lloc ( sizeof ( int) ) ;* / / * q等价p ,等价于 p = ( int * ) ma lloc ( sizeof( int) ) ;/ / q = 5 ; / / e

143、rror! q指针/ / * q = 5 ; / / error! p = 5* * q = 5 ; / / O K !等价于 * p = 5int ma in( void )(int * p;f( & P ) ; 只有调用变量的地址,才能改变变量的值printf( % d n , * p) ; 函数中,没有free( q) ;所以动态空间仍然保留,动态空间中的内容可以被访问return 0 ;/ *- - - - - - - - - - - 在V C + + 6 . 0输出结果:5* /枚举什么是枚举把一个事物所以可能的取值一一列举出来/ *日期:2 0 1 1 - 0 5 - 0 4目的:

144、枚举* /# inc lud e 自定义了一个数据类型,并没有定义变量,该数据类型的名字enumW eekD a yenum W eekD a y(/ / M onD a y, T uesD a y, W ed nesD a y, T hursD a y, F riD a y, S a turd D a y, S und a yM onD a y= 1 0 , T uesD a y, W ed nesD a y, T hursD a y, F riD a y, S a turd D a y,S und a y ; 分号int ma in( void )(/ / int d a y; d a y

145、定义成int类型范围太大不合适,d a y的取值只可能有7个( 0 - 6 ) ,浪费空间enum W eekD a y d a y = F riD a y; 初始化一个enum W eekD a y 类型变量 d a yprintf ( % d n ,d a y) ;return 0 ;)/ *- - - - - - - - - -在V C + + 6 . 0输出结果:41 4* /怎么使用枚举/*日期:2 0 1 1 - 0 5 - 0 4目的:枚举2*/# inc lud e enum weekd a y(M onD a y, T uesD a y, W ed nesD a y, T h

146、ursD a y, F riD a y, S a turd D a y, S und a y) ;void f ( enum weekd a y i) 本函数的目的只是期望接受0-6之间的数字,将形参定义为枚举s w i t c h (i )(c a s e 0:p r i n t f (/zM o n D a y ! n );b r e a k ;c a s e 1:p r i n t f (z ,T u e s D a y ! n );b r e a k ;c a s e 2:p r i n t f (z ,W e d n e s D a y ! n );b r e a k ;c a s

147、e 3:p r i n t f ( T h r u s D a y ! n );b r e a k ;c a s e 4:p r i n t f (? ,F r i D a y ! n );b r e a k ;c a s e 5:p r i n t f (, zT h u r s D a y ! n );b r e a k ;c a s e 6:p r i n t f (z /S u n D a y ! n );b r e a k ;i n t m a i n (v o i d )(f (F r i D a y );虽然F r i D a y 本质上就是5 , 但直接写出f (5);就是错的

148、,也不可能写成F r i d a y 大小写敏感r e t u r n 0;枚举的优缺点优点:代码更安全(强制输入),比较直观(有意义)缺点:书写麻烦,不能出错。总结:当是有限个元素时,用枚举更安全,高效。位运算符约 翰 冯 诺 依 曼 (J o h n V o n N o u m a , 19031957), 美藉匈牙利人被称为计算机之父:2大贡献二进制计算机设备分类:运算器控制器存储器输入设备输出设备什么是进制数字是本质,进制只是不同表现方式一个十六进制位,要用4个二进制数表示,(1) 1 6 =(0001) 2 前面补齐二进制逢二进一十进制 逢十进一 d e c八进制 逢八进一 o c

149、t 0数 字 i n t i = 05;十六进制 逢十六进一 h e x O x 数 字 0X 数字i n t i = 0x 5;i n t i = 0X 5;生活中:七进制 七天进周十二进制十二月进年二十四进制二十四小时进日六 十 进 制 六十分钟进小时六十秒钟进分钟汇编里1101B 二进制13570八进制2049D 十进制3F B 9H 十六进制十进制(D )二进制(B )八进制(0)十六进制(H )000011112102231133410044510155611066711177810001089100111910101012a(A )11101113b(B )12110014c(c

150、)X)/1717DEFz(z(/(def5671111111c( lu1Xt-H1X1X1A1r-H34516 I00002010017 = 7 + I*8= 150x17 = 7 + 1*16 = 251234 = 4 + 1*10三次方 + 2*10 二次方 + 3*10一次方0x32c = c + 3*16 二次方 + 2*16一次方=4354最高累数是位数T#i n c l u d e i n t m a i n (v o i d )i n t i = 0x 32c ;p r i n t f (z /i = %d n, z, i );p r i n t f f i = i );p r

151、i n t f (, zi = %o n, z, i );/*p r i n t f的用法% d以十进制输出% x或% X以十六进制输出% o或% 0以八进制输出* /r e t u r n 0; i n c l u d e i n t m a i n (v o i d )(i n t i = 1000;p r i n t (%X n , i ) /3E 8p r i n t f r %#X n, z, i ) /0X 3E 8 %#X 推荐r e t u r n 0;补码:原码:也叫符号绝对值最高位0表示正1表示负,其余二进制位是该数字的绝对值的二进制位在计算机中,从未被使用!反码反码运行不

152、便,也没有在计算机中应用移码表示数值平移n位,n称为移码量移码主要用于浮点数的阶码的存储补码地址是内存单元编号从。 到4G-1即2的32次方-1 总线若是32位,则有32个0, 1主要解决整数的存储int 4字 节32位个0, 1A已知十进制求二进制求正整数的二进制除2取余,直到商为零,余数倒序排列求负整数的二进制先求出与该负数相对应的正整数的二进制代码,然后,将所有位取反末尾加1 ,不够位数时,左边补一4字节int - 5先求5的二进制0000 0000 0000 0000 0000 0000 0000 0101 所有位取反,末尾加 11111 1111 1111 1111 1111 111

153、1 1111 1011 16进制:FFFFFFFB2字 节short int (-3 )先求3的二进制0000 0000 0000 0011 所有位取反,末尾加11111 1111 1111 1101 用十六进制表示: FFFD求零的二进制全是零B已知二进制求十进制如果首位是0 ,则表明是正整数,按普通方法来求如果首位是1 ,则表明是负整数,将所有位取反末尾加1 ,所得数字就是该负数的绝对值习题:FFFFFFF5已 知 二 进 制 求其代表的整数是多少?1111 1111 1111 1111 1111 1111 1111 0101由于最高位是1 ,所以最终是负数,先对其所有取反0000 000

154、0 0000 0000 0000 0000 0000 1010 末尾加 1 后0000 0000 0000 0000 0000 0000 0000 1011 该值为 11 所以最终结果:T1如果全是零,则对应的十进制数字就是零C二 进 制 到 十 六 进 制4位一段从右到左分别转化 不够左边初零(0010 1110) 2 - (2E) 16D十六进制到二进制一位转化成4 位,不够左边补0( 1 ) 1 6 ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ) 2E二进制转到八进制从右往左,三位一段不够被0F八进制

155、与十六进制不能直接转化。通过中间进制。进制总结:进制属于什么知识点,许多人爱不懂装懂。学习好它有利于将来学习底层如汇编等知识,但要往高级语言发展则不需要掌握,另外学好它对后面位运算等有帮助。学习后应掌握:在在V C + + 6 . 0 中一个i n t 类型变量所能存储的数字的范围是多少3 2 位系统,3 2 个0 , 1 组合表示的内存单元,8 个十六进制数组合)i n t 类型变量所能存储的最大正数用十六进制表示: 7 F F F F F F Fi n t 类型变量所能存储的绝对值最大负整数用十六进制表示:8 0 0 0 0 0 0 0最小负数的二进制代码是多少 1( 0 - 0 3 1

156、个0 )最大正数的二进制代码是多少 0 ( 1 - 1 3 1 个1 )已知一个整数的二进制代码求原始的数字按“ 已知二进制求十进制 求数字超过最大正数会怎样 变成负数0 1 1 1 1 1 1 1 = 1 2 7 1 0 0 0 0 0 0 0 - 1 2 8不同数据类型转化丢失最高位. 只截留后者类型所占的字节数。例如: i n t 类 型 转 化 为c ha r则高3 位字节被截取。只保留最后一位字节。结构体 ( 非重点)为什么需要结构体为了表示一些复杂的事物,而普通的基本类型无法满足实际要求。什么叫结构体把一些基本类型数据组合在一起形成的一个新的复合数据类型。如何定义结构体3 种方式:

157、/ / 第一种只是定义了一个新的数据类型,并没有定义变量推荐采用1s t ru c t S t u d e n t I nt a g e ;F l oa t sc ore ;C h a r se x ; ;第二种struc t Stud e nt I nt a g e ;F l oa t sc ore ;C h a r se x ; st;/ / 第三种struc t I nt a g e ;F l oa t sc ore ;C h a r se x ; st;怎样强用结构体变量赋值和初始化定义的同时可以整体赋值。如果定义完之后,则只能单个赋初值。如果取出结构体变量中的每一个成员 重点1结构体

158、变量名. 成员名2指针变量名_ 成员名( 更常用)它会在计算机内或转化成( * 指针变量名) . 成员名的方式来执行。所以两者是等价的。例子:Struc t Stud e nt(I nt a g e ;F l oa t sc ore ;C h a r se x ;) ;I nt ma i n( voi d )(Struc t Stud e nt st = 8 0 , 6 6 . 6 f , F ;初始化定义的时候赋值6 6 . 6 在C 语言中默认是d oub l e 类型,如果希望一个实数是f l oa t类型,则必须在末尾加f 或F,因此6 6 . 6 是d oub l e , 6 6 .

159、 6 f 或6 6 . 6 F 是f l oa tstruc t Stud e nt st2 ;st2 . a g e = 1 0 ;st2 . sc ore = 8 8 ;st2 . se x = F ; / / 第二种方式单独赋值Struc t Stud e nt * pst = & st; / / & st 不能写成 stPst- a g e = 8 8 ; / / 通过结构体指针变量pri ntf (z z% d st. a g e , pst- sc ore ) ;Return 0;)理解:1 pst- age会在计算机内部转化成(*pst). a g e 的方式来执行, 没有为什么

160、,这就是- 的含义,这也是一种硬性规定。2 所 以 pst- age等价于 (*pst). age也等价于st. age3 pst- 的含义:pst所指向的那个结构体变量中的age这个成员。结构体变量的大小略大于其内部成员类型所占字节数之和。 试: sizeof(struct)若想通过函数对主函数结构体变量进行修改,则主函数必须发送地址,外函数定义指针结构体变量,通过外函数内部语句完成对变量的修改。而仅想输出、读取操作,则不用传地址,定义指针过程。例:/ *2009年11月24日9:17:43通过函数完成对结构体变量的输入和输出* /# include # include struct Stu

161、dent(int age;char sex;char name100; ; 分号不能省void I nputStudent(struct Student *);void OutputStudent(struct Student ss);int main(void)(struct Student st: 15行I nputStudent (&st); 对结构体变量输入必须发送st的地址/printf (z,%d %c %sn” , st. age, st. sex, st. name); / / 此行和 下行输出函数功能相同OutputStudent(st); 对结构体变量输出可以发送st的地址

162、也可以直接发送st的内容return 0;)void OutputStudent(struct Student ss)pri ntf ( % d % c % s n” , ss. a g e , ss. se x , ss. na me ) ;voi d I nputStud e nt ( struc t Stud e nt * pstu) pstu只占4个字节( * pstu) . a g e = 1 0 ;/ / pstu- na me = 张三丰 ; 或( * pstu) . na me = 张三丰 ; 都是e rror, 提示错误信息:c a nnot c onve rt f rom

163、c h a r 5 to 5 c h a r 1 0 0 strc py ( pstu- na me , 张三丰 );用字符串拷贝命令解决问题pstu- se x = F ;)/ *本函数无法修改主函数1 5行st的值 所以本函数是错误的voi d I nputStud e nt( struc t Stud e nt stu)(stu. a g e = 1 0 ;strc py ( stu. n a m e , 张三” ) ; 不能写成 stu. na me = 张三” ;stu. se x = F ;)*/结构体:应该发送地址还是内容设计函数的目的:必须考虑功能单一, 还要考虑安全因素C +

164、 +中指针前可加c o n s t则只能读而不能修改其指向的变量。指针的优点:耗用内在小(4字节)快速传递数据执行速度快。因此:推荐使向结构体变量作为函数参数来传递/*2 0 0 9年 1 1 月2 4 日 9 : 1 7 : 4 3示例:发送地址还是发送内容目的:指针的优点之一:快速的传递数据,耗用内存小执行速度快*/# include # include struct Student(int age;char sex;char name100; ; 分号不能省void I nputStudent(struct Student *);void OutputStudent(struct Stu

165、dent *);int main(void)(struct Student st ; 15行/printf(%dn, sizeof(st);I nputStudent (&st); 对结构体变量输入必须发送st的地址OutputStudent (&st); 对结构体变量输出 可以发送st的地址也可以直接发送st的内容但为了减少内存的耗费,也为了提高执行速度,推荐发送地址return 0;)void OutputStudent(struct Student *pst)(printf (z ,%d %c %sn” , pst- age, pst- sex, pst- name);)void I n

166、putStudent (struct Student * pstu) pstu只占4个字节(*pstu). age = 10;strcpy (pstu- name,“ 张三);pstu- sex = F;)结构体变量的运算不能加减乘除操作,只能相互赋值。例如:struct Student(I nt age;Char sex;Char100;);S truc t S tud e nt strl , str2 ;S trl = str2 / str2 = strl ; 都是正确的。举例:动态构造存放学生信息的结构体数组# i nc l ud e # i nc l ud e / / 必须先添加头文件

167、 m a l l ocstruc t S tud e nt(i nt a g e ;f l oa t sc ore ;c h a r na m e 1 0 0 ; ;i nt m a i n(voi d )(i nt l e n;struc t S tud e nt * pA rr;i nt i , j ;struc t S tud e nt t;动态的构造一维数组pri ntf (请输入学生的个数: n);pri ntf (l e n = );sc a nf ( %d , &l e n);pA rr = (struc t S tud e nt * )m a l l oc (l e n * s

168、i ze of (struc t S tud e nt);/ / pri ntf C,%d n, z, si ze of (struc t S tud e nt); / / 1 0 8 字节输入f or (i = 0 ; i l e n; + + i )pri ntf (请输入第%d 个学生的信息: n ,i + 1 );pri ntf (a g e = );s can f& p Ar r i . a g e );pri ntf ( na m e = );sc a nf pA rr i . na m e ); na m e 是数组名,本身就已经是数组首元素的地址,所以pA rr i . na

169、m e 不能改成&pA rr i . na m epri ntf ( sc ore = );s c a n f & p A r r i . sc ore );按学生成绩升序排序冒泡算法for (i=0; ilen-l; +i)(for (j=0; j pArrj+l. score) / / 升序 降序(t = pArrj; / / 注意 t 的类型为 Struct StudentpArrj = pArrj+l;pArrj+l = t;)printf (nn学生的信息是: n);输出for (i=0; ilen; +i)(printf ( 第知个学生的信息是: n ,i+1);printf(ag

170、e = %dn, pArri. age);printf(name = %sn, z, pArri. name);printf(score = pArrEi. score);printf(n);)return 0;总结:对于一个人事管理或图书管理项目,分析流程:第一步;存储第二步:操作第三步:输出前两个过程最难、最 核 心 是 “ 数据结构”研究的重点,一般都屏蔽了。数组和变量虽然都可以存储,但都不完美。比如:人事关系图、交通图等,都不好用数组保存。从事关系结构只能用“ 树”还保存,而对于两个起终点:公交线路查询,实现时间最小/ 距离最短/ 花费最低等功能,只能用“ 图”来存。而图和树都必须有指

171、针知识,它们属于较高深的思想层次的东西。因此要学好数据结构必须要懂得指针。若感兴趣:可以继续学习郝斌老师的 数据结构教学视频。链 表 ( 较难)C语言和数据结构的连接( 过渡)链表是数据结构第一部分而是C语言最后一章内容, 由此可以比较两者难算法:通俗定义:解题的方法和步骤狭义定义:对存储数据的操作对不同的存储结构,要完成某一个功能所执行的操作是不一样比如:要输出数组中所有的元素的操作和要输出链表中所有的元素的操作 是不一样的这说明:算法是依附于存储结构的不同的存储结构,所执行的算法是不一样的广义定义:广义的算法也叫泛型C+无论数据是如何存储的,对该数据的操作都是一样的分层思想,站在更高的层次

172、看,把内部的实现给屏蔽数组和链表都是线性的,都是先输出一个元素后,再输出下一个元素我们至少可以通过两种结构来存储数据数组优点:存取速度快缺点:需要一整块连续的空间( 对于庞大数据, 往往没有一个适合的较大的连续的空间如a30000000000000)插入和删除元素效率很低( 插入和删除中间某个元素,其后的所有都要前后移动)链表优点:插入删除元素效率高缺点:查找某个位置的元素效率低( 由于不是连续的,不同由下标直接找,必须由头至尾逐一比对查找)两者各有所长, 至今没有出现一个更优的存储方式, 可集数组、 链表优点于一身。链表专业术语:首结点:点放第一个有效数据的结点尾结点:东放最后一个有效数据的

173、结点,指针域的指针为N U L L ,尾结点的标志头结点:头结点的数据类型和首结点的类型是一模一样的头结点是首结点前面的那个节点头结点并不存在有效数据设置头结点的目的是为了方便对链表的操作头指针:存放头结点地址的指针变量确定一个链表需要一个参数,头指针对于每个链表元素,分为左右两部分,左边为数据单元,右边为下一元素地址。例:# i n c l u d e # inc lu d e i t inc lu d e s t ru c t N od e(int d at a; 数据域s t ru c t N od e * pN e x t ; 指针域);函数声明s t ru c t N od e *

174、c re at e _lis t (v oid );v oid t rav e rs e _lis t (s t ru c t N od e *);int main(v oid )(s t ru c t N od e * pH e ad = N U L L ;pH e ad = c re at e _lis t ();c re at eis t ():就建一个非循环单链表,并将该链表的头结点的地址付给pH e adt rav e rs e _lis t (pH e ad );re t u rn 0 ;)s t ru c t N od e * c re at e _lis t (v oid )i

175、nt le n; 用来存放有效节点的个数int i;int v al; 用来临时存放用户输入的结点的值分配了 一个不存放有效数据的头结点s t ru c t N od e * pH e ad 二(s t ru c t N od e *)malloc (s iz e of (s t ru c t N od e );if (N U L L = = pH e ad )(print f (分配失败,程序终止! n );e x it (- 1 );)s t ru c t N od e * pT ail = pH e ad ;pT ail- pN e x t = N U L L ;print f (请输入

176、您需要生成的链表节点的个数:le n = );sca n f& l en ) ;f or (i= 0 ; i d at a = v al;pT ail- pN e x t = pN e w ;pN e w - pN e x t = N U L L ;pT ail = pN e w ;re t u rn pH e ad ;)v oid t rav e rs e _lis t (s t ru c t N od e * pH e ad )(s t ru c t N od e * p = pH e ad - pN e x t ;w h ile (N U L L ! = p)(print f (%d ”

177、 , p- d at a);p = p- pN e x t ;)print f ( n );re t u rn;)对于以上例题:不要求逐行敲出,但要能看懂。字符串的处理两种: 字 符 数 组 字 符 指 针位运算& 按 位 与 一 每 一 位 都 按 位 与 (区别&j取地址)1 &1 = 11 &0 = 00 &0 = 00 &1 = 0I按 位 或 一 每一位都按位与取反 一每一位取反按 位 异 或 一 相 同 为 零 不 同 为11 0 = 10 1 = 11 1 = 00 *0 = 0 按 位 左 移 一左移n位相当于乘以2的n次方i 3表示把i的所有二进制位左移动3位 ,右边补零面试

178、题:A ) i = i*8 ;B ) i = i 3 ;请问上述两个语句,哪个语句执行的速度快答案:B快乘法在运算器里,运行原理比较复杂按位左移,简单! 按位右移 一右移n位相当于除以2的n次方,首位为0补0 ,首位是1补1i 3表示把i的所有二进制位右移动3位,左边补零防止过度右移,容易丧失精度和意义位运算的现实意义:通过位运算符,我们可以对数据的操作精确到每一位。N U L L 二进制全部为零的含义:- 0 0 0 0 0 0 0 0 0 0 的含义1 ,数值零2 . 字符串结束标记 0 3 .空指针N U L LN U L L表示零,而这个零不代表数字零,而表示的内存单元的编号零我们计算

179、机规定了,以零为编号的存储单元的内容不可读,不可写f re e (p);p = N U L L ;*P = 0 ;错 !把0号单元改写! 0单元是非常重要的数据。程序员不可能读写出0号单元信息纯C的知识( 略)文件不是用 流 的思想,用函数实现, 于ja va C +没联系宏ty p e d e f期末考试1 . 什么叫分配内存,什么叫释放内存分配内存:操作系统把某一块内存空间的使用权力分配给该程序内存释放:操作系统把分配给该程序的内存空间的使用权力收回,该程序就不能使用这块内存空间附注:释放内存不是把该内存的数据清零2 .变量为什么必须初始化不初始化,变量通常是垃圾值,很可能是上次程序结束遗

180、留下来的数据。3 . 详细说明系统如何执行:i n t i = 5 ;这条语句的1 V c +6 . 0软件请求操作系统为i分配存储空间2 操作系统会在内存中寻找一块空闲的区域,把该区域当作i来使用3 V c +6 . 0会把i和这块空间区域关联起来,今后对字母i操作就是对这块空闲的区域操作。4 把5存储到字母i所关联的内存区域中附注:所谓内存区域也就是内存的一块存储单元4 .详细列出C语言所有基本类型i n t l o n g i n t sh o r t i n t c h a r f l o a t d o ub l e5 . 在p r i n tf函数中,i n t用%d输出,请问:l

181、 o n g i n t c h a r d o ub l e f l o a t分别用什么输出?%l d %c %l f %f6 .函数的优点1 避免重复操作2 有利于程序的模块化7 .谈谈你对函数的理解8 . 什么是指针,什么是地址,什么是指针变量,三者之间的关系?地址是内存单元的编号指针就是地址指针和地址是同一个概念指针变量是存放内存单元编号的变量指针变量和指针是两个完全不同的概念,只不过人们通常把指针变量称作指针9 .请写出静态变量和动态变量的异同相同点:都需要分配内存不同点:静态变量是由系统自动分配,自动释放,程序员无法在程序运行的过程当中手动分配,也无法在程序运行的过程中手动释放。

182、静态变量是在栈中分配的,只有在函数终止之后,静态变量的存储空间会被系统自动释放。动态内存是由程序员手动分配,程序员可以在程序运行的过程当中手动分配,手动释放。动态变量是在堆中分配的,程序员可以在行是执行过程中的任何时刻手动释放动态变量的空间不需要等到函数终止才释放。1 0 . C语言中哪些知识点是我们学习的重点,请一一列举出来流程控制函数 指针 静态内存和动态内存U . f o r ( l ; 2 ; 3 )A ;B;1 2成立,会继续执行哪条语句:A2 3执行完毕后,会继续执行哪条语句:23 A执行完毕后,会继续执行哪个语句:34 1总共会执行几次:1次12. f o r ( l ; 2;

183、3)f o r ( 4; 5; 6)(A ;B ;)C;1 6执行完毕后,会继续执行哪个语句:52 5成立,会继续执行哪个语句:A3 5不成立,会继续执行哪个语句:34 2不成立,会继续执行哪个语句:C5 2成立,会继续执行哪个语句:46 A和B语句是否一定会被执行不 会( 2或5不成)7 C语句是否一定会执行是13. f o r ( l ; 2; 3)(w hil e ( 4)5;6;b r e a k;if 8 ;9 ;)10 ;1 5执行完毕后,会继续执行哪个语句:42 b r e a k终止什么? 终止f o r , b r e a k终止最里层包裹它的循环3 如果8是b r e a

184、k语句,贝 !8执行完毕之后会继续执行哪个语句104 如果7不成立,会继续执行哪条语句9方法:调整清楚f o r ( 1; 2; 3)w hil e ( 4)5;)6;b r e a k;if ( 7)(8;)9 ;)10 ;1 4 判断下列程序语法上是否有错误,说出错误原因A ) in t * p ; * p = 10 ; 错 p 没有指向,* p 数据不可读和操作B ) c ha r * p ; c ha r c h=A ; p =&c h; 错 A 改成 A A 非法无意义C) in t i, j; i=j=0 ; in t * p ; p =&i; 对 i=j=0 ; 从右向左D )

185、in t * p ; in t * * q ; q = &p ; 对指针的指针是in t * * 类型E ) in t * p ; in t i=5; p =&i; * p =10 ; 对 p 指向i, * p =5; 把 10 赋值给* p1 5 编程实现:如果x大于0 , 则y 为1. 如果x小于0 , 则y 为- 1 , 如果x等于0 , 则y为0,以下程序段中,不能根据x值正确计算出y 值 的 是 CDA ) if ( x 0 ) y =l ;e l s e if ( x=0 ) y =0 ;e l s e y =- l ;B ) y =0 ;if ( x 0 ) y =l ;e l

186、s e if ( x =0 ) ; ( ; 空语句)if ( x 0 ) y =l ;D ) if ( x =0 )if ( x 0 ) y =l ;e l s e y =0 ;16. 若变量已正确定义,有以下程序段in t a =3, b =5, c =7;if ( a b )a =b ;c =a ;if ( c !=a )c =b ;p r in t f (, z%d , %d , %d n ” , a , b , c ) ;输出结果是:BA ) 程序段有语法错误B ) 3, 5, 3C) 3, 5, 5 D ) 3, 5, 717 . 执行以下程序后,输 出 的 个 数 是 :6t t

187、in c l ud e in t m a in ( vo id )(in t i, j;f o r ( i=l ; i5; i+ + )f o r ( j=2; j=i; j+ + )p r in t f ( %c n , ;r e t ur n 0 ;18 . 有以下程序 in c l ud e in t m a in ( vo id )(in t i, s =0 ;f o r ( i=l ; i10 ; i+ =2)s + =i+ l ; / / s = s + ( i + 1) ;p r in t f ( %d n , s ) ;r e t ur n 0 ;)程序执行后的结果是: DA)

188、自然数19 的累加和B)自然数110 的累加和0 自然数19 中的奇数之和D)自然数110 中偶数之和19 . 若有一些定义和语句in t a = 4;in t b = 3;in t * p ;in t * q ;in t * w ;p =&a ;q =&b ;w = q ;q = N U L L ;则以下选项中错误的语句是AA ) * q =0 ; B ) w =q ; C) * p =88; D ) * p =* w ;2 0以下程序#in c l ud e vo id f un ( c ha r * a , c ha r * b )a =b ; 指针a b 相互指向,则他们的值相同( *

189、 a ) + + ;)in t m a in ( vo id )(c ha r c l = A , c 2= ,a , * p l , * p 2;p l =&c l ;p 2=&c 2;f un ( p l , p 2) ;p r in t f ( %c %c n ” , c l , c 2) ;)程序运行后的输出结果是:A b实验程序/ *#in c l ud e vo id f un ( c ha r * a , c ha r * b )(p r in t f (, z%c 枇 n ” , * a , * b ) ; / / A aa =b ;p r in t f ( 枇 %c n, z

190、, * a , * b ) ; / / a a( * a ) + + ;p r in t f (, z%c %c nz /, * a , * b ) ; / / b b)in t m a in ( vo id )(c ha r c l= ,A * , c 2=* a , * p l , * p 2;p l =&c l ;p 2=&c 2;f un ( p l , p 2) ;p r in t f ( 猊 %c n ” , c l , c 2) ; / / A b* / in c l ud e in t m a in ( vo id )(in t i = 0 ;in t j = 1;in t *

191、 a = &i;in t * b = &j;a =b ; / / O K 互为指向 * a =* b =l ;p r in t f (, z%d %d n ” , * a , * b ) ; / / I 1* /* a + =l ;p r in t f (, z%d %d n ” , * a , * b ) ;2 2 指针a和指针互为指向,改变*a的值,就是改变* b的值/ *a =a + 2; 把指针a的址编号加2, b不指向a ,1)仍然指向a原来的地址无法知道与a地址相隔2个单元的内容*a .p r in t f ( %d %d n ,* a , * b ) ; / / 12450 88 2r e t ur n 0 ;21 .若有定义:in t k;以下程序段的输出结果是:#2#4f o r ( in t k=2; k6; K + + , K + + ) pri ntfk );K + + , K + + = 1个循环因子22 . b r e a k23 .进制转化24 . C的一些认识问题。此致:郝斌老师的C语言教程全部结束。课堂讲解全程动手敲代码,讲解细致,对于重要知识点的讲解不厌其烦,是一个难得的C语言入门教程。在这里对老师的辛勤付出表示感谢。2014-3-8

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号