导图社区 考研C语言思维导图
考研计算机C语言笔记整理,内容非常详细,针对历年高频考点制作,方便给正在备考计算机专业研究生考试的同学们查漏补缺。
编辑于2020-11-13 15:14:29listener 音标['lisnә] 读音 汉语翻译 n. 收听者, 听众 英语解释: 名词listener: someone who listens attentively 同义词:hearer, auditor, attender
Filter过滤器(重要) Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作。 1、Filter快速入门 1.1、步骤: 1. 创建一个类实现Filter接口 2. 重写接口中方法 d...
会话的解释 [conversation] 指两人以上的对话(多用于学习别种语言或方言时) 详细解释 (1).聚谈;对话。现多用于学习别种语言或方言时
社区模板帮助中心,点此进入>>
listener 音标['lisnә] 读音 汉语翻译 n. 收听者, 听众 英语解释: 名词listener: someone who listens attentively 同义词:hearer, auditor, attender
Filter过滤器(重要) Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作。 1、Filter快速入门 1.1、步骤: 1. 创建一个类实现Filter接口 2. 重写接口中方法 d...
会话的解释 [conversation] 指两人以上的对话(多用于学习别种语言或方言时) 详细解释 (1).聚谈;对话。现多用于学习别种语言或方言时
807C语言
基础知识
编译过程
C语言编译的程序称为源程序(.c),又称编译单位,以ASCII数值存放在文本文件中
C编译程序的功能
对C源程序进行语法检查,若无语法错误,翻译成目标代码,最后形成可执行文件
预处理(.i)
展开头文件 宏替换 去掉注释 条件编译
gcc -E hello.c -o hello.i
将hello.c预处理输出hello.i文件。
编译(.s)
检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,把代码翻译成汇编语言
语义分析 语法分析 词法分析 符号汇总
gcc –S hello.i –o hello.s
将预处理输出文件hello.i汇编成hello.s文件
汇编(.obj)
编译阶段生成的”.s”文件转成二进制目标代码
形成符号表,转为机器语言
gcc –c hello.s –o hello.o
将汇编输出文件test.s编译输出test.o文件。
链(.exe)
1、合并段表 2、符号表的合并和符号表的重定位
gcc hello.o –o hello.exe
将编译输出文件hello.o链接成最终可执行文件hello.exe
编译预处理不是C语言的一部分,不占运行时间,不要加分号
#define PI 3.1415926;这个写法是错误的,一 定不能出现分号
数制及转换
定义
十进制
逢10进1
0-9
例子
1234 34561 348758
是十进制
23e9a1
不是,出现0-9以外的字符
09111
不是,前面加0有特殊含义
二进制
C语言不支持
逢2进1
0-1
八进制
标志
0
逢8进1
0-7
十六进制
标志
0x
逢16进1
0-9 A-F(大小写均可)
进制转换
十进制-->二进制
除2取余倒排
二进制-->十进制
按位乘权相加
二进制-->八进制
三位压成一位
000-->0
001-->1
010-->2
011-->3
100-->4
101-->5
110-->6
111-->7
八进制-->二进制
一位展成三位
二进制-->十六进制
四位压成一位
0000-->0
0001-->1
0010-->2
0011-->3
0100-->4
0101-->5
0110-->6
0111-->7
1000-->8
1001-->9
1010-->A
1011-->B
1100-->C
1101-->D
1110-->E
1111-->F
十六进制-->二进制
一位展成四位
数据类型
基本数据类型
字符类型(char)(也可看做整型)
1字节
整型类型
短整型(short)
2字节
整型(int)
4字节
长整型(long)
32位:4字节
64位:8字节
浮点类型(也叫实型)
单精度浮点型(float)
4字节
双精度浮点型(double)
8字节
派生类型
指针类型(*)
数组类型([])
结构体类型(struct)
共用体类型(union)
枚举类型(enum)
空类型(void)
标识符
概念
标识符是给常量或者变量起的名字
标识符可以是字母(A~Z,a~z)、数字(0~9)、下划线_组成的字符串,并且第一个字符必须是字母或下划线
类型
关键字(32个)
main不是关键字
关于数据类型的关键字(12)
char int long short double float signedunsigned struct enum union void
关于控制语句的关键字(12)
循环语句
for do while
条件判断语句
if else switch case default
跳转语句
goto continue break return
关于存储类型的关键字(4)
auto extern register static
其它一些关键字(4)
const sizeof typedef volatile
预定义标识符
define、scanf、printf、include
用户自定义标识符
注意事项
标识符不能是C语言关键字
可以用用预定义标识符但不建议
标识符不能重复定义
标识符大小写敏感
标识符长度不要太长
标识符最好见名知意
常量
概念
程序运行过程中,值不会改变的量,一般用来给变量赋值,直接放在等号的右边(这样的常量也叫字面量)
如int a = 120;float b = 0.1234;// 等号左边的a,b是变量(标识符),等号右边的整数和小数是字面量
类型
符号常量
用编译预处理语句(不是C语言的语句)声明的常量叫符号常量如:#define 标识符 常量值
这样的常量在编译前,定义的标识符就会被预处理,整体替换为后面的常量值
字面量
字面量通常是直接写在赋值(=)号右边的常量
类型
整型常量
整数,通常指十进制整数,由0-9的数字组成,可带正负号,如6,+100,-3等
类型
八进制整型常量
八进制整数,以0开头,由0-7的数字组成,可带正负号,如-01,011,+077等
十进制整型常量
通常意义上的整型常量
十六进制整型常量
十六进制整数,以0x开头,由0-9的数字和字母a-f组成,可带正负号,如0x17a,-0xffff,+0xabc123,0XabA1(字母可大写,可大小写混合)
注
C语言中没有二进制整型常量
若表示长整型常量必须后加字母l或L,如0L
实型常量
小数,一般不考虑进制,即默认为十进制小数,当小数点前一位只有0时,可以省略0,即0.121还可以表示为.121;同理指数形式也可省略,0.2e3还可以表示为.2e3
类型
十进制小数形式
由数字和小数点组成,可带正负号,如0.123,+6.24,-3.2等
指数形式
以字母e代表10为底的指数,指数只能是整数(即e3表示10的3次方,e-5表示10的-5次方),如12.3e-5,3.1e10,+1e0,,1.2e3
注
指数形式,当小数点前面只有0,且e前没有整数时,0不可省略,如0.e5,如果省略就变成了.e5,是错误的
字符常量
用单引号括起来的字符,通常只有一个字符,转义字符除外
类型
普通字符
用单引号括起来的一个字符,如‘a’,‘3’,‘A’,‘$’,‘ ’,'"'等
大小写字母转换
‘A'+32='a' 相互之间一般是相差32
字符可以进行算术运算
转义字符
\--->转移标志
'\n'换行符
'\t'制表符
Tab
'\b'退格符
backspace
'\r'回车符
注
'\'不合法
'\\'表\
八进制字符
用单引号括起来的以\开头,由0-7的数字组成的串,最多只有三位数字,理解的时候转换为十进制所对应的ASCII码所对应的字符即可,如:'\041','\040'
十六进制字符
用单引号括起来的以\x开头,由0-9的数字和a-z的字母组成的串,最多只有两位,理解的时候转换为十进制所对应的ASCII码所对应的字符即可,如:'\x28','\x29'
字符串常量
用双引号括起来的零个或者多个字符(可以是上面的字符常量组成)
如"abd","sdf123"
注意
每一个字符串尾都有一个字符串结束符'\0'
C语言中没有字符串常量
借存
字符型数组
字符型指针
变量
程序运行过程中,值可以改变的量
要点
变量会占据内存中一定的存储单元
使用变量之前必须先定义
变量定义的一般形式为:数据类型 变量名
可以同时定义多个类型相同的变量:数据类型 变量名, 变量名, 变量名…
变量名和变量值是完全不同的两个概念
变量名必须满足标识符的规范
数据类型必须是C语言数据类型
如果定义了变量未赋值就使用,那么该变量的值将不可预测
static变量
给变量赋值的方式
先定义后赋值
定义的同时赋值
注
变量在定义中不允许连续赋值,如:int a = b = c = 3;是错误的语句,但是已经定义好的变量允许连续赋值
输入与输出
概念
C语言没有输入输出语句
C语言的输入输出操作都需要依赖库函数,常用的输入输出函数是scanf()和printf() ,使用时一定要先引入头文件#include<stdio.h>
一个算法可以没有输入,但是一定要有输出
printf()函数
格式化输出函数
函数原型
int printf(const char *format, ...)
用法
printf(“格式控制字符串”, 输出列表)
功能
将变量转化为“格式控制字符串”所规定格式的数据,然后输出到终端中
格式字符串是以%开头的字符串,在%后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等,一般形式为[标志][输出最小宽度][.精度][长度]类型,(注意:[]表示可省略的项)
类型
d
以十进制形式输出带符号整数(正数不输出符号)
0
以八进制形式输出无符号整数(不输出前缀0)
x,X
以十六进制形式输出无符号整数(不输出前缀Ox)
u
以十进制形式输出无符号整数
f
以小数形式输出单、双精度实数
e,E
以指数形式输出单、双精度实数
g,G
以%f或%e中较短的输出宽度输出单、双精度实数
c
输出单个字符
s
输出字符串
标志
-
结果左对齐,右边填空格
+
输出符号(正号或负号)
空格
输出值为正时冠以空格,为负时冠以负号
#
对c、s、d、u类无影响;
对o类,在输出时加前缀o;
对x类,在输出时加前缀0x;
对e、g、f 类当结果有小数时才给出小数点
输出最小宽度
用十进制整数来表示输出的最少位数。若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0
精度
精度格式符以“.”开头,后跟十进制整数
长度
长度格式符为h、l两种,h表示按短整型量输出,l表示按长整型量输出
scanf()函数
格式化输入函数
函数原型
int scanf(const char *format, ...)
用法
scanf("输入控制符", 输入参数)
功能
将从键盘输入的字符转化为“输入控制符”所规定格式的数据,然后存入以输入参数的值为地址的变量中
输入控制符几乎与printf()一模一样
注
输入参数接收的是地址,在某些情况下,请注意使用&运算符
scanf和gets的数据
putchar(),getchar()函数
char a = getchar()是没有参数的,从键盘得到你输入的一个字符给变量a
putchar(‘y')把字符y输出到屏幕中
总结
控制符中,%d、%f、%s、%c 最常用,功能分别是输出整数、实数、字符串和字符
printf()使用时需注意转义字符有特殊的含义
scanf()在某些情况下,使用时需注意使用&运算符
编译器不会检查输入和输出的参数数目与控制符数目是否一致
输入时候字符和整数的区别
scanf(“%d”,&x);这个时候输入1,特别注意表示的是整数1scanf(“%c”,&x);这个时候输入1,特别注意表示的是字符‘1'ASCII为整数48
使用scanf()函数输入字符串时,要注意,scanf()读到第一个空格、或者Tab或者回车符就会结束读入
终端输入:1234567scanf(“%2d%4d%d”,&x,&y,&z);x为12,y为3456,z为7终端输入:1 234567 由于1和2中间有空格,所以只有1位给xscanf(“%2d%4d%d”,&x,&y,&z);x为1,y为2345,z为67
在某些情况下可能会遇到scanf()和printf()的返回值,所以特别说明一下,返回值的意义,用scanf()读取几个数据,则scanf()的返回值为几,printf()同理,用printf()输出几个数据,则printf()的返回值为几
基本运算符
算术运算符(7个)
+
把两个操作数相加
-
从第一个操作数中减去第二个操作数
*
把两个操作数相乘
/
分子除以分母
两边都是整型的话,结果就是一个整型。3/2的结果就是1
如果有一边是小数,那么结果就是小数。3/2.0的结果就是0.5
%
取模运算符,整除后的余数
两边一定是整数
++
自增运算符,整数值增加 1
--
自减运算符,整数值减少 1
B = ++A、B = --A(++在前先加后用)B = A++、B = A--(++在后先用后加)
关系运算符(6个)
==
检查两个操作数的值是否相等,如果相等则条件为真
!=
检查两个操作数的值是否相等,如果不相等则条件为真
>
检查左操作数的值是否大于右操作数的值,如果是则条件为真
<
检查左操作数的值是否小于右操作数的值,如果是则条件为真
>=
检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真
<=
检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真
逻辑运算符(3个)
&&
称为逻辑与运算符。如果两个操作数都非零,则条件为真
||
称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真
!
称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假
赋值运算符(6个)
=
简单的赋值运算符,把右边操作数的值赋给左边操作数
C = A + B 将把 A + B 的值赋给 C
+=
加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数
C += A 相当于 C = C + A
-=
减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数
C -= A 相当于 C = C - A
*=
乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数
C *= A 相当于 C = C * A
/=
除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数
C /= A 相当于 C = C / A
%=
求模且赋值运算符,求两个操作数的模赋值给左边操作数
C %= A 相当于 C = C % A
其他运算符(4个)
sizeof()
返回变量或者类型的大小
sizeof(a) 将返回 4,其中 a 是整数。 sizeof(double) 将返回 8
&
返回变量的地址
&a; 将给出变量的地址
*
指向一个变量或取指针所指向内存地址的值
int *a = &b; 将指向一个变量。b = *a:将取出a指向地址的变量值赋值给b
三目运算符 ? X : Y ;
条件表达式
如果条件为真 ? 则值为 X : 否则值为 Y
运算符优先级与结合性
后缀运算符 () [] -> . ++ - - 从左到右
优先级最高
一元运算符 + - ! ~ ++ - - (type)* & sizeof 从右到左
乘除运算符 * / % 从左到右
加减运算符 + - 从左到右
关系运算符 < <= > >= 从左到右
相等运算符 == != 从左到右
条件运算符 ?: 从右到左
赋值运算符 = += -= *= /= %= >>= <<= &= ^= |= 从右到左
逗号运算符 , 从左到右
优先级最低
表达式
表达式与语句
表达式必须有一个执行结果,这个结果必须是一个值,例如3*4+5的结果 17,a=c=d=10的结果是 10,printf("hello")的结果是 5(printf()函数的返回值是成功打印的字符的个数)
以分号;结束的往往称为语句,而不是表达式,例如3*4+5;、a=c=d;等
语句不一定以分号结束,比如if语句,for语句
C程序书写格式自由,一行内可以写几个语句,一个语句可以写在几行上
分类
算术表达式
+,-,*,/,%
赋值表达式
表达式数值是最左边的数值,a=b=5;该表达式为5,常量不可以赋值,赋值的左边只能是一个变量
复合赋值表达式
注
int x=y=10:错啦,定义时,不可以连续赋值
int x,y;x=y=10;对滴,定义完成后,可以连续赋值
int x=7.7;对滴,x就是7
float y=7;对滴,x就是7.0
自加自减表达式
++在前先加后用,++在后先用后加
逗号表达式
优先级别最低。表达式的数值逗号最右边的那个表达式的数值。(2,3,4)的表达式的数值就是4。
注
z=(2,3,4)(整个是赋值表达式)这个时候z的值为4。(有点难度哦!)z= 2,3,4(整个是逗号表达式)这个时候z的值为2。
自动类型转换
一个表达式中出现不同类型间的混合运算,较低类型将自动向较高类型转换,这个自动转换的过程就叫自动类型转换
不同数据类型之间的差别在于数据的表示范围及精度上,一般情况下,数据的表示范围越大、精度越高,其类型也越“高级”
赋值运算中如果左值精度比右值精度低,将会出现截断,会导致精度丢失
当函数调用时,所传实参与形参类型不一致时,也会把实参自动转换为形参类型后再赋值(类型以形参为准)
强制类型转换
C 语言提供了可显式指定类型转换的语法支持,通常称之为强制类型转换
形式
(目标类型) 表达式
一定是(int)a不是int(a),注意类型上一定有括号的
注
注意(int)(a+b)和(int)a+b的区别。前是把 a+b转型,后是把a转型再加b
三种取整丢小数的情况
int a=1.6;
(int)a;
1/2;3/2;
位运算
处理方法
先把十进制变成二进制再变成十进制
类型
&与两个位都为1时,结果才为1
3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1
|或两个位都为0时,结果才为0
3|5即 0000 0011| 0000 0101 = 0000 0111,因此,3|5的值得7
^异或两个位相同为0,相异为1
~取反0变1,1变0
<<左移各二进位全部左移若干位,高位丢弃,低位补0
>>右移各二进位全部右移若干位,对无符号数,高位补0
例子
char a=6,b;b = a<<2;
先要把a的十进制6化成二进制,再做位运算
在没有舍去数据的时候,<<左移--位表示乘以 2;>>右移--位表示除以 2
控制结构
三种基本结构
顺序结构
选择机构
if - else语句
else与最近邻的if相匹配
switch 语句
每一个case语句后面的break不能省(除非特殊情况)
如果case都不满足,则执行default语句
循环结构
for 循环
注意边界问题(通常 左闭右开)
while 循环
while()括号中的条件是:满足条件则执行,不满足退出循环
do...while 循环
与while 语句相同)(但 先执行语句,再判断,循环必定会被执行一次)
转移控制语句
break 只能从内层循环中跳出到上一层循环
continue 跳出本次循环
return
库函数-exit()
算法流程图
基本符号
顺序结构基本流程图
选择结构基本流程图
循环结构基本流程图
画流程图的步骤
写算法描述
转换为图(需要按照实际情况组合顺序结构,循环结构,选择结构对应的基本流程图)
选择结构
C语言逻辑真假
非0为真(true),0为假(false)
在关系和逻辑表达式中,若表达式为真则值取1,否则值取0
关系运算符
C 语言提供的关系运算符有: >(大于)、>=(大于等于)、<(小于)、<=(小于等于)、==(等于)和 !=(不等于)6 种二元关系运算符
前 4 个的优先级高于最后两个
由关系运算符组成的式子为关系表达式,如 a > b 即为关系表达式,在 C 语言中,同逻辑表达式一样,关系表达式的值也为逻辑值,即布尔型(bool),取值为真或假
关系运算符一般不能连用,如果连用将表达不同的含义
逻辑运算符
与运算(&&)
参与运算的两个表达式都为真时,结果才为真,否则为假
或运算(||)
参与运算的两个表达式只要有一个为真,结果就为真;两个表达式都为假时结果才为假
非运算(!)
参与运算的表达式为真时,结果为假;参与运算的表达式为假时,结果为真
逻辑运算符和关系运算符与其他运算符的优先级
赋值运算符(=) < &&和|| < 关系运算符 < 算术运算符 < 非(!)
布尔表达式求值
确定运算符优先级
确定运算符结合方向
得出值(布尔表达式的值只可能是0或者1)
if语句
不加括号只对一条语句起作用,对多条语句起作用用括号
表达式的值不为0,就执行操作1(操作1可包含多条语句),否则什么都不做,往下继续执行
if (表达式) {操作1}
表达式的值不为0,就执行语句(只有一条语句),否则什么都不做,往下继续执行
if (表达式) 语句;
if else语句
表达式的值不为0,就执行操作1,否则执行操作2(操作1,2可包含多条语句)
if (表达式) {操作1} else {操作2}
表达式的值不为0,就执行语句1,否则执行语句2(语句1,2只能是单条语句
if (表达式) 语句1;else 语句2
并列的if else语句
如果表达式1的值不为0,就执行操作1否则判断表达式2的是否为0,如果不为0,执行操作2否则判断表达式3的值是否为0,如果不为0,执行操作3,...否则判断表达式n的值是否为0,如果不为0,执行操作n,否则执行操作n+1
if (表达式1) {操作1} else if (表达式2) {操作2} else if (表达式3) {操作3} ...else if (表达式n) {操作n} else {操作n+1}
注
操作1~n+1中只有一个可以执行
嵌套的if else语句
如果表达式1的值不为0,判断表达式2的值是否为0,如果表达式2的值为0,执行操作1,否则判断表达式3的值是否为0,如果不为0,执行操作2,否则执行操作3
if (表达式1) {if (表达式2) {操作1}} else {if (表达式3) {操作2} else {操作3}}
注
多种形式的if、if else、并列的if else、嵌套的if else等可以相互组合和嵌套,但是不建议嵌套太多层,那样会减低程序的可阅读性
switch语句
一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查
switch(expression){case constant-expression :statement(s);break; /* 可选的 */case constant-expression :statement(s);break; /* 可选的 */ /* 可以有任意数量的 case 语句 */default : /* 可选的 */statement(s);}
要点
switch 语句中的 expression 是一个常量表达式,必须是一个整型(char本质上属于整型)或枚举类型
在一个 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要比较的值和一个冒号
case 的 constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量或字面量
当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止
当遇到 break 语句时,switch 终止,控制流(可理解为程序的执行过程)将跳转到 switch 语句后的下一行
不是每一个 case 都需要包含 break。如果 case 语句不包含 break,控制流将会 继续执行 后续的 case,直到遇到 break 为止
一个 switch 语句可以有一个可选的 default,一般出现在 switch 的结尾。default 可用于在上面所有 case 都不为真时执行一个任务。default 中的 break 语句不是必需的
循环结构
for循环
for 循环允许编写一个执行指定次数的循环控制结构
for ( init; condition; increment ){statement(s);}
控制流程
init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可
接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句
在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可
条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止
while循环
只要给定的条件为真,C 语言中的 while 循环语句会重复执行一个目标语句
while(condition){statement(s);}
statement(s) 可以是一个单独的语句,也可以是几个语句组成的代码块
condition 可以是任意的表达式,当为任意非零值时都为 true。当条件为 true 时执行循环。 当条件为 false 时,退出循环,程序流将继续执行紧接着循环的下一条语句
do…while循环
不像 for 和 while 循环,它们是在循环头部测试循环条件。在 C 语言中,do…while 循环是在循环的尾部检查它的条件,do…while 循环与 while 循环类似,但是do…while 循环会确保至少执行一次循环
do{statement(s); }while( condition );
最后的分号不能丢
条件表达式出现在循环的尾部,所以循环中的 statement(s) 会在条件被测试之前至少执行一次
如果条件为真,控制流会跳转回上面的 do,然后重新执行循环中的 statement(s)。这个过程会不断重复,直到给定条件变为假为止
死循环
如果循环控制流中条件表达式的值永远为true,称为死循环,通常是应该避免的
常见死循环
for形式死循环
for(;;) { }
for(;1;) { }
while形式死循环
while(1) { }
do...while形式死循环
do{ }while(1);
三种循环语句比较
在知道循环次数的情况下更适合使用for循环
在不知道循环次数的情况下适合使用while或者do-while循环,如果有可能一次都不循环应使用while循环,如果至少循环一次应使用do-while循环
从本质上讲,while,do...while和for循环之间可以相互转换
多重循环(循环嵌套)
有时候一个循环有可能满足不了需求,或者说使用起来不太方便,如:遍历二维数组时,这个时候我们就需要用到多重循环,多重循环就是在循环结构(含有循环语句的结构就叫循环结构)的循环体中又出现循环结构
break语句
break 语句,可以跳出循环结构,还可以跳出 switch语句
不能用于循环语句和 switch 语句之外的任何其他语句中
在多层循环中,一个break语句只跳出当前循环
使用break语句,可以跳出死循环
在没有循环结构的情况下,break不能用在单独的if else语句中
continue语句
continue 的用法十分简单,其作用为结束本次循环,即跳过循环体中下面尚未执行的语句,然后进行下一次是否执行循环的判定
continue和break的区别
continue 语句和 break 语句的区别是,continue 语句只结束本次循环,而不是终止整个循环,break 语句则是结束整个循环过程,不再判断执行循环的条件是否成立
continue 只能在循环语句中使用,即只能在 for、while 和 do…while 中使用,除此之外 continue 不能在任何语句中使用
数组的使用
数组
数组是在内存中连续存储的具有相同类型的一组数据的集合
一维数组
语法
类型说明符 数组名[正整数常量表达式];
int a[5];
解释说明
表示定义了一个整型数组,数组名为 a,定义的数组称为数组 a。数组名 a 除了表示该数组之外,还表示该数组的首地址,也就是元素a[0]的地址(等价于&a)
此时数组 a 中有 5 个元素,每个元素都是 int 型变量,而且它们在内存中的地址是连续分配的。也就是说,int 型变量占 4 字节的内存空间,那么 5 个int型变量就占 20 字节的内存空间,而且它们的地址是连续分配(物理相邻)的
定义数组时,需要指定数组中元素的个数。方括号中的正整数常量表达式就是用来指定元素的个数。数组中元素的个数又称数组的长度
C语音通过给每个数组元素进行编号的方式访问数组中的元素。数组元素的编号又叫下标,访问数组中第5个元素的方式应该是a[4]因为数组中的下标是从 0 开始的
元素就是变量,数组中习惯上称为元素
初始化
数组跟变量一样必须先定义,然后使用
定义时数组的个数一定是常量(可以是算术表达式),不是变量
定义数组时给所有元素赋初值,这叫“完全初始化”
int a[5] = {1, 2, 3, 4, 5};
通过将数组元素的初值依次放在一对花括号中,初始化之后,a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5,即从左到右依次赋给每个元素。需要注意的是,初始化时各元素间是用逗号隔开的,不是用分号
可以只给一部分元素赋值,这叫“不完全初始化”
int a[5] = {1, 2};
定义的数组 a 有 5 个元素,但花括号内只提供两个初值,这表示只给前面两个元素 a[0]、a[1] 初始化,而后面三个元素都没有被初始化。值得注意的是,不完全初始化时,没有被初始化的元素自动为 0
需要注意的是,“不完全初始化”和“完全不初始化(未初始化,即只声明了但未赋值)”不一样。如果“完全不初始化”,即只定义int a[5];而不初始化,那么各个元素的值就不是0了,所有元素的值都是不确定值
for循环语句遍历数组
常见错误
int main() {int a[5];a[5] = {1, 2, 3, 4, 5};// 错误的原因是,只有在定义时才可以用大括号初始化return 0;}
int main() {int a[5] = {1, 2, 3, 4, 5, 6};// 错误的原因初始化数组超过了数组本身的大小return 0;}
int main() {int a[5] = {};// 初始化大括号里面不能什么都不填return 0;}
二维数组
二维数组在逻辑上是数组的数组,即二维数组的每个元素是一个一维数组(一行),在物理上是一维数组,即所有的元素都是连续存储的。从直观上来看,二维数组就是线性代数中的矩阵
语法
类型说明符 数组名[正整数常量表达式1][正整数常量表达式2];
int a[3][4];
解释说明
在这个定义的二维数组中,共包含3 * 4个元素,即12个元素
同一维数组类似,对数组元素的访问也是用下标,指定行下标(常量表达式)和列下标(常量表达式),行下标和列下标都是从0开始的
a[0][0]; //为0行0列元素,注意与习惯上区分开,习惯上的第1对应下标0a[2][1]; //为2行1列元素a[1][1+2]; //为1行3列元素
初始化
先定义,后赋值,在显式赋值之前,二维数组的各数据元素是随机值(不确定)
// 先定义int a[2][3];// 后赋初值a[0][0]=1;a[0][1]=2;a[0][2]=3;a[1][0]=4;a[1][1]=5;a[1][2]=6;
在定义二维数组的同时,采用初始化列表的形式对其元素赋初值
// 分行给出初始化数据,且每行的初始化数据个数等于列数,这一行代码相当于上面的七行代码int a[2][3]={{1,2,3},{4,5,6}};
// 由于初始化列表中明确给出了两行数据,故定义该数组时,其第一维的大小可省略,编译器能间接算出该数组的行数为 2,故依然可以确定其空间大小,因此,在对二维数组进行初始化时,其第一维的大小可以省略,即写成如下形式:// int a[][3]={{l,2,3},{4,5,6}};
// 等价于不分行写法,前提是 数组元素的个数(行数 × 列数)= 大括号后面的初始值个数// int a[2][3]={l,2,3,4,5,6};
// 同样可以省略第一维的大小// int a[][3]={l,2,3,4,5,6};
// 如果数组元素的个数(行数 × 列数)不等于 大括号后面的初始值个数// int a[][3]={l,2,3,4,5,6,7};// 这就相当于// int a[3][3] = {l,2,3,4,5,6,7,0,0}; // 第一维大小可省略// 也相当于// int a[3][3] = {l,2,3,4,5,6,7,0}; // 第一维大小可省略// 还相当于// int a[3][3] = {{l,2,3},{4,5,6},{7,0,0}}; // 第一维大小可省略// 同时相当于// int a[3][3] = {{l,2,3},{4,5,6},{7}}; // 第一维大小可省略// 最后,还可以相当于先定义,后赋值的形式,这里省略相关代码
注
某行一行初始值如未写全,那么该行元素,后面的元素会自动被赋予初值0
常见错误
int a[2][] = {{l,2,3},{4,5,6}}; //错误。不能省略第二维大小
int a[][] = {{l,2,3}, {4,5,6}}; //错误。不能省略第二维大小
int a[][3]; //错误。没有提供初始化列表时,两维的大小都必须显式给出
int a[2][3] = {{l,2,3},{4,5,6},{7,8,9}}; //错误。初始行数多于数组行数
遍历
通常使用双层for循环,遍历二维数组
字符数组与字符串
字符数组
用来存放字符的数组称为字符数组。字符数组的各个元素依次存放字符串的各字符,字符数组的数组名代表该数组的首地址,这为处理字符串中个别字符和引用整个字符串提供了极大的方便。字符数组的定义形式与前面介绍的整型数组相同
语法
char c[6];
赋值
在定义时进行初始化赋值
// 长度可省略char c[6]={'c', ' h ', 'i', 'n', 'a' , '\0' };
先定义后赋值
char c[6];c[0]= 'c',c[1]= 'h',c[2]= 'i',c[3]= 'n',c[4]= 'a',c[5]= '\0';
字符串常量的赋值
char a[]={"china"};// 长度是6,因为最后还有一个结束符'\0'// 等价形式// char a[] = "china";/ 同理,长度是6
scanf %s输入字符数组时,不需要取地址,因为数组名本身就是地址常量
char a[10];scanf("%s",a);// scanf %s不能输入带有空格的字符串,会被截断,如果字符串中可能带有空格(回车,tab)字符,用gets函数输入
其中,‘\0’为字符串结束符。如果不对c[5]赋任何值,‘\0’会由编译器自动添加
如果如果大括号里面的元素个数小于数组的长度,则只将大括号中的字符赋给数组中前面的元素,剩下的内存空间编译器会自动用 ‘\0’ 填充
打印
可以用for循环(其他循环也可以)加printf %c形式输出字符数组的内容,也可以直接用printf %s格式输出字符数组内容
char a[] = "china";// for循环加printf %c形式输出int i;for (i = 0;i < sizeof(a);i++) {printf("%c",a[i]);} // 直接用printf %s格式输出字符数组printf("%s",a);
字符串
要点
C语言中没有字符串这种数据类型,但是可以通过char的数组来替代
字符串一定是一个char的数组,但char的数组未必是字符串
数字0(和字符‘\0’等价)结尾的char数组就是一个字符串,但如果char数组没有以数字0结尾,那么就不是一个字符串,只是普通字符数组,所以字符串是一种特殊的char的数组
内存中字符串以字符数组的形式存在,而数组以指针常量(地址常量)的形式存在,即数组首地址是个很关键的因素
正是由于数组都是以指针常量的形式存在,所以C语言没有办法对数组的大小进行检查,所以通常,数组越界错误编译器是不会指出来的,但是也有部分高级的编译器会指出warning
字符串操作函数
常用函数
strlen(s)
获得字符串的长度(单位字节)
strlen("abc"),结果:3
strcmp(s1,s2)
比较字符串
strcmp("ab","ac"),结果-1
strcpy(sl,s2)
字符串拷贝
strcpy(s1,"abo“)
strcat(s1,s2)
把字符串s2拼接到s1后
strcat(sI,”abc“)
atoi(s1)
字符串转换为整数
atoi("100"),结果:100
注意事项
使用前需要先引入头文件#include<string.h>;
strlen()获取字符串的长度,在字符串长度中是不包括‘\0’而且汉字和字母的长度是不一样的
strcmp()在比较的时候会把字符串先转换成ASCII码再进行比较,返回的结果为0,表示s1和s2的ASCII码相等,返回结果为1,表示s1比s2的ASCII码大,返回结果为-1,表示s1比s2的ASCII码小
strcpy()拷贝之后会覆盖s1原来的字符串且s1不能是字符串常量
s,s1,s2均为字符指针类型(即可以传递的实参为字符指针,字符数组,字符串常量)
函数的使用
函数
函数是C程序的基本结构单位
文件是基本编译单元
一个函数就是实现一个功能模块
在函数不可以再定义函数
不能嵌套定义,但可以嵌套调用
每个 C 程序都至少有一个函数,即主函数 main() 且只能有一个main(),所有简单的程序都可以定义其他额外的函数。主函数main()的功能是程序入口
程序执行从main函数开始,到main函数结束
函数声明告诉编译器函数的名称、返回类型和参数类型。函数定义提供函数的实际主体
形参的名称不一定要有
语法
return_type function_name( parameter list ){body of the function}
组成部分
返回类型
一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是 void(即返回值为空,不返回任何值)
函数名称
这是函数的实际名称。函数名和参数列表一起构成了函数签名
参数
参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数
参数传递
传数值
形参的变化不会改变实参的变化
传地址
形参的变化就会有可能改变实参的变化
函数主体
函数主体包含一组定义函数执行任务的语句
函数名必须满足标识符的规范
递归函数
一个函数总会在某种情况下调用它本身,这样的函数叫递归函数
原则
把大问题转换为子问题(找递推关系式)
递归出口
库函数
已经写好的函数,放在仓库中,直接调用就行
常见库函数
abs()
int abs(int x) 返回 x 的绝对值
整数
fabs()
double fabs(double x) 返回 x 的绝对值
浮点数
sqrt()
double sqrt(double x)返回 x 的平方根。
pow()
sin()
double sin(double x)返回弧度角 x 的正弦
变量存储特性
局部变量
定义在函数体内部的变量(函数的形参也是局部变量),就是局部变量,每次调用函数局部变量都会被初始化,每次离开函数,局部变量就被销毁,回收空间
局部变量的作用范围是从定义的位置开始到函数体结束
全局变量
定义在函数体外部的变量,就是全局变量
全局变量的作用范围是从定义的位置开始到本文件结束
static
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内
指针的使用
概念
每一个变量都有一个内存位置,每一个内存位置都定义了 & 运算符访问的地址,它表示了在内存中的一个地址。而指针的本质就是地址
printf %p可以直接输出地址(也就是指针)
指针变量是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。一般变量存取数值。指针变量通常简称为指针
语法
type *var-name;
int *ip; /* 一个整型的指针 */double *dp; /* 一个 double 型的指针 */float *fp; /* 一个浮点型的指针 */char *ch; /* 一个字符型的指针 */
解释说明
type 是指针的基类型,它必须是一个有效的 C 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针
所有实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型(如:结构体类型),对应指针的值的类型都是一样的,都是一个代表内存地址的长的十六进制数(即:所有指针变量所占用的空间都是一个字节)
不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同
如何使用指针
定义一个指针变量
初始化
把变量地址赋值给指针
访问指针变量中可用地址的值
NULL 指针
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针
NULL 指针是一个定义在标准库中的值为零的常量。有点类似字符串的结束符
二级指针
*p:一级指针:存放变量的地址
**q:二级指针:存放一级指针的地址
三名主义
数组名
表示第一个元素的地址
数组名不可以自加,因为它是地址常量名
函数名
表示该函数的入口地址
字符串常量名
表示第一个字符的地址
指针变量相关运算和相关概念
指针的算术运算
可以对指针进行四种算术运算:++(指向下一个位置)、--(指向上一个位置)、+(往后移)、-(往前移)
指针数组
可以定义用来存储指针的数组
指向指针的指针(双重指针)
C 允许指向指针的指针
传递指针给函数
通过引用或地址传递参数,使传递的参数在调用函数中可以被改变。
从函数返回指针
C 允许函数返回指针到局部变量、静态变量和动态内存分配
指针与数组
数组名就是地址常量(指针常量)
字符串与字符指针
字符串通常是字符数组
char name[] = "aaa";
字符指针通常是指向字符型变量的指针,但C语言还支持直接使用一个字符指针指向字符串
char *str = "hello C language";
字符数组和指向字符串的字符指针的差别
字符数组存放在全局数据区或栈区,可读可写。指向字符串的字符指针所指向的字符串存放在常量区,只读不能写
char *str = "hello";str[1] = 'a';// 错误,尝试修改常量char *str2 = "world";str = str2;// 正确,str是指针变量,可以修改指针变量的指向char a[] = "hello world";a[0] = 'b';// 正确,字符数组的元素可读可写a = str2;// 错误,a为指针常量,不能修改指向的内存地址
结构体
概念
C 数组允许定义可存储相同类型数据项的变量,结构体是 C 编程中另一种用户自定义的可用的数据类型,它允许存储不同类型的数据项
结构体用于表示一条记录,比如学生成绩,一条学生成绩信息需要包括:学生姓名(字符数组)、学号(整型),数学成绩(单精度或双精度浮点型),英语成绩(单精度或双精度浮点型),C语言成绩(单精度或双精度浮点型),总分(单精度或双精度浮点型),平均分(单精度或双精度浮点型)
语法
定义结构体,必须使用 struct 关键字
struct tag {member-listmember-listmember-list...} variable-list ;
解释说明
tag 是结构体标识符(别名)
member-list 是标准的变量定义,比如 int i; 或者 float f,或者其他有效的变量定义
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量
struct Score {int stu_num;char stu_name[10];double math;double english;double c;double avg;double sum;} someonedScore;
在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c//同时又声明了结构体变量s1//这个结构体并没有标明其标签struct {int a;char b;double c;} s1; //此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c//结构体的标签被命名为SIMPLE,没有声明变量struct SIMPLE {int a;char b;double c;};//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3(结构体指针)struct SIMPLE t1, t2[20], *t3; //也可以用typedef创建新类型,这个考纲没有要求,大概看看了解以下typedef struct {int a;char b;double c;} Simple2;//现在可以用Simple2作为类型声明新的结构体变量Simple2 u1, u2[20], *u3;
如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明
struct B; //对结构体B进行不完整声明 //结构体A中包含指向结构体B的指针struct A {struct B *partner;//other members;}; //结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明struct B {struct A *partner;//other members;};
初始化
struct Books {char title[50];char author[50];char subject[100];int book_id;} book = {"C 语言", "RUNOOB", "编程语言", 123456}; int main() {printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);}
访问结构体成员
struct Books {char title[50];char author[50];char subject[100];int book_id;}; int main() {struct Books Book1; /* 声明 Book1,类型为 Books */ /* Book1 详述 */strcpy(Book1.title, "C Programming");strcpy(Book1.author, "Nuha Ali");strcpy(Book1.subject, "C Programming Tutorial");Book1.book_id = 6495407; /* 输出 Book1 信息 */printf("Book 1 title : %s\n", Book1.title);printf("Book 1 author : %s\n", Book1.author);printf("Book 1 subject : %s\n", Book1.subject);printf("Book 1 book_id : %d\n", Book1.book_id); return 0;}
指向结构体的指针
struct Books *struct_pointer;// 声明指针变量struct_pointer = &Book1;// 初始化指针struct_pointer->title;// 使用指向该结构的指针访问结构的成员
结构体数组
本质上就是个数组,只不过数组中的元素变成了结构体变量,用法同数组一样,使用下标访问数组元素
链表