***************C语言******************

--day01--

Linux是一个和Windows类似的操作系统

通常通过终端软件使用Linux操作系统

终端软件里只能使用键盘不能使用鼠标

可以在终端软件里输入各种命令控制计算机
完成各种任务

clear命令可以清除终端窗口里的所有文字

操作系统里用来管理文件的部分叫文件系统

所有文件系统都采用分组的方式管理文件,
一个分组里可以包含任意多个文件
每个分组里的文件都可以再次分组

文件系统里把一个文件分组叫做一个文件夹或
目录

Linux文件系统里有一个大的文件分组,这个
分组里包含所有文件
这个文件分组叫做根目录
根目录可以使用/表示

如果目录A直接包含目录B则他们之间存在父子
关系,其中目录A叫做父目录,目录B叫做
子目录

路径用来表示文件或目录的位置
路径表示从某个目录到一个目录或文件所经过
的路线
根据起点不同可以把路径分为两种,一种是
绝对路径另外一种是相对路径

绝对路径的起点一定是根目录
所有绝对路径一定以/做开头,以/做开头的
路径一定是绝对路径

相对路径可以把任何目录作为起点
相对路径里使用..表示从下向上走一步
相对路径里使用.表示原地踏步
相对路径里不可以包含起点位置

终端里可以把一个目录设置成当前目录,
当前目录是所有相对路径的起点
当前目录的位置随时可以改变

pwd命令可以用来察看当前目录的位置

cd命令可以用来修改当前目录的位置
使用方法如下
cd 目录路径

ls命令可以用来察看一个目录里的内容
使用方法如下
ls 目录路径
如果省略目录路径就可以察看当前目录里的
内容
使用-a选项可以察看目录里的所有内容
使用-l选项可以察看每个内容的详细信息
这两个选项可以合并成-al

touch命令可以用来创建一个空文件
使用方法如下
touch 文件路径
如果文件已经存在就把文件的最后修改时间
改成执行touch命令的时间

rm命令可以用来删除一个文件
使用方法如下
rm 文件路径

mkdir命令可以用来创建目录
使用方法如下
mkdir 目录路径
目录必须还不存在,但是它的父目录必须已经
存在
使用-p选项可以把路径中所有还不存在的目录
都创建出来

rm命令使用-r选项就可以用来删除目录
使用方法如下
rm -r 目录路径

vi是Linux系统中用来记录文字信息的工具

vi只能在终端窗口里使用(只能使用键盘不能
使用鼠标)

vi的功能分成三组,任何时候只能使用其中
一组
vi里包含三种工作模式,每种工作模式对应
一组功能
任何时候只能处于一种工作模式下
三种工作模式分别是正常模式,插入模式和
命令模式

正常模式下可以执行简单命令
插入模式下可以修改文字内容
命令模式下可以执行复杂命令

每当启动vi的时候一定处于正常模式

可以在不同模式之间进行转换
正常模式下输入i可以转换成插入模式
正常模式下输入:可以进入命令模式
任何时候输入esc可以进入正常模式

可以使用如下命令启动vi
vi 文件路径

可以采用两种方法退出vi
1.在命令模式下输入q!可以退出vi(丢失没有
保存的修改)
2.在命令模式下输入wq或者x可以退出vi(首先
保存所有修改然后退出)

可以在命令模式下使用w命令保存所有修改
而不需要退出vi

在正常模式下输入nyy命令(n代表一个整数,如果
是1可以省略)。这个命令把光标所在行开始
的连续n行拷贝到剪贴板上

在正常模式下输入np命令(n代表一个整数,如果
是1可以省略)。这个命令把剪贴板上的内容
在光标所在行下面连续粘贴n次

在正常模式下输入ndd命令(n代表一个整数,如果
是1可以省略)。这个命令把当前光标所在行
开始的连续n行剪切到剪贴板上。

在命令模式下输入set nu命令可以让vi显示
每行的行号

gVim是windows里的vi

预习:
1.C语言程序基本结构
2.C语言程序开发过程
3.printf标准函数
4.变量

---day02--
C语言里包含以.c作为扩展名的文件,这种
文件叫源文件。C语言程序的绝大部分内容
应该记录在源文件里。
C语言里还包括以.h作为扩展名的文件,这种
文件叫头文件.

C语言程序里可以直接使用数字和加减乘除
四则运算符号(*代表乘法,/代表除法)

所有计算步骤都必须用分号做结尾,每个用
分号结束的计算步骤叫做一条语句

C语言程序里的绝大多数语句应该包含在
大括号中间

C语言程序里可以用大括号代表函数
(函数可以看作一组语句)

每个函数有一个名字,不同函数的名字不能
相同

C语言程序里至少要包含一个叫做main的函数,
这个函数叫主函数
整个程序从主函数的第一条语句开始执行,当
主函数最后一条语句结束后整个程序结束

一个函数结束后可以用一个数字表示它的工作
结果,这个数字叫函数的返回值
主函数应该有返回值,如果返回值是0表示
程序希望计算机认为它正常结束了,如果
返回值不是0表示程序希望计算机认为它
出问题了。

C语言里预先保留了几十个英文单词,它们叫做
关键字
每个关键字有特定的用途,不能随意使用
所有关键字都是由小写字母构成的

return就是一个关键字,它有两个用途。
主要用途是结束函数的执行,辅助用途
是指定返回值的数值

计算机里根据不同数字在某个方面的区别把
数字分成几组,每组叫做一个数据类型
每个数据类型都有自己的名字
整数类型叫做int,它几乎包含所有不带小数点
的数字

程序里的所有数字必须有类型,没有类型的
数字计算机无法处理
程序里不带小数点的数字默认是整数类型的

如果函数有返回值就应该把返回值的类型名称
写在函数名称前面

C语言程序编码规范
1.一行里最多包含一条语句
2.同级别语句最左边一列应该上下对齐
3.在合适的地方使用空格和空行

C语言程序里通常会包含预处理指令
预处理指令都以#做开头,不是以;做结尾
标准C阶段遇到的预处理指令都可以把写在
文件里的内容替换成其他内容
#include预处理指令可以把一个头文件的
内容包含到当前文件里
这个预处理指令中通常采用相对路径表示
被包含头文件的位置
如果把相对路径包含在<>中间就表示以系统
中预先规定好的一组目录依次作为起点
如果把路径包含在""中间就表示首先以当前
文件所在目录作为起点,然后再以系统中
预先规定好的一组目录依次作为起点

可以在C语言程序里加入各种文字性的说明
信息
这些文字性的说明信息必须加入到注释区域里
计算机会直接忽略注释区域里的内容
单行注释以//做开头,一直到行尾
多行注释以/*做开头,以*/做结尾

C语言里大量使用名称区分不同内容,
这些名称叫做标识符
尽量采用英文单词做标识符
标识符编写规则
1.标识符的第一个字符可以是英文字母或下划线
2.后面的每个字符可以是英文字母,下划线或
阿拉伯数字
3.大小写不同的标识符是不同的标识符
(大小写敏感)
4.关键字不能作为标识符使用
5.标识符的长度没有限制,计算机只会截取
前面一部分使用
6.标识符可以采用驼峰方式或下划线方式书写

编译器可以把源文件翻译成计算机能认识的格式
gcc是Linux系统里常用的C语言编译器
MinGW是Windows里的gcc

Linux系统里开发C语言程序的基本步骤
1.采用vi编写源文件和头文件
2.使用gcc把所有文件翻译成计算机能认识的
格式(编译)
3.使用./a.out做命令就可以执行程序

gcc编译器的工作步骤
1.处理所有预处理指令
2.把第一步的处理结果翻译成计算机能
认识的格式(编译)
3.把第二步的结果合并成可以执行的文件(链接)

gcc选项介绍
-E 只处理预处理指令
-c 只处理预处理指令并把结果翻译
成计算机认识的格式
处理结果是以.o作为扩展名的
目标文件
-o 用来决定最终执行文件的名称
-std=c89/-std=c99
用来决定采用什么版本进行编译
默认采用c89规范编译

C语言里提供一组标准函数,它们用来一些解决
常见的问题
不同标准函数的名称不同
可以在程序里编写函数调用语句使用标准函数

printf标准函数可以把程序里的数字显示在
终端窗口里
为了使用这个标准函数需要包含stdio.h头文件
可以使用占位符把双引号里面的数字转移到
双引号后面
双引号后面的数字可以是一个计算公式的结果,
计算机会先计算出结果然后替换掉双引号
里面的占位符
不同类型的数据应该和不同的占位符配合使用,
整数类型数字和%d占位符配合使用
可以在一条语句里使用多个占位符,占位符
的数量应该和双引号后面数字的数量一样

程序中使用的数字都记录在内存里
内存由大量的字节构成,每个字节可以记录
一个数字
每个字节有一个编号,这个编号叫做字节的
地址
不同字节的地址不同
所有地址从0开始向正数方向递增
字节地址有前后顺序,地址小的在前,地址
大的在后

可以把几个相邻的字节合并成一个整体用来
记录一个数字

可以把内存里用来记录一个数字的所有字节叫做
一个存储区
一个存储区只能记录一种类型的数字
存储区也有地址,存储区的地址就是它所包含
的字节里最前面那个字节的地址

C语言里变量可以用来代表存储区(对变量的
操作就是对它所代表存储区的操作)
变量必须首先声明然后才能使用,变量声明
语句可以用来声明变量
变量声明语句会让计算机为程序分配一个存储区
可以在一条变量声明语句里声明多个同类型
变量

赋值语句可以向变量代表的存储区里放一个数字
赋值语句里需要使用赋值操作符(=)
赋值操作符左边的内容必须可以代表存储区,
这种内容叫左值(变量就是一种左值)
赋值操作符右边的内容必须可以当作数字使用
赋值操作符可以把右边的数字放在左边的
存储区里

可以在声明变量的时候立刻对变量进行赋值,
这叫做变量的初始化
C语言里所有变量都应该初始化

可以直接在程序中把变量当作数字使用,这个
数字就是变量代表存储区里的数字

变量名称既可以代表存储区也可以代表存储区
里的数字,由环境决定

存储区的地址也可以代表存储区
在变量名称前使用符号&可以得到存储区的地址
可以使用%p作为占位符把地址数据显示在屏幕上

变量可以用来代表固定数字

可以用一个变量代表一组数字(不同的时候代表
不同的数字)

预习:
1.数据类型
2.scanf标准函数
3.sizeof关键字
4.二进制

--day03--

字符类型的名称是char
字符类型里包含256个不同的整数,每个
整数对应一个字符(例如'a', '^'等)
这些整数和字符完全可以互相替代
ASCII码表列出所有整数和字符的对应关系
'a' 97
'A' 65
'0' 48

ASCII码表里所有小写英文字母是连续排列的,
其中'a'对应的整数最小,'z'对应的整数
最大
所有大写英文字母和阿拉伯数字字符也都符合
这个规律

'd' - 'a' 等于 'D' - 'A'
'd' - 'a' 等于 '3' - '0' 等于 3 - 0

所有字符数据被分成两组,每组包含128个
其中一组字符对应的整数在所有计算机上都
一样,这些整数的范围从0到127
另外一组字符对应的整数在不同计算机上有可能
不同,这些整数的范围可能从-128到-1也
可能从128到255

'\n' 换行字符
'\r' 回车字符
'\\' 代表字符\
'\'' 代表字符'
'\"' 代表字符"

短整数类型名称是short
它里面包含65536个不同的整数,其中一半是
负数,另外一半是非负数。这些数字以0
为中心向两边扩展。

长整数类型名称是long
它里面包含2的32次方个不同的整数,其中
一半是负数,另外一半是非负数。这些
数字以0为中心向两边扩展。

整数类型名称是int
在我们的计算机里整数类型和长整数类型
完全一样

以上类型都叫做有符号类型
每个有符号类型都有一个对应的无符号类型,
无符号类型的名称就是在对应有符号类型
名称前加unsigned(例如unsigned char,
unsigned int等)
无符号类型包含的数字个数和对应的有符号
类型一样,但是不包含负数

整数相关类型所包含的数字范围互相重叠并
逐渐扩大

程序中不带小数点的数字后加u表示这个数字
的类型是无符号整数类型

C语言里用浮点类型表示带小数点的数字
浮点类型分为单精度浮点类型和双精度浮点类型
双精度浮点类型可以记录更多小数点后面的数位
单精度浮点类型的名称是float
双精度浮点类型的名称是double

程序中带小数点的数字默认都是双精度浮点
类型的
如果在带小数点的数字后加f就表示这个数字的
类型是单精度浮点类型

C语言里可以创建新的数据类型
这些新的数据类型叫做复合数据类型
复合数据类型必须先创建出来然后才能使用

C99规范里引入布尔类型
布尔类型里只包含两个数字,一个叫真另外
一个叫假。真用1表示,假用0表示。
真和假都叫做布尔值

所有整数都可以当作布尔值使用,0当作布尔值
使用的时候是假,其他所有整数当布尔值
使用的时候都是真

一般在程序里不需要使用布尔类型,直接用
整数类型代替

数据类型和占位符的对应关系
char和unsigned char %c
short %hd
unsigned short %hu
long %ld
unsigned long %lu
int %d
unsigned int %u
float %f或%g
double %lf或%lg
%f或%lf会保留小数点后
无效的0,%g和%lg不会保留

不同类型存储区所包含的字节个数可能不同
sizeof关键字可以用来计算一个类型的存储区
所包含的字节个数

char和unsigned char 1个字节
short和unsigned short 2个字节
int和unsigned int 4个字节
long和unsigned long 4个字节
float 4个字节
double 8个字节

sizeof关键字小括号里可以写任何能当作
数字使用的内容
sizeof小括号里对任何存储区内容的修改不会
真正发生

scanf标准函数可以用来从键盘得到用户临时
输入的数字
为了使用这个标准函数需要包含stdio.h头文件
scanf函数调用语句里要使用存储区的地址
表示存储区
双引号里使用占位符表示存储区的类型
不要在scanf函数调用语句的双引号里写不是
占位符的内容
如果用户输入的内容不符合程序中要求的格式
程序就不能得到数字
可以在一条scanf函数调用语句里得到多个数字,
这个时候要提供多个存储区地址

一个字节分成八段,每段只能记录一个0或者1
要想把一个数字记录到一个字节里就需要首先
把这个数字拆分成八个0或者1
用一组0或者1表示数字的方法叫做二进制
任何一个数字既可以用十进制方式表示也可以
用二进制方式表示
计算机里只能记录二进制方式表示的数字
二进制表示方式里包含很多数位,每个数位
有一个编号。最右边数位的编号是0,向左
依次递增。
某个数位里的1代表的数字是2的数位编号次方
二进制表示方式中如果两个相邻数位的内容一样
则左边数位代表的数字是右边数位代表
数字的2倍
二进制表示的非负数符合以上规则
二进制数字加一的时候需要把编号0位置开始的
连续多个1都变成0,把最右边的0变成1

二进制表示的非负数转换成十进制的时候首先
把每个数位单独代表的数字计算出来然后再
求和

0001 0011 = 2的4次方 + 2的1次方 + 2的0次方
= 16 + 2 + 1
= 19

0110 1010 = 2的6次方 +2的5次方 + 2的3次方
+ 2的1次方
= 64 + 32 + 8 + 2
= 106

不断对原始数字进行除以2并保留整数部分的
操作可以得到一组数字,用这组数字中的
每一个除以2取余得到一个数位的内容。
把所有数位按照从后向前的顺序书写就
得到转换结果。

12 *******0
6 ******0
3 *****1
1 ****1
0 ****

转换结果是0000 1100

91 1
45 1
22 0
11 1
5 1
2 0
1 1
0 0

转换结果是0101 1011

负数的二进制和十进制之间不能直接转换,
必须借助相反数

转换过程需要首先计算相反数,然后把相反数
进行转换,最后根据转换结果再计算相反数

把二进制数字中每个数位的内容变成相反数然后
再加一就得到相反数的二进制

-14
14
0000 1110
1111 0001 + 1 = 1111 0010

有符号类型数字最左边的二进制数位内容可以
用来判断数字的符号,这个数位叫做符号位。
符号位内容是0表示数字是非负数,符号位
内容是1表示数字是负数。

1100 0101
0011 1010 + 1 = 0011 1011
59
-59

预习:
1.八进制和十六进制
2.操作符

--day04--
把二进制表示的数字从右向左每三个数位分成
一组,每组用一个0到7之间的数字替换。
这个替换结果叫做数字的八进制表示方式

0110 1010 01 101 010 152(八进制)

可以直接在程序里用八进制方式表示数字,
这种数字必须以0做开头
可以采用%o做占位符把数字的八进制表示
方式显示在屏幕上

把二进制数字从右向左每四个数位分成一组,
每组用一个字符替代,这个替换结果
叫做数字的十六进制表示方式。
用a到f之间的字母替换10到15之间的数字

1100 1011 cb(十六进制)

可以在程序里使用十六进制方式表示数字,
这种数字必须以0x做开头
可以使用%x或%X做占位符把数字的十六进制
表示方式显示在屏幕上
显示结果不是以0x做开头的
使用%x做占位符的时候显示结果里所有字母
都是小写的
使用%X做占位符的时候显示结果里所有字母
都是大写的

操作符代表对数字的处理规则
根据操作符所需要配合的数字个数把操作符
分为单目操作符,双目操作符和三目
操作符

C语言里用+,-,*和/代表加减乘除四则运算符号
如果参与除法计算的两个数字都是整数则计算
结果只保留整数部分

取余操作用%表示

赋值操作符用=表示
它可以把一个数字记录到一个存储区里
赋值语句可以当作数字使用,这个数字就是
赋值完成后左边存储区里的数字
可以在一条语句里使用多个赋值操作符,这个
时候先计算右边的操作符

C语言里绝大多数双目操作符可以和赋值操作符
合并形成复合赋值操作符,例如+=, %=等
复合赋值操作符左边必须是一个存储区,右边
必须是一个数字
复合赋值操作符会把双目操作符的结果记录到
左边的存储区里
复合赋值操作符的优先级和赋值操作符一样低

自增操作符(++)和自减操作符(--)都是单目
操作符
它们都只能和存储区配合使用,它们可以把
存储区的内容做加一或减一操作
它们都有两种使用方法,一种是前操作(操作符
写在存储区前面)另外一种是后操作
(操作符写在存储区后面)
使用自增或自减操作符编写的表达式本身也可以
当作数字使用。前操作当作数字使用的时候
是修改后的数字,后操作当作数字使用的
时候是修改前的数字。
不要在一条语句里对同一个变量多次进行自增
或自减计算,因为结果不确定

逻辑操作符用来编写逻辑表达式
逻辑表达式的结果一定是布尔值

!是一个单目逻辑操作符,它表示对一个
布尔值求反(真变假,假变真)

双目逻辑操作符包括等于(==),不等于(!=),
大于(>),小于(<),大于等于(>=)和
小于等于(<=)

如果一个表达式里最多包含一个双目逻辑操作符,
它在计算机里的结果和在数学里的结果一定
一样。这种表达式叫做简单逻辑表达式。
如果一个表达式里包含多个双目逻辑操作符就
必须首先拆分成多个简单逻辑表达式然后
再合并

与(&&)和或(||)也是双目逻辑操作符,他们可以
把两个逻辑表达式合并成一个

如果原来的两个逻辑表达式里有一个的结果
是假则用与(&&)合并后的逻辑表达式结果
也一定是假
如果原来的两个逻辑表达式里有一个的结果
是真则用或(||)合并后的逻辑表达式结果
也一定是真

与(&&)和或(||)都具有短路特征(如果
前面的逻辑表达式结果可以决定整个逻辑
表达式的结果就不计算后一个逻辑表达式)

位操作符可以直接操作二进制数位

~是一个单目位操作符
它可以根据一个数字计算出另外一个数字,这
两个数字的所有二进制数位内容都不一样
(按位求反)

双目位操作符包括按位与(&),按位或(|)和
按位异或(^)
它们都可以把两个数字对应二进制数位的内容
做计算

按位与(&)可以把对应数位的内容做与计算
只要一个数位的内容是0则与计算的结果就是0

3 0000 0011
& 5 0000 0101
0000 0001

按位或(|)可以把两个数字对应数位的内容做
或计算
如果一个数位的内容是1则或计算以后结果
就是1

3 0000 0011
| 5 0000 0101
0000 0111

按位异或(^)可以把两个数字对应数位的内容做
异或计算
如果两个数位的内容一样则异或以后结果是0,
否则结果是1

3 0000 0011
^ 5 0000 0101
0000 0110

移位操作符可以把一个数字里所有二进制数位
的内容统一向左或向右移动n个位置
>>表示向右移位
<<表示向左移位
它们都是双目位操作符
操作符左边的数字是将要进行移位操作的数字
操作符右边的数字是将要移动的位数
移位操作相当于把每个数位的内容换一个数位放

向左移位的时候一定在右边空出来的数位里
填充0

有符号类型数字右移时左边空出来的数位里
一定填充符号位的内容,无符号类型数字
右移时左边空出来的数位里一定填充0

一般情况下数字向左移动n位相当于乘以2的
n次方,向右移动n位相当于除以2的n次方

位操作符不会修改现有存储区的内容

&也可以作为单目操作符使用,这个时候
它可以根据一个存储区计算出存储区
的地址
可以使用%p做占位符把地址数据显示在屏幕上
我们的计算机里所有地址都是32个二进制数位
构成的

*也可以作为单目操作符使用,这个时候它可以
根据地址找到地址对应的存储区

三目操作符可以从两套不同的计算规则中选择
一套进行计算
三目操作符格式如下
布尔值 ? 公式一 : 公式二
如果布尔值是真就采用公式一进行计算,否则
采用公式二进行计算
不要在问号后使用赋值操作符

预习:
1.类型转换
2.分支(if分支,switch...case分支)
3.for循环

--day05--
如果表达式里包含多个不同类型的数字就必须
首先把它们转换成同一个类型然后才能
计算
这个转换过程叫做隐式类型转换,完全由
计算机完成

隐式类型转换过程中一定把占地小的类型转换
成占地大的类型

如果不同类型存储区大小一样就把整数类型转换
成浮点类型,把有符号类型转换成无符号
类型

C语言里可以临时给一个数字指定一个类型,
这叫做强制类型转换
强制类型转换格式如下
(char)300
强制类型转换有可能导致数据内容丢失

类型转换不会修改现有存储区的内容,计算机
会产生一个新存储区用来记录转换后的数字

分支语句可以在程序运行的时候从多组语句中
选择一组执行而忽略其他组
如果编写程序的时候遇到多种可能性,每种
可能性都需要使用专门的语句处理,这种
情况就可以采用分支结构解决。

if关键字可以用来编写分支
if分支里需要为每种可能性编写专门的
处理语句
if分支里需要为每组语句编写配对的逻辑表达式,
执行的时候如果某个逻辑表达式结果为真
就执行它配对的那组语句

有可能同时执行的语句不可以包含在一个
if分支里

编写if分支之前应该把所有可能性的个数先
确定下来

如果if分支中的所有可能性不会都不执行就
可以省略最后一组语句的逻辑表达式

如果if分支里多个逻辑表达式的结果同时为真
就执行最前面为真的逻辑表达式对应的语句
而忽略后面的语句
if分支里的某一组语句不仅仅只和与它配对的
逻辑表达式有关,还和前面的所有逻辑
表达式都有关
编写if分支的时候尽量把简单逻辑表达式写在
前面,这样可能可以简化后面的逻辑表达式

switch...case关键字也可以用来编写分支
如果分支里的每种可能性都可以用一个整数
表示就可以采用switch...case关键字
编写分支解决这个问题

循环语句可以让一组语句反复多次执行
for关键字可以用来编写循环
for循环里可以让一个变量依次代表一组数字,
然后使用一组语句处理这个变量代表的
每个数字
这个变量叫做循环变量
采用如下格式描述循环变量的变化过程
(把开始数字赋值给循环变量;
用逻辑表达式表示循环变量在变化过程中和结束数字的关系;
循环变量每次变化的规律)
如果一个问题可以采用一组数字的变化过程描述
并且这组数字之间符合某种规律就可以采用
for循环解决这个问题

假设有如下的for循环
for (1;2;3) {
4
}
它按照以下方式分组执行
[1,2][4,3,2][4,3,2]...[4,3,2]
第一组和其他组都不一样
正常情况下for循环一定在两组之间结束
如果某一组最后编号为2的逻辑表达式结果
为真就启动下一组,否则结束循环
如果循环正常结束则循环变量一定落在指定
范围之外
for循环有可能不执行大括号里面的语句

for循环小括号里的每部分都可以省略
如果省略小括号中间的逻辑表达式就表示
逻辑表达式永远为真,这种循环不能
正常结束,这种循环叫做死循环

for循环小括号里前后两部分可以是用逗号
连接的多条语句

C99规范里允许在for循环的小括号里临时声明
循环变量
这种循环变量只能在循环里使用,循环结束
之后就不存在了

可以在循环里使用break;语句立刻结束循环的
执行
一旦执行了break;语句则循环里的一切语句都
不再执行,包括循环变量也不再变化
使用break;语句结束循环后循环变量的数值
一定在指定数字范围内
如果编写循环的时候不容易描述循环的结束
条件就可以编写一个死循环,然后在
循环里用break;语句结束它

可以在循环里使用continue;语句直接跳到
循环大括号的末尾,中间的语句这次循环
就不执行了

预习:
1.for循环
2.多重循环
3.while循环和do...while循环
4.缓冲区管理
5.数组

--day06--
无法预知的数字叫随机数
rand标准函数可以用来获得随机数
为了使用这个标准函数需要包含stdlib.h头文件

srand标准函数用来设置随机数种子
这个函数把一个整数作为种子使用
不同的种子产生的随机数不同
为了使用这个标准函数也需要包含stdlib.h头
文件

time标准函数可以用来获得当前时间
这个函数用一个整数表示当前的时间
同一秒之内这个用来代表时间的整数是同一个
为了使用这个标准函数需要包含time.h头文件

任何程序只需要设置一次随机数种子

分支和循环都可以让程序中的语句不再从上到下
顺序执行,它们都叫做流程控制语句

goto也是流程控制语句
goto语句可以把任何一条语句指定成下一条
语句
一般不要使用goto语句

如果一个问题可以用多组数字的变化过程描述,
并且不同数字的变化频率不同就可以采用
多重循环结构解决。
编写多重循环的时候外部循环变量应该用来代表
变化慢的数字,内部循环变量应该用来代表
变化快的数字

while关键字也可以用来编写循环
不适合采用for关键字编写的循环再考虑
用while关键字编写
while循环格式如下
while (逻辑表达式) {
反复执行的语句
}
反复执行大括号里面的语句直到逻辑表达式
结果为假

while循环会交替执行逻辑表达式的计算和大括号
里面的语句

while循环第一步计算逻辑表达式的结果

当逻辑表达式为假的时候循环结束

while循环有可能不执行大括号里面的语句

while循环的逻辑表达式如果永远为真(比如1)
就成为死循环

while循环里也可以使用break;和continue;语句

do...while关键字也可以用来编写循环
do...while循环格式如下
do {
反复执行的语句
} while (逻辑表达式);
do...while循环小括号后面必须用分号结束
do...while循环也会交替执行逻辑表达式的
计算和大括号里面的语句
do...while循环第一步执行大括号里面的语句
do...while循环可以保证大括号里面的语句
至少执行一次

scanf函数获得数字的时候数字首先从键盘
进入输入缓冲区,然后从输入缓冲区
进入程序的存储区
先进入输入缓冲区的数字必须先处理,前面
的数字没有处理完就不能处理后面的数字
如果用户输入的格式和程序里要求的格式不
一样就无法处理以后用户输入的数字

可以使用如下两条语句把用户某一次输入的
所有内容都从输入缓冲区里丢掉
scanf("%*[^\n]");
scanf("%*c");

printf函数显示数字的时候首先把数字放在
输出缓冲区里然后再显示在屏幕上
输出缓冲区里的内容在以下四种情况下才会
出现在屏幕上
1.如果输出缓冲区里包含'\n'换行字符则
换行字符前面的内容会显示在屏幕上
2.程序结束后它放在输出缓冲区里的内容会
显示在屏幕上
3.当输出缓冲区被充满的时候它里面的内容
会显示在屏幕上
4.使用fflush(stdout)语句可以强制把输出
缓冲区里的内容显示在屏幕上

数组用来代表内存里一组连续的同类型存储区
这些存储区叫做数组的元素
数组也需要先声明然后才能使用
声明数组时也需要提供类型名称和数组命令,
另外还需要提供一个整数用来表示数组里
的存储区个数
数组一旦存在则里面存储区的个数就不可以
改变了
数组通常不会作为整体使用,一般一次只
使用其中的某个存储区
数组里每个存储区有一个编号,这个编号
叫做下标
有效下标范围从0开始到存储区个数减一为止,
超过范围的下标不能使用
使用数组名称和下标就可以表示数组里的某个
存储区

可以使用for循环依次处理数组里的每个存储区
在这个for循环里循环变量依次代表每个有效
下标

数组也应该初始化
初始化数组的时候可以提供多个初始化数据,
它们应该写在一对大括号中间,相邻数据
之间用逗号分开
如果初始化数据的个数比存储区的个数多
就忽略后面的初始化数据
如果初始化数据的个数比存储区的个数少
就把后面的存储区初始化成0
如果初始化数据个数和存储区个数一样就可以
省略数组声明里的存储区个数

预习:
1.数组
2.变长数组
3.多维数组

--day07--
数组名称不可以代表存储区
数组名称可以代表数组里第一个存储区的地址

可以对数组名称进行sizeof计算,结果是
数组里所有存储区的总大小

C99规范里可以使用变长数组
声明变长数组的时候可以用变量表示数组里
的存储区个数
某一次程序执行过程中变长数组里存储区
个数不会变化
如果程序会多次执行则每次执行的时候数组
里包含的存储区个数可能不同
变长数组不可以初始化

多维数组可以表示存储区的分组情况
一维数组不能表示存储区的分组情况
二维数组是最常见的多维数组,它只代表
了存储区的一次分组情况
声明二维数组的时候需要提供两个整数,
前一个整数表示分组个数,后一个整数
表示每组里的存储区个数
使用二维数组名称和两个下标可以表示二维
数组里的某个存储区,前一个下标表示
分组编号(组下标),后一个下标表示
分组内的存储区编号(组内下标)
组下标的有效范围从0开始到分组个数减一为止
组内下标的有效范围从0开始到组内存储区
个数减一为止
可以采用多重循环依次处理二维数组里的每个
存储区
可以把二维数组当作一维数组进行初始化
可以对初始化数据进行分组,一组初始化数据
用来初始化一组存储区
如果可以根据初始化数据的个数计算出分组个数
就可以省略数组声明里的分组个数

二维数组名称也可以代表数组里第一个存储区
的地址
对二维数组名称进行sizeof计算结果是数组
里所有存储区的总大小

二维数组名称也可以只配合一个下标使用,这个
下标当组下标用。这个写法表示那一组中
最前面那个存储区的地址
这个写法有时候可以当作一维数组使用,这个
一维数组由组下标对应组中所有存储区
构成

预习:
1.函数

--day08--
C语言里可以采用分组的方式管理语句
每个语句分组叫做一个函数

多函数程序执行的时候时间分配情况必须
遵守以下规则
1.整个程序的执行时间被划分成几段,每段
时间都被分配给一个函数使用
2.不同时间段不能互相重叠并且所有时间段
必须连续
3.如果函数A在工作的时候把一段时间分配给
函数B使用则函数B结束所有工作之后必须
把后面的时间还给函数A

如果函数A在工作的时候把时间分配给函数B
使用则它们之间存在函数调用关系
在函数调用关系中函数A叫做调用函数,函数B
叫做被调用函数
函数调用关系只在被调用函数工作的时间
范围内才存在

函数调用语句可以产生函数调用关系,可以
把一个函数的执行时间分配给别的函数

不可以跨函数使用变量
不同函数里的变量可以重名
如果函数多次运行则它里面的变量每次
对应的存储区都可能不同

声明变量的时候可以使用volatile关键字,
这种变量对应的存储区可以被多个
程序同时使用

函数调用过程中通常伴随着两个函数之间
的数据传递
函数调用过程中数据传递存在两个完全相反
的方向,可以从调用函数传递给被调用
函数也可以从被调用函数传递给调用函数
任何方向的数据传递都要使用被调用函数提供
的存储区

只能从被调用函数向调用函数传递一个数据
这个数据叫做被调用函数的返回值
只能在被调用函数结束的时候传递返回值
传递返回值的时候需要把它记录到被调用函数
提供的一个存储区里,这个存储区的类型
名称应该写在函数名称前
被调用函数里使用return关键字可以把返回值
记录到这个存储区里
调用函数把函数调用语句当作数字使用就可以
得到函数的返回值

如果被调用函数没有使用return关键字向存储区
里放返回值则存储区里的内容是随机的
调用函数只有一次获得返回值的机会,得到
返回值以后或者立刻使用或者另外存储
到其它存储区
如果函数没有返回值就应该在函数名称前
写void
如果函数名称前什么都不写在C89规范里表示
函数提供一个整数类型存储区用来存放
返回值,在C99规范里不允许这样

被调用函数不可以用数组存放返回值

函数调用过程中可以从调用函数向被调用函数
传递多个数据,这些数据的类型可以不同
被调用函数需要为每个传递过来的数据提供一个
对应的存储区
可以使用被调用函数提供的一组变量表示
这些存储区,这些变量必须声明在
函数名称后面的小括号里
这些变量叫做函数的形式参数,小括号里的
所有内容叫做函数的形式参数列表
每个形式参数的类型名称都不可以省略
相邻形式参数声明之间用逗号分开
被调用函数里可以象使用普通变量一样使用
形式参数
函数调用语句的小括号里需要为每个形式参数
提供一个对应的数字,相邻数字之间用逗号
分隔
这些数字叫做实际参数
函数调用的时候计算机把每个实际参数存放在
对应的形式参数里,被调用函数里可以
通过形式参数得到实际参数的数值
只要能当作数字使用的内容都可以作为实际参数
使用
如果函数没有形式参数就应该在小括号里写void
编写函数时如果小括号里什么都没写表示函数
可以提供任意多个形式参数,这些形式参数
的类型可以不同

预习:
1.函数
2.递归函数
3.作用域和生命周期
4.全局变量和局部变量

--day09--
数组可以作为形式参数使用
数组做形式参数的时候真正的形式参数并
不是数组而是一个可以作为数组使用的
变量
数组形式参数里包含的存储区都不是被调用
函数提供的
声明数组形式参数的时候可以省略中括号
里的整数
使用数组形式参数的时候必须配合一个整数
类型的形式参数,这个参数用来表示
数组里的存储区个数
数组形式参数可以让被调用函数使用其他函数
的存储区
调用函数和被调用函数都可以自由使用数组
形式参数里的存储区,所以数组形式参数
可以实现双向数据传递,具有这种特征的
形式参数叫输入输出参数

C语言里函数参数的个数可以不固定
这种参数叫做变长参数
不能在编写函数的时候给变长参数命名,
在被调用函数里可以通过特殊的方法
获得没有命名参数的内容

如果编译器首先遇到函数调用语句就会猜测
函数的格式。计算机认为函数有一个整数
类型的存储区用来存放返回值,函数可以
接受任意多个不确定类型的参数。
这个猜测结果叫做函数的隐式声明
隐式声明里参数的类型只能是整数类型或
双精度浮点类型
如果函数的真实格式和隐式声明格式不同
则编译的时候就会出错
可以把函数大括号前面的部分单独写成一条
语句,这种语句叫做函数声明语句
把函数声明语句放在文件开头叫做显式函数
声明
函数的显示声明可以避免隐式声明的发生
函数声明语句里可以省略形式参数的名称

除了主函数以外的所有函数都应该显示声明

exit标准函数可以立刻结束程序的执行
为了使用这个标准函数需要包含stdlib.h头文件
这个函数需要一个整数类型的参数,这个参数
的作用和主函数返回值的作用一样

C语言里函数可以调用自己
这种函数叫做递归函数

如果一个问题可以拆分成多个小问题,至少
一个小问题和原来的问题在本质上一样但是
稍微简单一点。这种问题就适合采用递归
函数解决。

递归函数编写步骤
1.编写语句解决分解后的每个小问题
(这个时候要假设递归函数已经完成,
可以使用)
2.在递归函数开头编写分支解决不可分解
的情况(这个分支必须可以让函数结束)

使用递归函数解决问题的方法叫递归
使用循环解决类似问题的方法叫递推

检验递归函数的时候先用最简单的参数检验,
然后逐渐把参数变复杂继续检验。如果
所有参数的检验都能成功就说明递归
函数编写正确。

C语言里一个变量只能被某些语句使用,能
使用某个变量的所有语句叫做那个变量
的作用域
声明在某个函数里面的变量叫做局部变量
局部变量的作用域就是函数里面的所有语句
声明在所有函数外边的变量叫全局变量
全局变量的作用域包含程序里的所有语句
没有初始化的全局变量会自动被初始化成0
全局变量和局部变量可以重名,重名变量名
优先代表局部变量
如果全局变量和局部变量都能解决问题就
应该优先选用局部变量

存储区的使用不受作用域限制,但是受到
生命周期限制
生命周期指一段时间,在生命周期开始的时候
计算机把存储区分配给程序使用,在
生命周期结束的时候计算机把存储区收回
全局变量的生命周期就是整个程序的执行时间
局部变量的生命周期是函数某一次执行的
时间范围

--day11--
使用存储区的地址作为返回值可以让调用
函数使用被调用函数的存储区
这种时候被调用函数需要提供一个指针类型
的存储区记录作为返回值的地址数据
不可以把非静态局部变量的地址作为返回值
使用

C语言里的文字信息必须记录在一组连续
的字符类型存储区里
所有文字信息必须以'\0'字符做结尾,这个
字符的ASCII码就是数字0
符合以上两个特征的内容可以用来在C语言
程序里表示文字信息,它们叫做字符串
字符串里'\0'字符前面的部分是有效字符
所有字符串都可以采用字符类型指针表示

字符串字面值是表示字符串的一种方法,
用两个双引号中间包含的一组字符
表示字符串字面值(例如"dsg","^*&*@"等)
编译器在编译的时候会自动在字符串字面值的
末尾追加'\0'字符
编译器会把字符串字面值替换成第一个字符
所在存储区的地址
字符串字面值的内容在程序执行过程中不
可以改变
程序里内容一样的字符串字面值是同一个
多个并列的字符串字面值会被合并成一个

字符数组也可以用来记录字符串
只有包含'\0'字符的字符数组才可以当作
字符串使用
可以使用字符串字面值对字符数组进行初始化,
编译器会把字符串字面值里的'\0'字符
初始化到字符数组里
字符数组里字符串内容可以修改

在printf函数调用语句里使用%s做占位符可以
把字符串里所有有效字符显示在屏幕上

不可以使用操作符对字符串进行操作,应该
使用一组标准函数
为了使用这组标准函数需要包含string.h头文件
strlen 用来统计字符串里有效字符
的个数
和sizeof关键字完全不同
strcat 用来把两个字符串合并成
一个字符串
这个函数有可能修改不属于
数组的存储区,这会造成
严重错误
strncat 功能和strcat函数类似
这个函数可以避免strcat的
错误
strcmp 用来比较两个字符串的大小
根据字符ASCII码比较两个
字符串的大小
返回值是0表示两个字符串
一样大
返回值是1表示第一个参数
代表的字符串大
返回值是-1表示第二个参数
代表的字符串大
strncmp 用来比较两个字符串前n个
字符的大小
strcpy 用来把一个字符串的内容
复制到字符数组里
这个函数也可能修改不
属于数组的存储区,
这会造成严重错误
strncpy 功能和strcpy类似
只复制字符串里前n个字符,
这样可以避免问题
有可能不复制'\0'字符
memset 用来把字符数组里多个
连续的字符类型存储区
内容设置成同一个字符
strstr 从一个大字符串里查找
小字符串的位置
如果找不到就返回NULL

以下两个函数不需要包含string.h头文件
sprintf 把多个数字按照格式拼凑成
字符串并记录到字符数组里
sscanf 从字符串里获得多个数字并记录
到存储区里

以下两个函数需要包含stdlib.h头文件
这两个函数可以把字符串里的数字转换
成数字类型
atoi 这个函数可以把字符串里开头
的整数部分转换成整数类型
atof 这个函数可以把字符串里开头
的浮点数部分转换成双精度
浮点类型

在scanf函数调用语句里使用%s做占位符
可以把用户在键盘上输入的字符串记录
到字符数组里
这种方法有可能造成严重问题

fgets函数也可以把键盘上输入的字符串
记录到字符数组里
这个函数可以避免scanf函数的问题
这个函数需要三个参数
1.数组名称
2.数组里的存储区个数
3.用stdin表示键盘

如果用户输入的内容不能把数组充满就把
用户最后输入的回车当作'\n'字符也
放到字符数组里
如果用户输入的内容超过数组的范围就把
多余的部分留在输入缓冲区里等
下次读

在每次使用fgets函数从键盘得到字符串以后
都应该把可能存在的多余数据清理掉
清理多余数据的语句应该放在分支里,分支
要保证输入缓冲区里有多余数据的时候
才进行清理

预习:
1.字符串
2.宏
3.条件编译
4.多文件编程

--day12--
指针数组里的每个存储区是一个指针类型
的存储区
字符指针数组里包含多个字符类型指针,其中
每个指针可以表示一个字符串
字符指针数组可以用来表示多个相关字符串

主函数的第二个参数是一个字符指针数组,
其中每个指针代表一个字符串,所有
这些字符串的内容都来自于用户的命令
主函数的第一个参数是一个整数,它表示
第二个参数里的指针个数

#define预处理指令可以用来定义宏

宏可以用来给数字起名字
定义宏的时候要把宏名称写在#define预处理
指令后,宏名称后写它所代表的数字
宏名称通常由大写英文字母构成
宏名称里不可以包含空格
用宏给数字起名字的时候不可以使用赋值
操作符
可以在程序里使用宏名称代表它所对应的数字,
编译器会把程序里的所有宏名称替换成
它所代表的数字

可以在编译命令里使用-D选项临时指定
宏所代表的数字

宏还可以给一个计算公式起名字
计算公式里包含未知数字,宏的参数用来
表示这些未知数字

编译器采用二次替换的方式处理带参数的宏

宏的参数不一定代表数字,所以它没有类型
如果宏有多个参数就需要用逗号把他们分开

宏不可以使用自己的存储区和函数进行数据
传递
宏没有形式参数也没有用来存放返回值的
存储区

能当作数字使用的宏必须编写成一个表达式
(因为宏没有用来记录返回值的存储区)

宏的参数直接代表函数的存储区,在宏里对
参数内容的修改可以直接影响函数

因为宏没有用来记录返回值的存储区,所以
不能保证优先计算宏里面的操作符
所有能当作数字使用的宏必须写在一对小括号
里面

宏没有形式参数所以不能保证优先计算参数
里面的操作符
编写宏的时候所有能当做数字使用的参数也都
必须写在小括号里面

不要把自增或自减的结果作为宏的参数使用

编写宏的时候可以使用一些特殊的符号,它们
叫做宏操作符

#是一个宏操作符,它可以把宏的参数转换
成字符串字面值
##也是一个宏操作符,它可以把一个代表
标识符的参数和其他内容连接得到
一个新的标识符

条件编译可以在编译的时候从几组语句里
选择一组编译而忽略其他组
#ifdef/#ifndef...#else...#endif
以上结构可以根据一个宏名称是否被定义过
从两组语句中选择一组编译
最开始的预处理指令应该从两个里选择一个,
它们的后面都要跟着一个宏名称
如果选择#ifdef就表示它后面的宏名称被定义
过就编译前一组语句,否则编译后一组
语句
如果选择#ifndef就刚好相反

#if...#elif(任意多次)...#else...#endif
这个结构也可以实现条件编译,它可以根据
任意逻辑表达式从多组语句中选择一组
编译

预习:
1.多文件编程
2.结构体

--day13--
多文件编程时一个文件里可以包含多个函数,
一个函数只能属于一个文件

多文件编程的步骤
1.把所有函数分散在多个不同的源文件里
(主函数通常单独占一个文件)
2.为每个源文件编写一个配对的以.h作为
扩展名的头文件(主函数所在的源文件
不需要配对的头文件).不分配内存的内容
都可以写在头文件里,头文件里至少要
包含配对源文件里所有函数的声明。
3.在所有源文件里使用#include预处理指令
包含需要的头文件(配对头文件是一种
需要的头文件,如果源文件里使用了
头文件里声明的函数则这个头文件也是
需要的头文件)

在gcc命令后列出所有源文件的路径就可以编译
多文件程序

可以把多文件程序的编译过程记录在Makefile
文件里,然后使用make工具完成编译过程

头文件的内容应该包含在条件编译的预处理
指令中,这样可以避免重复编译
头文件里第一条预处理指令应该是#ifndef

头文件里采用的宏名称应该是根据头文件的
路径变化得到的

从一个源文件里使用另外一个源文件里声明的
全局变量时需要使用extern关键字再次声明
这个全局变量

使用extern关键字声明变量的语句通常应该放在
头文件里

不可以跨文件使用静态全局变量

C语言里可以在一个存储区里记录多个相关
数字
这种存储区的类型叫结构体,这种类型需要
编写程序创建出来
结构体存储区里包含多个子存储区,每个子
存储区可以记录一个数字
结构体的不同子存储区类型可以不同,子存储区
类型也可以是结构体类型
结构体声明语句可以用来创建结构体类型
结构体声明语句里需要使用struct关键字

结构体声明语句里包含多个变量声明语句,它们
叫做结构体的成员变量。每个成员变量
代表一个子存储区。
所有成员变量声明语句都没有分配存储区,
它们只是用来代表子存储区的类型和名称
C语言里结构体不可以包含函数
结构体声明语句可以写在头文件里
可以把结构体作为类型声明变量,这种变量
叫结构体变量
把结构体作为类型的时候需要把struct关键字
和结构体名称一起作为类型名称使用
结构体变量被分配了内存,可以用来记录数字

typedef关键字可以给现有的类型名称起别名,
别名可以代替原来的类型名称使用
结构体类型通常需要起别名

可以把声明结构体类型的语句和起别名的语句
合并成一条语句
这个时候可以省略结构体本身的名称

结构体变量也应该初始化
结构体变量的初始化方法和数组的初始化
方法一样

结构体变量通常不能作为整体使用,一般
一次只使用其中的某个子存储区
可以采用如下写法表示结构体的某个子存储区
prsn.age
其中prsn是结构体变量名称,age是某个
成员变量的名称

同类型的结构体变量之间可以直接赋值

和结构体存储区捆绑的指针叫结构体指针
可以采用如下写法通过结构体指针表示结构体
的子存储区
p_person->age
其中p_person代表一个已经捆绑好的结构体指针,
age代表成员变量名称

结构体类型的形式参数可以从调用函数向被调用
函数传递结构体数据
使用结构体类型的形式参数有可能造成时间
和空间的浪费
采用结构体指针作为形式参数可以避免这种
浪费
结构体指针形式参数尽量用const关键字声明

可以使用结构体变量做返回值从被调用函数
向调用函数传递数据
这个时候被调用函数就需要提供一个结构体
类型的存储区用来存放返回值
这更容易造成时间和空间的浪费
采用结构体存储区的地址做返回值可以避免
这种浪费(这个时候被调用函数需要
提供一个结构体指针类型的存储区
用来存放返回值)
不可以把非静态局部结构体存储区的地址
当返回值使用

预习:
1.数据对齐和补齐
2.枚举和联合
3.二级指针
4.函数指针
5.回调函数
6.动态内存分配

--day14--
一个存储区的地址必须是它自身大小的整数倍
(double类型存储区的地址只需要是4的
整数倍)
这个规则叫数据对齐
结构体里面的子存储区通常也需要遵守数据
对齐的规则
数据对齐会造成结构体内部子存储区之间
有空隙

结构体存储区的大小必须是它所包含的基本类型
存储区中占地最大类型存储区大小的整数倍
(如果这个基本类型是double类型则结构体
存储区的大小只需要是4的整数倍)
这个规则叫数据补齐
数据补齐可能在结构体最后增加一些浪费的
字节

枚举有可以用来创建新的类型
枚举类型存储区就是整数类型存储区,枚举
类型存储区里应该只能存放有限的几个整数
枚举类型也需要先声明然后才能使用,声明
的时候需要使用enum关键字
声明枚举类型的时候需要提供一组名称,计算机
为每个名称分配一个对应的整数,枚举
类型存储区里只能存放这些整数
不同枚举类型所能记录的整数范围不同
计算机把从0开始连续的非负数分配给枚举类型
里的名称
可以在声明枚举类型的时候指定为某个名称
分配的整数,这个名称后面的名称对应的
整数也会发生变化

联合也可以用来创建新的数据类型
联合也需要先声明然后再使用,声明联合的时候
需要使用union关键字
联合成员变量所占的存储区是互相重叠的
联合所有成员变量的地址都是一样的
联合存储区可以当作多种不同类型的存储区
使用,每个成员变量代表了一种可能的
类型
联合存储区的大小就是最大成员变量的大小

用来记录普通变量地址的指针叫做一级指针
二级指针可以记录一级指针的地址,通过它
可以找到捆绑的一级指针
声明二级指针时需要在指针变量名称前加**

二级指针变量名称前加**可以表示捆绑
的普通变量存储区
二级指针变量名称前加*可以表示捆绑
的一级指针存储区

二级指针可以代表指针数组但是不能代表
二维数组

无类型指针有可能记录一级指针的地址,这个
时候必须把这个指针强制类型转换二级
指针然后再使用

二级指针通常作为形式参数使用,使用二级
指针形式参数可以让被调用函数向调用
函数传递一个地址数据

C语言里函数也有地址
函数名称可以用来表示函数的地址
函数指针可以用来记录函数的地址
函数指针也需要先声明然后再使用
函数指针的声明可以根据函数声明变化得到

函数指针也分类型,不同格式的函数适合
与不同类型的函数指针捆绑
函数指针可以用来调用函数

函数指针可以作为形式参数使用
会作为实际参数使用的函数叫回调函数

可以在程序运行的时候临时决定需要分配多少
存储区
这种分配内存的方法叫动态内存分配
为了管理动态分配内存需要使用一组标准函数
为了使用这些标准函数需要包含stdlib.h头文件

malloc函数可以动态分配一组连续的字节
这个函数需要一个整数类型的参数表示希望分配
的字节个数
它的返回值表示分配好的第一个字节的地址
如果失败则返回值是NULL
函数的返回值记录在一个无类型指针里,必须
首先强制类型转换成有类型指针然后才能
使用

动态分配内存使用完以后必须还给计算机,否则
会造成内存泄漏问题
free函数可以用来释放动态分配内存
这个函数需要分配好的第一个字节的地址作为
参数
一起分配的内存必须一起释放
如果用指针做参数调用free函数则函数结束后
指针成为野指针,必须恢复成空指针

预习:
1.文件操作

--day15--
调用函数可以使用被调用函数动态分配的
存储区

calloc函数也可以动态分配一组连续的
存储区
这个函数可以把所有动态分配的存储区
内容设置成0
为了使用这个函数也需要包含stdlib.h头文件
这个函数需要两个参数,第一个参数表示要
分配的存储区个数,第二个参数表示单个
存储区的大小
这个函数的返回值也是分配好的第一个存储区
的地址
这个函数也可能失败,如果失败则返回NULL

realloc函数可以调整一段动态分配内存中
的存储区个数
尽量少使用这个函数

所有文件都采用二进制的方式记录数字
如果文件里的所有二进制数据都来自于字符
则这种文件叫文本文件
文本文件以外的文件都叫做二进制文件

C语言里提供了两种操作文件的方法,一种
方法只能操作文本文件,另外一种方法
可以操作所有文件
第一种操作文件的方式叫文本方式,第二种
操作文件的方式叫二进制方式

文件操作基本步骤
1.打开文件(fopen)
2.操作文件(fread/fwrite)
3.关闭文件(fclose)

fopen函数需要两个参数
1.代表要打开的文件路径
2.代表打开文件的方式(决定
程序里可以对文件做什么操作)

打开方式有如下选择
"r" 只能察看文件内容不可以修改
只能从文件头开始察看
如果文件不存在则打开会失败
"r+" 比"r"多了修改功能
"w" 只能修改文件内容不能察看
只能从文件头开始修改
如果文件不存在就创建文件
如果文件存在就删除文件里的所有
内容
"w+" 比"w"多了察看功能
"a" 只能修改不能察看
只能在文件末尾追加新内容
如果文件不存在就创建文件
如果文件存在不会修改文件的
原有内容
"a+" 比"a"多了察看功能

"b"也是一种打开方式
他可以和前面的任何一种打开方式混合使用
如果程序里采用二进制方式操作文件就
应该使用这个打开方式

fopen函数返回的是一个地址,应该记录在
文件指针里。
程序里只能用文件指针代表打开的文件
fopen函数有可能失败,如果失败则返回值
是NULL

一旦完成对文件的所有操作后必须使用fclose
函数关闭文件
fclose函数需要文件指针作为参数
fclose函数结束后文件指针成为野指针,必须
恢复成空指针

文件操作分两种
1.把内存里一组连续存储区的内容拷贝到
文件里(写文件操作)
2.把文件里一组连续存储区的内容拷贝到
内存里(读文件操作)

fread函数可以采用二进制方式对文件进行读
操作
fwrite函数可以采用二进制方式对文件进行
写操作

这两个函数都需要四个参数
1.内存里第一个存储区的地址
2.单个存储区的大小
3.希望操作的存储区个数
4.文件指针

它们的返回值表示实际操作的存储区个数

以下两个函数以文本方式操作文件

fprintf函数可以把数据按照规定的格式记录到
文本文件里
fprintf函数的第一个参数是一个文件指针,
后面的参数就是printf函数的参数

fscanf函数可以从文本文件里获得数字并记录
到存储区里
这个函数的第一个参数是一个文件指针,后面的
参数就是scanf函数的参数

预习:
1.位置指针
2.数据结构和算法

标准C 语言总结的更多相关文章

  1. 关于标准C语言的预定义宏【转】

    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来. __LINE__  当 ...

  2. 【部分原创】标准C语言的优先级、结合性、求值顺序、未定义行为和非确定行为浅析

    零. 优先级    在C++ Primer一书中,对于运算符的优先级是这样描述的:     Precedence specifies how the operands are grouped. It ...

  3. 标准SQL语言的用法

    原文链接:http://www.ifyao.com/2015/05/18/%E6%A0%87%E5%87%86%E7%9A%84sql%E8%AF%AD%E8%A8%80%E4%BD%BF%E7%94 ...

  4. 关于标准C语言的预定义宏

    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来.__LINE__  当前 ...

  5. UML标准建模语言与应用实例

    一.基本信息 标题:UML标准建模语言与应用实例 时间:2012 出版源:科技创新导报 领域分类:UML标准建模语言 面向对象 系统分析与设计 二.研究背景 问题定义:UML建模语言用图形来表现典型的 ...

  6. UML(统一建模语言)是通用的可视化标准建模语言。由构造块、公共机制、构架三部分组成。

    UML UML(统一建模语言)是通用的可视化标准建模语言.由构造块.公共机制.构架三部分组成. 1.构造块:包括基本的UML建模元素(类.接口.用例等).关系(关联关系.依赖关系.泛化关系.实现关系) ...

  7. 标准C语言(1)

    C语言程序的绝大部分内容应该记录在以.c作为扩展名的文件里,这种文件叫源文件,C语言里还包含以.h作为扩展名的文件,这种文件叫做头文件 C语言程序里可以直接使用数字和加减乘除四则运算符号(*代表乘法, ...

  8. 【M35】让自己习惯于标准C++语言

    1.最近一些年C++语言增加的特性有: a.RTTI,namespace,bool,关键字mutable和explicit,enums,以及const static int可以直接初始化. b.扩充了 ...

  9. 标准C语言的输入输出流(i/o)方法详解

    cppreference.com -> 标准 C I/O ->详细说明 标准 C I/O clearerr 语法: #include <stdio.h> void cleare ...

随机推荐

  1. Bing Maps进阶系列六:使用Silverlight剪切(Clip)特性实现Bing Maps的迷你小地图

    Bing Maps进阶系列六:使用Silverlight剪切(Clip)特性实现Bing Maps的迷你小地图 Bing Maps Silverlight Control虽然为我们提供了简洁.方面的开 ...

  2. Tool:安全狗

    ylbtech-Tool:安全狗 安全狗,互联网安全品牌,云安全服务与解决方案提供商 .企业用户遍布互联网金融.电商.游戏.移动互联网.政府单位等多个行业. 1.返回顶部 1.   2. 2.返回顶部 ...

  3. ORACLE数据删除数据删除的解决办法

    今天主要以oracle数据库为例,介绍关于表中数据删除的解决办法.(不考虑全库备份和利用归档日志)删除表中数据有三种方法:·delete(删除一条记录)·drop或truncate删除表格中数据 1. ...

  4. Android基础整理

     1.使用Debug方式调试程序 2.使用LogCat方式调试程序  3.使用Toast动态显示信息 4.使用AlertDialog实现提示框.. 5.使用OptionsMenu实现选项菜单

  5. codevs1690 开关灯(线段树)

    1690 开关灯 USACO  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description YYX家门前的街上有N(2< ...

  6. [Swift通天遁地]七、数据与安全-(10)文件的加密压缩和解压加密压缩

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  7. Django day25 序列化组件(*****)

    序列化:将变量从内存中存储或传输的过程称之为序列化 1.序列化组件是干什么用的? 对应着表,写序列化的类 2.如何使用序列化组件 Serializer 1) 重命名:用source:xx = seri ...

  8. 微信小程序的wxml文件和wxss文件在webstrom的支持

    webstrom默认不支持wxml文件和wxss文件,所以要进入设置里面手动添加支持. 对wxml文件的支持: 文件 -> 设置 -> 编辑器 -> 文件类型, 然后选择XML文件, ...

  9. 在3D中两条射线的相交性检测

    摘自[3D数学基础: 图形与游戏开发] 考虑在3D中两条以参数形式定义的射线: \(\vec{r_1}(t_1)=\vec{p_1}+t_1\vec{d_1}\) \(\vec{r_2}(t_2)=\ ...

  10. python网络爬虫数据中的三种数据解析方式

    一.正则解析 常用正则表达式回顾: 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线 ...