程序设计C语言
1. C语言程序的结构
1.1程序的构成
1.C语言
C语言是面向过程(结构化程序设计)语言,是一门高级语言。
2.源程序文件
用C语言编写的程序称为C语言源程序,源程序文件的后缀名位".c"
3.执行步骤
用C语言编写的源程序不能直接被计算机执行,所有C程序都需要编译与连接无误后才能运行
- 需要先编译生产目标文件(.obj);
 - 再把目标文件与各种库函数连接起来
 - 生成".exe"可执行文件
 - C程序在运行过程中所有计算都以二进制方式进行
 
4.函数
C语言源程序的主要组成是函数。函数包括:主函数(main函数)、其他函数(自定义函数、库函数)。
- C源程序由若干个函数构成,即C程序的基本组成单位是函数
 - 一个C程序的执行是从主函数开始执行的,到主函数结束为止,主函数可以在程序任意的位置
 - 每条语句、数据定义、函数声明等最后必须有一个分号,分号是C语句的必要组成部分
 - 同一语句的不同成分之间宜用空格隔开
 - C程序书写的格式是自由的
 - C语言本身没有输入输出语句,是能够调用标准库函数的输入输出函数来实现的
 - 注释可以使用 //行注释,也可以使用/* */ 块注释
 - 注意:C语言区分大小写(大小写敏感),变量先定义,后使用;函数是先声明或定义,后使用。
 
5.主函数
- 
主函数一般形式:main为主函数名
c#include"stdio.h" // 引用头文件 main(){ // ()形参列表 {}main函数体 } - 
主函数是C程序的入口,先从主函数开始执行
 - 
每个C程序有且只有一个主函数,可以没有自定义函数(0个或多个)
 - 
主函数的位置可以不固定,可以出现自定义函数之前,也可以出现在其后
 
6.自定义函数
- 用户根据实际需要自己定义的函数,用于实现某些功能,为主函数而服务
 - 自定义函数可以出现在主函数之前,也可以出现在主函数之后(使用时候需要先声明),还可以出现在其他C程序文件中(使用时候,需要先声明)
 - 主函数中可以调用自定义函数,也可以自定义函数之间相互调用
 
7.库函数
- C语言提供一些封装号的函数使用,比如字符串处理函数、标准输入输出函数、数学函数等
 - 使用库函数时需要先将库函数所在头文件引入(#include)即预编译命令
 - 使用尖括号<>和双引号""的区别在于头文件的索引路径不同:
- 使用尖括号<>:编译器回到系统路径下查找头文件;
 - 使用双引号"":编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。
 
 - 主函数或自定义函数内调用
 
8.模块化
C语言主要时借助定义函数功能来实现程序模块化
9.结构化程序设计方法的主要原则
- 逐步求精:对复杂的问题,应设计一些子目标作过度,逐步细化
 - 自顶向下:程序设计时应先考虑总体,后考虑细节,先考虑全局目标,后考虑局部目标。不要一开始久过多追求众多细节,先从最上层总目标开始设计,逐步使问题具体化
 - 模块化:一个复杂问题,肯定是由诺干较为简单的问题构成,模块化是把程序要解决的总目标分解为分目标,在进一步分解为具体小目标,把每个小目标称为一个模块,而可复用是面向对象程序设计的特点,C语言允许对函数单独进行编译(不能单独执行,需要从主函数开始执行),从而可以实现模块化,而且提供了丰富的数据类型
 - 限制使用goto语句
 
10.C语言三种结构
- 顺序结构
 - 选择结构
 - 循环结构
 
11.结构作用
由三种结构(顺序结构、选择结构和循环结构)组成的算法可以解决任何复杂的问题
1.2 头文件、数据说明、程序注释
- 
头文件
- 使用标准库函数(stdio.h)、数学函数(math.h)、字符串函数(string.h)等,需要引入头文件
 - 也可以引入用自己定义的头文件
 - 格式: #include <头文件名>或"头文件名"
 - <>优先取标准库(系统目录)里找
 - ""优先在新项目所属于目录(当前目录下)找,如果没有再去系统目录下找
 - 头文件方便函数共享
 - 一般引入头文件放在文件首部
 
 - 
数据说明
- 
程序数据来源:程序赋值,传参,外部输入,读文件,数据库,程序处理中间结果,以及最终结果,输出文件等
 - 
数据类型:字符型、整数型、浮点型、指针类型、结构体、共同体等
 - 
计算机在电脑中保存数据式采用二进制形式,由0或1构成的二进制称为位(bit),八个位构成一个字节(Byte),1个Byte = 8个bit
 - 
二进制、八进制、十六进制转化为十进制采用乘法,十进制转化为二进制、八进制、十六进制采用除法。
 - 
数据的存放位置就是它的地址
 - 
数据长度
数据类型 32位平台 64位平台 char 1 1 short 2 2 int 4 4 long 4 8 long long 8 8 float 4 4 double 8 8  
 - 
 - 
程序注释
- 注释的作用
- 注释是对程序的说明,可出现在程序中任意合适的地方
 - 注释从"/"开始到最近的一个"/"结束
 - 注释的内容是不会被计算机执行的
 - 注释不可以嵌套
 
 - 单行注释
- 格式: // 注释内容
 - 一般用于一行内容的注释,对语句进行关键说明
 
 - 多行或块注释
- "/*"开始," */"结束
 - 一般用于多行可以对函数进行说明。
 
 
 - 注释的作用
 - 
VC++2010程序暂停
- 快捷键:Ctrl + F5
 - system("pause")
 
 
1.3源程序的书写格式
- 强制性规则
- 一个C程序必须有且仅有1个main函数
 - 函数名后 必须紧跟圆括号对,函数体置于花括号对中
 - 每个程序体,即语句块(包含函数的函数体、含有多条语句的选择结构和循环结构中的内嵌语句语序)必须用1对花括号括起来
 - 文件包含预处理命令 #include< .h> 应置于源程序的开始位置
 - 语句末尾必须有分号,而预处理命令和函数首部的末尾及右花括号之后不要分号
 - 同一字母大小写意义不一样,关键字和标准库函数必须用小写
 - 变量必须先定义,后使用
 - 关键字与其他字符之间必须至少1个空格
 - 注释必须包含在"/*"和" */"符号对之间或"//"之后
 
 - 推荐行原则和书写风格
- 及时书写和修改注释,注释宜简明扼要,放在程序的恰当位置
 - 同一层次的语句同列开始书写,下一层次的语句(包括选择结构、循环结构中的内嵌语句)在上一层次语句的列位置基础上退后几列开始书写,并合理使用花括号;
 - 在不导致逻辑错误的前提下,意义相近的几条语句可写在同一行,意义相差甚远的语句不宜写在同一行,C程序书写格式自由,一个语句可以分写在多行上,
 - 同一语句的不同成分之间宜用空格隔开
 - 复合语句的对齐和缩进风格
- K&R风格
 - Allman风格
 - Whitesmiths风格
 - GUN风格
 
 - 变量命名的风格和习惯:
- 驼峰命名法
 - 下划线命名法
 
 - 注释的风格
- / * */
 - //
 
 - switch符合语句及if嵌套语句对齐与缩进风格
 
 
2.数据类型及其运算
2.1C语言的基本数据类型及定义方法
1.标识符
- 
是标识名字的有效字符序列,可以理解为C程序中的的单词
 - 
标识符的命名规则
- 标识符只能由字母、数字和下划线组成,字母区分大小写
 - 标识符的第一个字符必须是字母或下划线,不能为数字
 
 - 
C语言标识符分为以下三类
- 
关键字,它们在程序中由固定的含义,不能另作他用。如int、for、switch等,共32个关键字
关键字 说明 关键字 说明 auto 自动变量 static 静态变量 short 短整型 volatile 变量在程序执行中可被隐含的改变 int 整型变量 void 声明函数无返回值或无参数,声明无类型指针 long 长整型 if 条件语句 float 浮点型 else 条件语句否定分支 double 双精度 switch 用于开关语句 char 字符型 case 开关语句分支 struct 结构体 for 循环语句 union 共用数据类型 do 循环语句的循环体 enum 枚举类型 while 循环语句的循环条件 typedef 以数据类型取别名 goto 无条件跳转语句 const 只读变量 continue 结束当前循环,开始下一轮循环 unsigned 无符号类型 break 跳出当前循环 signed 有符号类型 default 开关语句中的"其他"分支 extern 变量是在其他文件声明 sizeof 计算数据类型长度 register 寄存器 return 子程序返回语句  - 
预定义标识符:预先定义并具有特定含义的标识符,如define、include、标准库函数名等
 - 
用户标识符:用户根据需要定义的标识符,符合命名规则且不与关键字相同
 
 - 
 - 
用户标识符的命名与预定义标识符或关键字相同时
- 若用户标识符的命名与预定义标识符相同,则命名有效
 - 若用户标识符的命名与关键字向相同,将产生编译错误
 - 若用户标识符的命名与预定义标识符相同,则预定义标识符时区原有含义
 - 若用户标识符的命名与预定义标识符相同,则可能引发运行错误
 
 
2.常量与变量
- 
常量是指在程序运行过程中,其值不能改变的量
 - 
常量分为整型变量、实型常量、字符常量、字符串常量、符号常量5种
- 
整型常量
 - 
实型常量(实数或浮点数)
 - 
字符常量:两个单引号包起来,例如'a','\\'等
- 
字符常量可用于对应的ASCII码表,需记住: '0' 48,'A' 65,'a' 97
 - 
转义字符:'\t','\\','\n'等
转义字符 意义 ASCII 转义字符 意义 ASCII \b 退格 8 \n 换行 10 \t 横向跳到下一制表位置 9 \r 回车 13 \\ 反斜线'\' 92 \' 单引号 39 \ " 双引号 34 \f 走纸换页 12 \ ddd 三位八进制数字符 "\101"表示65的字符"A" \xhh 两位十六进制数字符 "\x41"表示65的"A"  
 - 
 - 
字符串常量
- 用双引号把若干字符括起来,字符串常量时双引号中的全部字符(但不包括双引号本身)
 - char *p = "hello"; 可以使用指针接收
 - 可以直接使用常量,比如printf("This is a string!")
 
 - 
符号常量:在c语言程序中,用一个符号名来表示一个常量,称为符号常量
- 
宏定义类型:#define 进行定义,例如 # define PI 3.14
这个符号名必须在程序中进行特别的"指定",并符合标识符的命名规则。
一般在程序中都是利用宏定义来定义符号常量的,在代码中可以利用undef来结束符号常量的定义,然后进行重新定义,符号常量的大小并没有特别的规定,一般时候为了和变量区分利用大写
 - 
枚举类型定义: enum 符号 { ...}
cenum COLOR { RED = 0, BLUE = 1 } - 
const类型定义:const 类型 符号
 
 - 
 
 - 
 
3.字符型
- 使用关键字: [ ]里内容可表示省略
signed\] char(有符号类型) unsigned char(无符号类型)
 - 变量名或常量名规则:标识符定义规则
 - 取值范围 [signed]char -128~127 unsigned char: 0~255
 - 常量定义(const)
 - 变量定义
 
4.整型
- 
使用关键字 int short long
 - 
占空间与取值范围
类型 32位 64位 取值范围 short 2 2 -32768~32767 unsigned short 2 2 0~65535 int 4 4 -21747483648~21747483647 unsigned int 4 4 0~4294967295 long 4 8 unsigned long 4 8  - 
常量名或常量名规则:标识符定义规则
 - 
常量定义(const)
 - 
变量定义
 
5.实型
- 使用关键字:float(单精度)、double(双精度)等
 - 占空间与取值范围
- 单精度 float 4字节 -3.4e38~3.4e38 6位小数
 - 双精度 double 8字节 -1.7e308~1.7e308 15位小数
 
 - 变量名或常量名规则:标识符定义规则
 - 常量定义
 - 变量定义
 
6.空类型
- 无值类型也叫空类型
 - 关键字:void
 - void指的是空,没有值
 - 函数不需要返回值的时候,可以定义为空类型
 - void的语义有多种
- 作为参数表示无参数
 - 作为返回值代表无返回值
 - 修饰指针变量代表位置类型的指针
 
 
2.2 运算符的种类、优先级和结核性
1.算术运算符
- 四则运算: + - * /
 - 取模运算: %
 - 求余运算 :%
 - 注意:取模运算结果的正负是由左操作数的正负决定的。如果%左边操作数是正数,那么运算结果是非负数,如果%左操作数是负数,那么结果是负数或者0.
 - 除法运算: / 符两边于是暖对象都为整数时,运算结果也为整数即舍掉小数部分
 - 优先级: * / % 高于 + -
 
2.关系运算符
- (>) (>=)(<)(<=)(==)(!=)
 - 优先级: (>、>=、<、<=)优先级高于(==、!=)
 - 关系表达式真为1,假为0。
 
3.逻辑运算符
- 逻辑与(&&)、逻辑或(||)、逻辑非(!)
 - 逻辑与(&&): 两边表达式同时为真时,为真,否则为假
 - 逻辑或(||):|| 两边表达式同时为假时,为假,否则为真
 - 逻辑非(!):!真 = 假,!假 = 真
 - 注意短路现象
- a++ || b++ 如果a++的值非零,则b++不执行
 - a++ && b++ 如果a++的值为零,则b++不执行
 
 - 逻辑表达式真时为非0(若是输出则1表示),假时 0
 - 优先级: ! 高于 && 高于 ||
 - 逻辑运算符两侧运算对象的数据类型可以是任何合法的类型数据
 
4.赋值运算符
- = ,+= ,-= ,*= ,/= ,%= ,<<= ,>>= ,|= ,&=,^=
 - 优先级相同
 - 赋值运算符"=";不同于"=="
 - 赋值表达式格式为:变量名 = 表达式,赋值运算符左边必须为变量,赋值运算是把赋值运算符右边表达式的值给左边变量
 - 复合运算符是将算数运算符或位运算符与赋值运算符组合在一起使用的运算符,掌握复合赋值表达式转为赋值表达式
 
5.三目运算符(条件运算符)
- 运算符: ? :
 - 格式: 表达式1 ? 表达式2 : 表达式3
 - 若表达式1值为真时,则整个表达式值为表达式2的值,否则是表达式3的值
 
6.自增自减运算符
- ++,--
 - 自加运算符++和自减运算符--是单目运算符,运算对象必须是变量
 - 自增自减运算分前缀运算和后缀运算,它们所对应的表达式的值是有区别的
 - 优先级相同
 - 常量不可以使用++或--运算符,它们的运算对象可以是char类型变量,int类型变量和float类型变量
 - ++,--中前缀和后缀的区别
- 在for的表达式3位置,,没有区别前后一样
 - 如果在函数体内,单个独立语句,前后也没区别
 - 如果在函数传递时,比如add(i++)和add(++i)不一样,前者先传递再自增,后者先自增再传递
 - 如果在逗号表达式中,比如(2,3,a++)那这个表达式的值就是a自增之前的,a还还是要自增
 - 如果在if或者循环条件判断中,++变量和变量++就有区别,前者先自增再判断,后者先判断后自增
 
 
7.位运算符
- &,|,^,~,<<,>>
 - 运算时,先需要将进行进制转换(转成二进制)
 - &运算规则:有0则为0,全1为1
 - |运算规则:有1为1,全0为0
 - 常用算法:(通常放在循环里使用)
- i = i & (i-1),统计i二进制中有多少个1
 - i = i | (i+1),统计i二进制中有多少个0
 
 - ^运算规则:相同为0,相异为1
 - ~运算规则:1取反变0,0取反变1,注意取反之后是补码
 - <<运算规则:扩大2的多少(n)倍,右边补0,每左移一位乘2操作
 - (>>)运算规则:缩小2的多少(n)倍,对于无符号整数和正整数,高位补0对于负整数高位补1.每右移一位即除以2操作
 - 优先级:(~)>(<<,>>) >(&)>(^)>(|)
 
8.逗号运算符
- ,
 - 可以把多个表达式用逗号联接起来,构成一个更大的表达式
 - 逗号运算符运算优先级最低,可将多个表达式构成一个新的表达式
 
9.运算符优先级
- 运算符按参加运算的对象数目可分为单目运算符、双目运算符和三目运算符
 - 初等运算符的优先级别最高,然后依次是单目运算符,算数运算符,关系运算符,逻辑运算符,条件运算符、赋值运算符、逗号运算符
 - 位运算符优先级介于算数运算符与逻辑运算符之间
 
10.结合性
- 结合顺序大多自左向右
 - 自右向左的有三个:单目运算符、条件运算符和赋值运算符
 - 左到右:(),算数运算符、关系运算符、&&,||
 - 右到左:!,++,--,*,&,赋值运算符
 
2.3不同类型数据间的转换与运算
1.类型转换
隐式转换与强制转换
2.隐式转换
编译自动转换,低精度向高精度转换
- 
数据赋值时:
cfloat f = 100; int n = f // f会被转换成(截取小数部分后)int型赋值给n - 
混合运算
cint a,b; float f; f = a + b; // 结果隐式转换成 float 型 double m = a + f; // 结果隐式转换成 double 型 - 
强制转换
- 将一个运算对象转换成指定类型
 - (类型名)(表达式)
 - 浮点型转换成整型时,小数部分截去了
 - 除法中,两个都是整数,结果只能为整数,否则会有小数,但是接收结果类型为int时,只会是整数,最好使用int强转
 
 
2.4 C语言表达式和求值规则
1.表达式
运算对象加运算符构成表达式
2.表达式语句
表达式加分号构成表达式语句
3.运算对象
运算对象可以是表达式、常量、变量
4.C语言表达式类型
- 算术表达式
 - 关系表达式
 - 逻辑表达式
 - 条件表达式
 - 赋值表达式
 - 逗号表达式
 - 其他表达式
 
5.算数表达式
- 运算对象加算术运算符
 - 算术表达式加分号构成算术表达式语句
 - 求余运算要求运算对象只能为整型
 - 除法运算符俩边运算对象都为整型,运算结果也为整型即舍掉小数部分
 - 注意优先级,类型转换(隐式、显式)
 
6.关系表达式
- 运算对象加关系运算符
 - 关系表达式加分号构成关系表达式语句
 - C语言用非0表示逻辑真(值为1),用0表示逻辑假(值为0)
 - 关系表达式真时为1,假时为0.
 - 一般关系表达式会出现if的条件、循环的条件等,经常与逻辑运算符构成符合表达
 
7.逻辑表达式
- 运算对象加逻辑运算符
 - 逻辑表达式加分号构成逻辑表达式语句
 - 注意个逻辑运算符的规则
 - 注意短路现象
 - 一般逻辑表达式和关系表达式等联合(复合表达式)用于if、循环条件等
 
8.条件表达式
- 运算符: ? :
 - 格式: 表达式1 ? 表达式2 : 表达式3
 - 若表达式1值为真时,则整个表达式值为表达式2的值,否则是表达式3的值
 - 条件表达式加分号构成条件表达式语句
 - 条件表达式可以嵌套使用,不建议嵌套层数太多,不方便理解和阅读
 
9.赋值表达式
- 运算对象加赋值运算符(+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=)
 - 赋值表达式加分号构成赋值表达式
 - 赋值表达式格式为: 变量名 = 表达式,赋值运算符左边必须是变量,赋值运算是把赋值运算符右边表达式的值赋给左边的变量
 - 复合赋值运算符是将算术运算符或位运算符与赋值运算符组合在一起组成的运算符,掌握复合赋值表达式转为赋值表达式的方法
 
10.逗号表达式
- 运算对象加逗号运算符
 - 可将多个表达式构成一个新的表达式
 - 从左向右依次计算各表达式的值,最后一个表达式的值是为整个逗号表达式的值
 
11.按位运算表达式
- 运算对象加按位运算符
 - 按位运算表达加分号构成按位运算表达式语句
 - 注意各运算规则
 
12.自增自减运算表达式
- 变量和自增自减运算符组合
 - 自增自减运算表达式加分号构成自增自减运算表达式语句
 - 注意变量在前在后的运算规则
 - ++等价于 变量 = 变量 + 1
 
13.复合表达式
- 若干个运算表达式组合而成
 - 复合表达加分号构成复合表达式语句
 - 计算复合表达式结果时,结合运算符的优先级来,以及运算符的运算规则,注意逻辑与逻辑或的短路问题
 
3.基本语句
3.1表达式语句,空语句,复合语句
1.简单语句
- 一条语句构成,用分号当作结尾
 - 表达式语句:一般是表达式末尾加分号(;)
 - 空语句: ;
 - 函数调用语句:函数名(参数列表)
 - 流程控制语句:goto、break、continue、return、if else、switch、for()、do...while()、while()
 
2.复合语句
- 复合语句简称为语句块,它使用大括号吧的许多语句和声明组合到一起,形成单条语句
 - 不用分号结尾
 - 在语句块内声明的变量将具有语句块作用域,在这个作用域内,这种声明会把在语句块以外声明的同名称对象隐藏起来
 - 动态变量的存储周期也被限制在语句块中它们生成的地方,这意味着,如果一个变量没有被声明为static或extern,那么变量的存储空间会在语句块结束后自动被释放
 - 可以在if中使用语句块
 
3.2格式化输入输出
1.C语言输入输出
- 需要引入头文件"stdio.h"
 - 格式符:格式占位符(%)和字母组成
 - 输入输出函数:putchar(字符输出)、puts(字符串输出)、printf(格式化输出)、getchar(字符输入)、gets(字符串输入)、scanf(格式化输入)
 
2.字符输入
- 
头文件:stdio.h
 - 
函数名:getchar()
 - 
功能:从键盘上接受一个字符的输入
 - 
常用形式
cchar a = getchar();cchar a; a = getchar(); - 
功能等价:是scanf函数的一种简化
 
3.字符输出函数
- 
头文件:stdio.h
 - 
函数名:putchar
 - 
功能:显示器上输出单个字符
 - 
常用形式:
cchar a = "c"; putchar(a); - 
功能等价:printf函数的一种简化
 
4.字符串输入函数
- 
头文件:stdio.h
 - 
函数名:gets
 - 
功能:从键盘上接受一串字符的输入
 - 
常用形式
cchar s[10]={0}; gets(s); - 
功能等价:scanf函数的一种简化
 
5.字符串输出
- 
头文件:stdio.h
 - 
函数名:puts()
 - 
功能:向显示器上输出一串字符串
 - 
常用形式:
cchar s[] = {"This is a String"}; puts(s); - 
功能等价:是printf函数的一种简化
 
6.格式化输入函数
- 引用头文件:stdio.h
 - 函数名:scanf
 - 功能:输入字符/字符串/数字等数据
 - 常用格式符:d(十进制整数)、o(八进制)、x(十六进制)、c(字符)、s(字符串)、f(实数)
 - 当用键盘输入多个数据时,数据之间用分隔符。分隔符包括空格符、制表符和回车符,单不包括逗号
 
7.格式化输出函数
- 头文件:stdio.h
 - 函数名:printf
 - 功能:输出字符/字符串/数字等数据
 - 常用输出格式符:d(十进制)、o(八进制)、x(十六进制)、u(无符号十进制)、f(小数)、e(整数全部输出,小数输出5位)、g(选择f或e格式中宽度较短的一个)、c(字符)、s(字符串)
 
4.选择结构
4.1if选择结构
1.选择结构
- 当对数据进行处理时,做出选择不同时,执行不同操作时,使用选择结构的设计来实现不同的处理
 - 选择结构分:if和switch
 
2.if语句
- if(表达式) 语句块1;
当表达式为真时,执行语句块1 - if(表达式) 语句块1; else 语句块2
当表达式值为真时,执行语句块1,为假时,执行语句块2 - if的表达式可以是任意合法的C语言表达式(如:逻辑表达式,关系表达式,算数表达式,复制表达式)也可以是任意类型的数据(整型,浮点型,字符型,指针型)
 
4.2switch语句
1.switch
- 开关语句
 - switch语句是一种多路判定语句(多分支选择),它测试表达式是否与一些常量整数值中的某个值匹配,并执行相应的分支动作
 - 配合关键字:case,break,default
 - switch是另外一种选择的语句,用来代替简单的,拥有多分支的 if else 语句
 
2.case执行
- 当switch后面括号内的表达式的值与某一个case后面的常量的表达式的值相等时,就执行case后面的语句
 - 若所有的case中的常量表达式的值都没有与表达式的值匹配的,就执行default(位置无所谓)后面的语句(主要看是否带break)不带break会执行后续case
 - 当匹配到某个case之后,发现没有break时各种情况(总结:遇到最近的break就退出)
- 找到其他case有break时执行完break时退出当前switch
 - 之后遇到default语句(带break)就退出
 - 之后遇到default语句(不带break)继续执行
 - case同理
 
 
3.注意
- swtich后小括号里面的表达式不能为实型(字符串也不行),只能是整型(字符型也是特殊的整数ASCII码可以使用0~127表示)等,case后表达式不能有变量
 - 判断是否正确的switch表达式与case常量表达式
 
4.3选择结构的嵌套
1.嵌套
- 选择结构的嵌套是实现复杂的分支结构处理
 - 常见的嵌套:if嵌套、switch嵌套、混合嵌套
 
2.if嵌套
- 注意if与else就近配对使用;
 - 语句块只有一条的时候,可以不写花括号;多条语句必须使用花括号
 
3.switch嵌套
- 某个case中再进行嵌套switch,不建议这样使用,一般建议可以嵌入一些简单的if判断
 - case的break,default微中子是否有break
 
4.混合嵌套
if和switch之间可以相互嵌套使用,不建议嵌套的太乱,层次太深,要根据实际情况来选择
5.循环结构
5.1 for循环
1.for循环组成
循环条件和循环体
2.格式:
            
            
              c
              
              
            
          
          for(表达式1,表达式2,表达式3){
    循环体;
}
        - 表达式1:一般是初始化变量(循环变量或其他变量),可以为空(缺,省),多个初始化时之间使用逗号分隔
 - 表达式2:一般是判定表达式(关系表达式、逻辑表达式或者复合表达式,最好是结果是真假值),可以为空
 - 表达式3:一般是使其循环变量值产生变化(自增++自减--,或者其他运算表达式等),可以为空,可以放在循环体内进行擦欧总,这样等于while或do while循环结构,多个表达式可以使用逗号分开
 
3.死循环
- 死循环是指循环体会一直执行下去,无法退出
 - 死循环一般是要避免的(循环一定要有结束条件,否则成了死循环),但是死循环不是一点用没有,有些特殊时间需要循环进行中断或者测试使用
 
5.2 while和do while循环
1.while
            
            
              c
              
              
            
          
          while(表达式1){
    循环体1;
}
        - 表达式1:循环条件,不可缺少,可以是复合表达式
 - 循环体:其中一般要有使用循环变量进行变化的语句,比如++,--等运算符进行操作
 - 当表达式1为1时,即while(1)是死循环
 
2.do while循环
            
            
              c
              
              
            
          
          do{循环体;}while(表达式);
        - 表达式1:不可缺,可以为复合表达式
 - 注意结尾的分号不可以少
 - 当表达式为1时,即死循环
 
5.3continue和break
1.continue
- 作用:continue是提前结束本轮循环
 - 使用场景:用于在循环中提前结束本轮循环,只能出现在循环体中
 - 当遇到continue时,停止后面的语句执行,去执行下一次循环
 
2.break
- 作用:在循环中break是终止整个循环,在switch中是退出当前的switch语句
 - 使用场景:它用于终止整个循环;或用于switch中退出当前switch语句
 - 当遇到break时,退出当前循环结构
 
5.4 循环嵌套
- 循环嵌套:某一个循环体中里面还有一个或多个循环
 - 对嵌套的层数没有限制,理论上是可以任意层嵌套
 - 但是建议一般不要超过三层
 - 外循环的循环变量变化一次,内循环要变化一轮
 - 计算时,要一层一层分析
 - 一般使用循环嵌套处理二维数组
 - 在循环嵌套中的break,只能退出break所在循环体的循环
 
6.数组
6.1 数组的定义和引用
- 数组:数组是有序的元素序列。若将有限个类型相同的变量的集合命名,那么这个名称为数组名
 
6.2 一维数组
1.一维数组
当数组每个元素都只带有一个下标时,称这样的数组为一维数组
2.定义
- 格式为:类型名 数组名[常量表达式]
 - 常量表达式可以省去不写,但是必须定义时就对数组进行初始化
 - 数组的所占字节为元素个数与基本类型所占字节的乘积
 
3.一维数组的初始化
- 
数组初始化元素值默认为0,没有初始化元素值为不确定的随机数
cint a[10]; // 各元素值是不确定的随机数 int b[10]={1}; // b[0]为1,其他元素默认为0 - 
一维数组初始化
cint a[10] = {0}; // a[0]是指定为0,其他元素默认值是0 int a[10] = {0,1,2,3}; // 未指定具体的元素初始值默认为0; int a[10] = {{0},{1},{2}}; // 初始化这样也可以 - 
使用循环初始化
cint a[10],i; for(i=0; i<10;i++){ a[i]=0; } - 
使用memset函数进行初始化
cint a[10]; memset(a,0,sizeof(a)/sizeof(a[0])); 
4.数组元素的引用
- 数组的下标都是从0开始,即a[0]表示数组a的首元素引用,下标可以是变量,可以是字符常量,整型常量,运算表达式
 - 数组的长度就是数组元素的个数
 - 当引用时,下标超出数组元素个数-1时,出现了数组下标越界
 - 每一个元素可以看成一个变量
 - 数组元素引用之后可以进行各种运算操作
 - 一维数组名是数组的首地址,数组名不能单独引用,不能通过一个数组名代表全部元素,数组名是地址常量,不饿能对数组名赋值,所以a为数组名时,a++时错误的,但数组名可以作为地址与一个整数相加得到一个新地址,一维数组名加减数字即表示水平移动
 
6.3二维数组
1.二维数组
当数组中每个元素都需要两个下标来确定时,称这样的数组为二维数组,像一个二维表一样,第一维是行,第二维是列,
2.定义
- 格式:类型名 数组名 [常量表达式1] [常量表达式2]
 - 常量表达式1可以省去不写,但是必须定义时就对数组进行初始化,常量表达式2不可以省略
 - 数组的所占字节为元素个数与基本类型所占字节的乘积
 
3.二维数组的初始化
- 
数组初始化值默认为0,没有初始化元素值为不确定的随机数
cint a[10][10]; // 各元素值是不确定的随机数 int b[10][10] = {1}; // a[0][0]为1,其他元素值默认是0; - 
同一维数组
 
4.引用
同一维数组
6.4 字符串与字符数组
1.字符串常量
- 字符串常量是由双引号括起来的一串字符
 - 在存储字符串时,系统会自动在其尾部加上一个空值"\0",空值也占用一个字节
 
2.字符数组
- C语言没有字符串变量,只能采用字符数组来存储字符串
 - 数组的大小应该比它将要实际存放的最长字符串多一个元素,从而存放"\0"
 
3.字符串的赋值
- 可以用下面的形式进行赋值:char arr[]="Hello"
 - 可以对字符数组逐个元素进行赋值,但一定要在最后赋一个'\0'
 
4.字符串输入输出
- 字符串输入:使用gets函数可以接受空格,scanf接收字符串时遇到空格会认为是结束
 - 字符串输出:使用puts函数在最后输出一个换行,printf换行需要手动填写'\n'
 
5.字符串函数
- 头文件:string.h
 - strcpy(s1,s2) 复制字符串s2到字符串s1
 - strcat(s1,s2) 连接字符串s2到字符串s1的末尾
 - strlen(s1) 返回字符串s1的长度
 - strcmp(s1,s2) 如果s1和s2相同,返回0;s1<s2 返回小于0; s1>s2 返回大于0
 - strch(s1,ch) 返回一个指针,指向s1中字符ch的第一次出现位置
 - strstr(s1,s2) 返回一个指针,指向s1中s2第一次出现的位置
 
6.字符串长度
- strlen函数和sizeof运算符都可以计算字符串长度
 - strlen遇到'\0'或者0就返回,实际上只计算到'\0'或0之前的字符长度
 
7.函数
7.1库函数
1.库函数调用
- 
调用c语言标准库函数时要包含include命令,include命令行以#开头,后面是""或者<>括起来的后缀为".h"的头文件
 - 
以#开头的一行称为编译预处理命令行,编译预处理不是C语言语句,不加分号,不占运行时间,常用的库函数头文件
c#include<stdio.h> // 标准输入输出函数 #include<stdlib.h> // abs绝对值函数 #include<stding.h> // 字符串函数 #include<ctype.h> // 字符函数 #include<math.h> // 数学函数 
2.数学函数
- 绝对值函数: abs和fabs
- abs() 是对整数取绝对值;函数原型 int abs(int x); 头文件:stdio.h
 - fabs() 是对浮点数取绝对值;函数原型 double fabs(double x);头文件是:math.h;
 
 - 平方根函数
- 函数原型:double sqrt(double x);头文件:math.h
 
 - 幂函数
- 函数原型:double pow(double x,double y);头文件:math.h
 - pow()用来计算以x为底的y次方值,然后将结果返回。设返回值为ret,则ret=x
 
 - 正弦函数
- 函数原型:double sin(double x);x为弧度;头文件:math.h;返回-1到1之间的计算结果
 
 
3.字符函数
头文件:ctype.h
- 
判断是否为小写:islower
- 函数原型:int islower(char ch)
 - 若ch是小写字母,则返回非0值,否则返回0;
 
 - 
判断是否为大写:isupper
- 函数原型:int isupper(char ch)
 - 若ch是大写字母,则返回非0值,否则返回0;
 
 - 
大写转小写:tolower
- 函数原型:int tolower(char ch)
 - 若ch是大写字母返回相应的小写字母
 
 - 
小写转大写:toupper
- 函数原型:int toupper()
 - 若ch是小写字符返回相应的大写字母
 
 - 
其他字符函数
cint isalnum(int c); // 检查字符是否为数字或字母; int isalpha(int c); // 检查字符是否为字母 int iscntrl(int c); // 检查字符是否为控制字符 int isdigit(int c); // 检查字符是否是十进制 int isgraph(int c); // 检查字符是否为图形表示 int isprint(int c); // 检查字符是否可打印的 int ispunct(int c); // 检查字符是否为标点符号 int isspace(int c); // 检查字符是否为空白字符 int isxdigit(int c); // 检查字符是否为十六进制数字 
4.字符串函数
头文件:string.h
- 字符串拷贝
- 函数原型:char * strcpy(char *dest,const char *scr);
 - 返回值:strcpy是一种C语言的标准库函数,strcpy把src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间,返回值的类型是char*。
 
 - 字符串比较
- 函数原型:int strcmp(const char *s1,const char *s2)
 - 返回值:若参数s1和s2字符串相同则返回0,s1若大于s2则返回大于0的值,s1若小于s2则返回值小于0的值。(ASCII码值比较)
 
 - 字符串连接
- 函数原型:char *stract(char *dest,const char *src);
 - 返回值:将src以追加的方式添加到dest中,返回值为dest首地址或者也可以直接访问dest获得最终结果
 
 - 字符串长度
- 函数原型:int strlen(const char *str)
 - 返回值:库函数strlen遇到'\0'(结束标记符)或者0就返回此之前的字符串的长度。注意这个时候'\0'是结束标记,要区分一下'\012'这种八进制转义字符中'\0'
 
 - 查找字符与字符串
- 字符:
- 函数原型:char *strchr(const char *s,char c); // 从左往右
 - 返回值:返回查找到的本身位置,如果查找失败则返回NULL
 
 - 字符串
- 函数原型:char *strstr(char *str1,const char *str2); // 从左往右
 - 返回值:查找字符串是否存在,不存在则输出false,存在返回查找到的字符串中的首地址
 
 
 - 字符:
 
5.随机函数
- 
头文件:stdlib.h
 - 
rand函数,C语言中用来产生一个随机数的函数
 - 
rand函数接线:stdlib.h头文件中有宏 #define RAND_MAX 0x7ff,rand产生一个 0-0x7fff(0-32767)的随机数,即最大是32767的一个数
 - 
函数原型:int rand(void)
 - 
函数应用
- 
如果想要表示一个数从0开始到最大值的,比如想要产生一个0-99之间的随机数,
cint num = rand()%100; // 随机产生0-99的整数 - 
如果想要产生一个数是从1开始到最大值的,比如想要产生一个1-100之间的随机数
cint num = rand()%100 + 1; - 
如果想要用此函数随机产生一个 0-99.99 之间的数,
cfloat num =(rand()%1000)/100.0; 
 - 
 
7.2 用户自定义函数
1.用户自定义函数
- 用户定义自己索要完成功能的函数
 - 一般有普通函数和递归函数
 
2.函数的定义
- 函数具有一定功能的一个程序块
 - 函数的首部为:函数类型 函数名(类型1 形参1,类型2 形参2,...)
 - 在函数定义中不可以在定义函数,即不能嵌套定义函数
 - 函数类型默认为int
 
3.函数返回值
- 通过return语句返回一个值,返回的值类型与函数类型一样
 - return只执行一次,执行完或函数体结束后退出函数
 
4.函数的声明
- 函数要"先定义后调用",或"先声明再调用后定义"
 - 函数原型包括返回类型、函数名、参数列表等函数定义的基本信息,一般用于告知调用者该函数的基本信息,便于调用
 - 函数原型声明通常有以下俩种形式:
- 无参函数原型声明格式为:
- 函数类型 函数名 (void);
 - 函数类型 函数名();
 
 - 带参函数预先声明
- 函数类型 函数名(类型1 参数1 ,类型2 参数2,...)
 - 函数类信息 函数名(类型1,类型2,...) // 形参的变量名可以缺少
 
 
 - 无参函数原型声明格式为:
 
7.3函数的调用与参数的值传递
1.函数的调用
程序从上往下执行,当碰到函数名后,把值传给调用函数,当程序得到了返回值或调用函数结束,再顺序往下执行
2.函数的参数及值传递
- 形式参数简称形参,是定义函数时函数名后面括号中的参数
 - 实在参数简称实参,时调用函数时函数名后面括号中的参数
 - 实参和形参分别占据不同的存储单元,实参向形参单向传递数值
 - 传值和传址的区别:
- 传值:传数值的话,形参的变化不会改变实参的变化,C语言规定,简单变量作为实参时,它和对应形参之间的数据传递方式时单向值传递
 - 传址:传地址的话,形参的变化就有可能改变实参所对应的量
- 实参是某个空间的地址,把该地址赋给形参变量,函数内对该地址擦欧总,可以间接对该地址所指的空间进行操作
 - 即传址调用过程,函数可以通过传入的地址值,改变该地址空间的值
 - 数组作为函数参数和指针作为函数参数均可实现址调用
 - 传址调用时,实参为地址
 - 形参一般为数组类型或指针类型
 - 如果形参为数组类型,则实参为同类型数组的数组名或首元素的地址
 
 
 
7.4 函数的嵌套调用与递归调用
1.嵌套调用
C语言中的函数定义是独立的,不可以定义再其他函数体内,只能单独下定义,但是可以在其他函数体内调用其他函数来完成相应的处理
2.函数的嵌套调用
- 一个函数的函数体中可以调用另一个函数,另一个函数也可以再调用其他函数
 
3.递归调用
- 函数直接或间接地调用自己称为函数的递归调用
 - 递归调用必须有一个明确的结束递归的条件
 - 递归调用的特性
- 递归调用必须存在一定的限制条件,当达到条件的时候,递归调用不再继续执行
 - 每次调用之后,其最终的结果都会是接近结束条件
 
 
7.5 局部变量与全局变量
1.变量的存储方式
- 静态存储方式
- 静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式
 - 全局变量全部存放在静态存储区中,在程序开始执行时给全局变量分配存储区,程序执行完毕就释放,整个执行过程中它们占据着固定的存储单元
 
 - 动态存储方式
- 动态存储方式是指在程序运行的期间根据需求进行动态的分配存储空间的方式
 - 动态存储区中存放以下数据:
- 函数形式参数。在调用函数时给形参分配存储空间
 - 函数中定义的没有用关键字static声明的变量,即自动变量,内部变量或局部变量。
 - 函数调用时的现场保护和返回地址等
 
 
 
2.变量的存储类别
- C语言中,每一个变量和函数都有2个属性:数据类型和数据的存储类别
 - C的存储类别有4种,
- 自动的 auto
 - 静态的 static
 - 寄存器的 register
 - 外部的 extern
 
 - 变量的存储类别分别对应变量的作用域与生命周期
 
3.变量的分类
- 变量按存储区域分为:全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区
 - 变量按作用域分:
- 全局变量:在整个工程文件内都有效;"在主函数外定义的变量",即从定义变量的位置到本源文件结束都有效,由于同一文件中的所有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值,就能影响到其他函数中全局变量的值
 - 静态全局变量:只在定义它的文件内有效,效果和全局变量一样,不够就在本文件内部
 - 静态局部变量:只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失,静态局部变量的生存期虽然为整个工程,但是其通仍与局部变量相同,即只能在定义该变量的函数内使用该变量,退出该函数后,尽管该变量还存在,但不能使用它。
 - 局部变量:在定义它的函数内有效,但是函数返回后失效,"在函数内定义的变量",即在一个函数内部定义的变量,只在本函数范围内有效
 
 
4.局部变量的存储类别
- 自动变量(auto)随着函数的使用与否创建消失;如函数中定义变量 int a;和 auto int a;是等价的,关于关键字"auto"是默认省略的,未初始或赋值时,其值是不确定的
 - 寄存器变量(register)分配在CPU中,没有内存地址;如果没有赋值或初始化,其值也不确定的。
 - 静态变量(static)占用固定存储单元(静态存储区),在程序执行过程中不释放,指导程序运行结束。此时应该用static声明该变量为"静态局部变量"。静态局部变量实际在编译时赋初始值的(不赋初始值,编译时自动赋0或空字符'\0')
 
5.全局变量的存储类别
- 全局变量都是存放在静态存储区中的
 - 在一个文件内扩展外部变量的作用域,应在引用前用关键字extern对该变量作"外部变量声明",表示把该外部变量的作用域扩展到此位置,用extern声明外部变量时,类目可写可不写
 - 将外部变量的作用域限制在本文件上加上static声明,只能用于本文件的外部变量称为静态外部变量