深入理解计算机系统
存储器层次
CPU主频: 3.2 GHz
高速缓存(1~10ns, 一个周期)
主存(10~100ns)
辅助(磁盘) (1byte/10ms, 一次可以传送大量字节, 几十到几百个周期)
三级存储(分钟为单位)
虚拟存储
虚拟页(VP), 物理页(PA), 页表(Page Table), 页表条目(PTE, Page Table Entry), DRAM(虚拟存储器缓存), SRAM(CPU和主存的缓存), MMU(存储器管理单元),
路旁转换缓冲(TLB, Translation Lookaside Buffer)
东芝satalite L700笔记本进入BIOS(ctrl + alt + del 之后F12)
Ubuntu 15.10可能不适配NVDIA显卡(如: NVDIA GeFore GTX 745)
Day01
C语言程序的绝大部分必须记录在以.c作为扩展名的文件里,这种文件叫源文件
C语言程序里可以直接使用加减乘除四则运算
符号(+、-、*、/)
每个独立的计算步骤最后必须使用分毫结束,用分号结束的一个计算步骤叫一条语句
任何C语言程序一个由大量的语句构成
C语言程序中,采用分组的方式管理所有的语句
一组里的所有语句必须写在一对大括号里
可以吧一组里面的语句再次进行分组
绝大多数语句必须属于某个分组
任何语句不可以跨越分组
不被其他大括号包含的大括号可以叫做顶级大括号
顶级大括号可以用来表示函数(可以吧函数看成一组语句)
每个函数必须有自己的名字,不用的函数的名字必须不同
任何C语言程序一对由一个活多个函数构成
C语言程序中必须有一个叫做main的函数,这个函数叫做主函数
C语言程序必须从主函数的第一条语句开始执行
当主函数的最后一条语句结束的时候整个程序结束
C语言程序允许一个函数的结束的时候遗留一个数字,这个数字叫做这个函数是返回值
主函数需要有一个返回值,这个返回值表示主函数的工作结果。如果这个返回值是0,则表示一切正常,否则就表示出现非正常情况。
C语言程序里预留了几十个英文单词,这些英文单词叫做关键字。每一个关键字有特定的用途,不能随便使用。
Return就是一个关键字,它有两个用途。主要用途是结束函数的执行(任何时候一定会起到这个作用),辅助作用是用来指定返回值数值(当关键字后面有数字时起这个作用)
根据数字在某个方面的区别把数字分成几组,每组叫做一个数据类型
每个数据类型有自己的名字
整数类型是一种数据类型,它的名字是int,它里面包含几乎所有不带小数点的数字程序中所有数字必须有类型
C语言程序中所有不带小数点的数字默认是整数类型
每个函数必须明确表示它返回值的类型(把返回值类型名称写在函数名称前面)
C语言程序基本开发步骤:
1、使用vi编写以.c作为扩展名的源文件
2、使用gcc工具对源文件进行翻译得到名为a.out的文件(编译)
3、用命令./a.out执行得到的文件
能够完成编译工作的软件叫编译器
不同编程语言有自己的编译器
Gcc是c语言的一种编译器
MinGW软件是windows里的gcc
所有C语言程序中都会包含预处理指令
预处理指令全都是以# 作开头,而且不是以;作结尾
标准C阶段遇到的预处理指令都可以把源文件内容改变成其他内容
#include 是一个预处理指令,它可以把其他文件内容合并到当前源文件中
使用这个预处理指令的适合需要指定文件路径,这个路径对应的文件会被包含到当前源文件中
这个路径通常采用相对路径:
如果把路径写在< > 中间表示相对路径的起点是系统预先设定好的一下目录
如果把路径写在“”中间表示相对路径的起点还包括当前源文件所在的目录gcc 工作步骤:
1、先处理所有预处理指令
2、把修改后源文件内容翻译成计算机认识的格式(也叫编译)
3、把编译得到的不同部分合并在一起(链接)
gcc 的选项:
-E 只完成预处理指令的处理工作
-c 只完成预处理和编译工作
-o 用来指定新文件名称
-std=c89/-std=c99 用来指定编译过程中遵循的版本(缺省情况下采用c89版本)
程序中的文字信息必须加入到注释的区域里,编译器会忽略所有注释
以// 做开头一直到行尾的区域叫单行注释
以/* 做开头,以*/ 做结尾的区域叫多行注释
C语言程序中大量使用名称区分不同内容,这些名称叫做标识符
标识符最好采用有意义的英文单词编写
标识符命名规则:
1、第一个字母只能是英文字母或者下划线
2、后面的字母可以是英文字母、下划线或者阿拉伯数字字符
3、标识符中大小写不同的字符被看作是不同的字符(大小写敏感)
4、关键字不可以当做标识符使用
5、标识符长度没有限制,但计算机只会截取前一段使用(c89规范中截取前31个
字符,c99规范里截取前63个字符)
C语言书写规范:
1、一行中最多包含一条语句
2、不同层次的语句要使用缩进区分开
3、在合适的地方使用空格和空行提高程序的可读性
4、标识符采用驼峰方式(区分大小写XiAn)或者下划线(xi-an)方式编写
C语言中提供了一组标准函数,每个函数负责解决一个常见问题
每个标准函数都有自己是名字
在程序中编写函数调用语句就可以使用某个函数了
printf 是一个标准函数的名字,这个标准函数可以把程序中的数字打印在终端窗口里;为了使用这个标准函数需要包含stdio.h 文件。
在printf函数调用语句中使用占用符可以把双引号里面的某个位置保留下来,在打印的适合先用某个数字填充这个位置然后再打印
使用占位符可以打印编写程序时还不知道的数字
不同类型的数字应该和不同的占位符配合使用
和整数类型配合使用的占位符是%d
可以在一条函数调用语句中使用多个占位符,有多少个占位符就应该在双引号后面提供多少个数字,数字之间使用逗号分开
计算机内存分成很多字节,任意两个的大小一样
每个字节可以用来存放一个数字。
可以临时把几个相邻的字节合并用来记录一个数字
我们可以把内存中用来记录一个数字的区域叫做一个存储区(一个存储区一定是由一个或多个相邻字节构成的)
每个字节有一个编号,这个编号叫做这个字节的地址
所有字节的地址从0开始逐渐递增
只有通过地址才能找到字节
一个存储区也有地址,它的地址是它所包含的字节中最前边的字节的地址
C语言中可以使用变量代表一个存储区,这一可以简化对存储区的使用
一个存储区只能用来存储一种类型的数字,因此存储区是分类型的(变量也是)计算机可以根据变量计算出对应存储区的地址(变量可以代表存储区的原因)
变量和存储区的对应关系完全由计算机决定
为了在程序中使用一个变量必须首先声明它,变量声明语句用来声明变量
变量声明语句会让计算机为变量分配一个存储区
变量声明语句中不用包含变量的类型和名称
变量的使用方法:
1、变量可以用来存储一个数字
2、从变量中获得数字并进行计算
变量赋值语句可以向变量中存放一个数字
赋值语句需要采用赋值操作符(=)编写
赋值操作符要求左边必须是一个能代表存储区的内容(左值)
赋值操作符要求右边必须是一个能代表数字的内容
赋值语句执行完成后可以把右边的数字记录在左边的存储区里
只要在程序中把代表存储区的内容当作数字使用,计算机就会先从存储区里获得数字,然后再使用
变量名称在程序中既可以带便存储区,也可以代表存储区的数字(num = num)
变量名称在程序中代表什么是由环境决定的
预习:
1变量2、scanf标准函数 3 数据类型
作业:
1、假设有1克到127克之间的127个不同的整数重量,要求设计一套砝码表示其中任何一个整数重量。(同样重量的砝码不能重复,砝码数量越少越好)
1 2 4 8 16 …
Day01—day02 总结:
whoami 查看当前使用的账号
clear 清除终端窗口里的文字信息
pwd 查看当前目录
cd cd~
ls ls -l ls -a ls -la
touch 创建新文件
mkdir 创建新目录
mkdir -p qwe/asd 两个目录一起创建出来
rm rm -rf
Tab键补齐
tar zcvf 压缩文件名.tar.gz 路径1 路径2 打包压缩
tar zxvf 压缩文件名.tar.gz 解包解压nyy (n为整数,如果是1可省略) 拷贝n行(必须在正常模式下)np 粘贴n次(必须在正常模式下)ndd 剪切n行(必须在正常模式下)set nu set nonu
vi ~/.vimrc 查看set命令(每次vi启动时,都会从~/.vimrc文件中获得大量set命令并按顺序执行它们)
chmod u+x(g+w / o-r) user/group/other
chmod 664(二进制后转的十进制数) 文件路径修改操作属性
mv 路径1 路径2 移动(覆盖)(也可以用来改名)
cp 路径1 路径2 拷贝(复制)
ln -s 路径1 路径2(可以不存在,新建) 链接(等同操作) echo abc > a.txt (重定义输出) (abc 覆盖 a.txt)
echo abc >> a.txt (追加) (abc 加在 a.txt 后) ps (-aux 系统所有进程) 查看当前窗口进程
kill (-9强制结束) 234(id号) 结束进程
ctrl + c 结束进程(相当于kill -2 自动寻找死循环) echo abc>a.txt 重定义输出
echo abc>>a.txt 追加
通配符:? (a?) 代表a_
* (a*) 代表以a开头的
gcc -E 只完成预处理指令的处理工作(编译)
gcc -c 只完成预处理和编译
gcc -o 用来指定新文件名称
-std=c89/-std=c99 用来指定编译过程中遵循的版本(缺省时采用
c89版本)
Day03:
可以在一条语句中声明多个同类型变量,这个时候类型名称写一次就行了
可以在声明变量的语句中立刻对变量进行赋值,这叫做变量的初始化
C语言里所有变量都应该初始化
变量可以用来在程序中代表一个未知的固定数字
变量可以用来代表一组相关数字(任何时候只使用其中某一个数字,使用过后就不再使用了)
在printf() “”中用%%,才会打印出% ;
Scanf()
如果scanf函数调用语句的双引号里有不是占位符的内容,则用户必须在输入的时候把它们按照顺序依次输入,否则计算机就无法得到数字
如果多次从键盘得到数字时某一次用户输入的格式错误则后面的所有输入都可能会错误
清理缓存区(有时前面输入错误,后面会都出错,清理缓存后就好了)Scanf(“%*[^\n]”);
Scanf(“%*c”);
scanf(“%*[^\n]”); scanf(“%*c”);
字符类型是一种数据类型,名称是char
这个类型中一个包含256个不同的数据,每个数据可以代表一个字符(‘%’‘#’)ASCII码表中记录所有256个数据两种表示方式之间的对应关系
‘a’97
‘A’65
‘0’48
所有字符数据分成两组,每组128个字符
其中一组里所有字符数据两种表示方式之间的对应关系在所有计算机上都一样(这组字符的整数表示方式范围从0到127)
另外一组中所有字符数据两种表示方式之间的对应关系在计算机上有可能不同(这组字符的整数表示方式范围从-128到-1,也有可能从128到255)
无符号字符类型也是一种数据类型
无符号字符类型用unsigned char 表示
这个数据类型里同样包含那256个不同的字符,所有的字符数据的整数表示方式范围固定从0到255)
ASCII码表中所有小型英文字符的整数表示方式是连续排列的,‘a’的整数表示方式最小
所有大写英文字母和阿拉伯数字字符也都符合这个规律
‘t’-‘a’=‘T’-‘A’
‘3’-‘0’= 3 - 0 =‘d’-‘a’
Short %hd
Unsigned short %hu
Long %ld
Unsigned long %lu
Int %d
Unsigned int %u
Float %f或者%g
Double %lf或者%lg
%lf和%f 会保留小数后面无效的零
%nd 和%-nd
%0nd也可以做站位符,(n同样代表一个整数)打印n个位子,无效位置用‘0’%n,mf作浮点占位符,共n个位置,小数点占m位
不同数据类型之间的区别是有它们是存储区所包含的字节个数不同造成的
Sizeof关键字可以用来计算一个变量或数据的存储区所占的字节个数
各种数据类型所包含的字节个数:
char(unsigned char) 1个字节
short(unsigned short) 2个字节
long(unsifned long) 4 个字节
int(unsigned int) 4个字节
float 4个字节
double 8个字节
Sizeof 关键字的小括号里可以写任何能当作数字使用的内容(赋值语句也可以当作数字)
Sizeof关键字的小括号里如果修改了任何存储区的内容则这种修改不会真正生效(如:sizeof(num = 10) 不会真正赋值)
计算机采用二进制表示数字,二进制里每个数位上只有0或1者两种可能
计算机里每个字节分成八段,每段可以用来记录一个0或者1
数字的二进制表示方式中每个数位有一行编号,最右边数位的编号是0,向左依次递增
二进制中每个数位上的1单独代表一个数字,它的数值就是2的编号次方
一个二进制所代表的数值就是他里边所有数位上的1所代表的数值之和
二进制加一是计算规则是吧最右边的0变成1,把它右边的所有1都变成0
二进制转十进制方式:把所有1单独转换最后把转换结果求和
0111 0011 = 1 + 2 + 16 +32 +64 =115
预习:1二进制(八进制十六进制,负数的二进制)
2操作符
作业:1编写程序计算给定长和宽的长方形的面积
2编写程序计算给定半径的元的周长
扩展:
crontab ( 任务调度)
crontab –l 查看任务调度
crontab –e 修改任务调度
可执行的shell 脚本
vi abc.sh
mkdir shell
cd shell
touch a.txt
ls –l abc.sh (查看脚本问价操作属性)
chmod 777 abc.sh (修改脚本操作属性,使其能被运行)
./abc.sh 执行脚本,从而运行里面步骤
远程操作别id的电脑(有对方ip和密码)(ftp 也可以)
telnet + ip(远程连接)
/sbin/ifconfig 查看本地ip
Ipconfig 在windows下查看ip
退出:exit(正常进入)
Quit(不正常进入)
服务器下:ftp 192.168.0.243
xly
xly
下载:gat 文件
上传:put 文件
退出:bye
Day04
十进制转二进制两种方法:
第一种,首先把十进制表示方法拆分成多个2的整数次方值和,然后把所有拆分结果单独转换成二进制,最后把所有转换结果合并就得到证个数字的二进制
57 = 32 + 16 + 8 + 1 = 0010 0000 + 0001 0000 +0000 1000 + 0000 0001
= 0011 1001
第二种是不断除以2取余,把所有余数按照从后向前的顺序书写得到转换结果
83 **** ***1
41 0*** ***1
20 00** ***0
10 000* ***0
5 0000 ***1
2 0000 0**0
1 0000 00*1
0 0000 0000
113/2 = 56/2 = 28/2 = 14/2 = 7/2 = 3/2 = 1/2 = 0
1000 1110 0111 0001
通过上述方法计算得到的二进制叫做源码
计算机里采用补码计算数字
非负数的源码和补码是一样的
八进制也是一种表示数字的方式(可以看成是二进制的简写方式)
把二进制的补码从有向左每三个数位分成一组,把每一组用0到7之间的数字替换得到结果就是八进制表示方法
0101 0111 01 010 111 127
4分3分八进制
可以直接在程序中使用八进制方式表示数字,但是必须在数字前写一个0
采用%o 做占位符可以把一个数字的八进制表示方式打印在屏幕上
十六进制也是一种表示数字的方法(也可以看成是二进制的简写方式)
把二进制补码中所有数位从右向左每四个数位分成一组,每组用一字字符替代得到的结果就是十六进制表示方式
如果某一组的转换结果在0到9之间则使用对应的阿拉伯数字字符替换,如果在10到15之间则使用‘a’到‘f’替换。
0010 1101 2d(十六进制)
可以在程序中使用十六进制的方式表示数字,但是必须在前面写上0x
采用%x 或者%X 可以把一个数字的十六进制表示方式打印在屏幕上
-5
0 – 5 0000 0000 – 0000 0101
1 0000 0000 – 0000 0101
=1111 1111 + 1 – 0000 0101
=1111 1111 -0000 0101 + 1
=1111 1010 + 1
=1111 1011
负数二进制补码计算方法:
1计算出负数相反数的补码
2把第一步的结果中每个数位变成相反数值,然后在加一
这种方法得到的结果直接是二进制补码
无符号类型的二进制补码一定是非负数
有符号类型的二进制最左边的数位可以用来盘点正负,如果是0则是非负数,如果是1则是负数
这个数位叫做符号位
不能直接把符号位替换成正负号
所有有符号类型中有一个特殊的二进制补码,它最左边的数位是1右边全是0,这个补码用来表示这个数据类型中最小的负数
当吧一个占地大的整数类型数据赋值给以个占地小的整数类型存储区的时候,计算机会保持二进制内容不变(会丢失一些数据)
当把一个占地小的整数类型数据赋值给一个占地大的整数类型存储区时会扩充二进制数位。原有的数字是有符号的,则扩充出来的二进制数位全是符号位。如果原有数字是无符号的,则扩充出来的二进制数位都是0
C语言程序中使用加减乘除
C语言中使用%表示区余操作、
,在C语言中可以做为操作符使用,它的左右和写一个能当数字使用的内容使用这个操作符编写的表达式可以当数字使用,这个数字就是逗号操作符后面的那个数字
逗号操作符的优先级非常低,甚至比赋值操作符优先级都低
赋值操作符(=)可以把一个数字放在一个存储区里
赋值操作符左边必须是一个能代表存储区的内容(左值)
赋值操作符右边必须是可以当数字使用的内容
赋值操作符的优先级非常低,但是比逗号操作符高
使用赋值操作符编写的赋值语句可以当作数字使用,这个数字就是赋值完成后的右边的存储区里的数字
一条语句中可以包含多个赋操作符,它们的计算顺序是先右后左
只需要一个数字就可以配合使用的操作符叫单目操作符
需要两个数字配合使用的操作符叫双目操作符
需要三个数字配合使用的操作符叫三目操作符
绝大多数双目操作符可以和赋值操作符合并形成赋值操作符(+= -= %=)
符合赋值操作符要求左边是能代表存储区的内容,有边是能当数字使用的内容
复合赋值操作符也是爽目操作符
所有复合赋值操作符的优先级都和赋值操作符的优先级一样低
自增++/自减--
它们是单目操作符,它们必须和一个存储区配合使用
这两个操作符都可以采用前操作方式或后操作方式使用(i++ ++i)
不用在一条语句中队同一个变量多次进行自增自减计算,因为结果不确定
布尔类型数据只包含两个数值,分别是真(true)和假(false)
在C89规范中真用整数1表示,假用整数0表示
整数也可以作为布尔值使用,0作为布尔值使用时是假,其他整数作为布尔值使用时是真
逻辑操作符用来编写逻辑表达式,逻辑表达式的计算结果只能是布尔值
!是单目逻辑操作符,表示求反
双目逻辑操作符: <><=>===
双目逻辑操作符的优先级比算术操作符的优先级低
C语言中所有逻辑表达式必须由一个或多个简单逻辑表达式构成(最多包含以个双目逻辑操作符的表达式叫简单逻辑表达式)
&& 与|| 或
(!Gender && weight > (height - 110))
|| ( Gender && weight > (height - 105))
与(&&)和或(||)都具有短路特性(前面的逻辑表达式如果能决定整个表达式的结果则不会去考虑后面的内容)
作业:
1、编写程序从键盘上得到一个1到127之间的整数,把它转换成二进制并把转换结果打印在屏幕上(两种方法)
Day05
位操作符可以直接对字节中的二进制数位进行操作
~是以个单目位操作符,它可以把字节中所有二进制数位求反,叫求反操作符
求反操作符不会修改原有数字内容
双目为操作符包括按位与(&),按位或(|)以及按位异或(^)
以上双目操作符首先把两个数字转化二进制补码,然后把对应数位上的数字进行操作(不对应的数位之间不会互相影响)
按位与会把对应数位上的数字进行与计算
按位与可以用来把租借中某些二进制数位清0;
任何数位和0按位与后是0
任何数位和1按位与后还是他本身
‘a’65 0100 0001
‘A’97 0110 0001
Char ch;
Ch &= ~32 // ~0010 0000; //1101 1111
按位或把对应数位上的数字进行或计算(或0得本身,或1得1)
3 0000 0011
| 5 0000 0101
= 7 0000 0111
按位或可以把字节中某些二进制数位设置成1
按位异或把对应上的数字进行异或计算(异或0不变,异或1结果改变)
0 ^ 0 = 0 3 ^ 5 = 0000 0110
0 ^ 1 = 1 = 6
1 ^ 1 = 0
按位异或可以把某二进制数位求反
移位操作符也是双目操作符;可以把所有二进制数位上的数字统一向左或向有移动n个位置
左移操作使用<<表示右移操作使用>>表示
移位操作符左边的数字是要进行移位操作的数字,右边的数字是移动的位数
移位操作不会修改原有的数字
移位操作后一定会有些数字丢失,另外一些位置空出来
左移时右边空出的位置上一定补充0;
右移时有符号类型数据左边空出来的位置上一定补充符号位,无符号类型数据左边空出来的位置上一定补充0
在移动过程中如果没有丢失有效数据位,则左移n位相当于乘以2的n次方,右移除以。
取地址操作符(&)可以根据一个存储区计算出它的地址
这是一个单目操作符,它必须和一个存储区配合使用
使用%p做占位符把地址打印在屏幕上
地址方式都是以十六进制来写的
可以在地址数据前使用* 操作符获得地址对应的存储区
三目表达式可以根据一个布尔值从两个计算规则中选择一个作为最终结果
三目表达式格式:
布尔值?表达式1 :表达式2
如果布尔值是真则采用表达式1计算最终结果,如果是假则采用表达式2计算最终结果
不要把赋值操作符写在三目操作符的问号后面
如果一个表达式中多个数据的类型不同,则计算机会首先把它们转换成同一类型,然后在进行计算
这个转换过程完全由计算机完成,这个过程叫隐式类型转换
隐式类型转换过程中会把char ,short 都转换成double当不同类型占地大小不同时会把有符号类型转换成武符号类型,整数类型转换成浮点类型
在C语言程序中可以随时给一个数据指定新类型,者叫做强制类型转换
强制类型转换的实现方法是在数据前写一对小括号,小括号里写数据类型名称
强制类型转换不受规则约束,所以转换过程中有可能造成数据丢失
实现强制类型转换的时候计算机会分配一个新的存储区,这个存储区的类型是我们在小括号里指定的类型。计算机用原来的数据对这个存储区进行赋值,然后使用这个存储区里的内容进行计算
如果对一个存储区的内容做强制类型转换则转换过程不会修改原有存储区里的数字流程控制语句可以让程序中的语句不再从上到下执行
分支是一种流程控制语句,它可以从几组语句中选择一组执行而忽略其他组
使用if 关键字可以编写分支,在if 分支中可以使用一个逻辑表达式的结果控制一组语句是否要执行(括号为真执行,位假不执行)
如果有多个分支,在任何时候最多只会执行其中一个分支,则可以使用else关键字把它们合并
如果合并好的多个分支任何时候必然会执行其中一组,则可以把最后一组的逻辑表达式省略
合并好的分支中多个逻辑表达式之间有先后顺序,只有当前面的逻辑表达式为假才会考虑后面的逻辑表达式
可以利用者一点在合并多个分支的时候简化它们的逻辑表达式
已经合并好的分支不一定能当作多个无关分支理解
作业:1编写程序从用户提供的三个数中找出最大数并打印
2编写程序从键盘得到小时、分钟、秒,计算出下一秒的时间,并按照如下格式打印
Hh:mm:ss
Day06
Switch … case 语句也可以用来实现分支
如果一个分支中包含有限个整数,每个整数对应一组专门的语句,这种一般使用Switch … case语句
Switch …case语句中在大括号内部把所有整数都列举出来,每个整数对应的处理语句就可以卸载这个整数下面。每段必须用break;语句结束
在大括号里可以编写一组语句用来处理没有处理没有例句出来的数字,可以用default:来包括所有这些没有列举过的数字
循环也是一直流程控制语句,它可以让一组语句反复多次执行
For 关键字可以用来编写循环
在for关键字编写的循环中,可以采用一个变量代表一组相关数字,这个变量叫循环变量
在循环的大括号里可以使用break;语句随时终止循环的执行
Break;语句不会执行后循环变量也不会再改变
Continue;语句会直接跳转到循环大括号的末尾,中间的语句这次都不会执行(只结束这次循环,而不会像break那样结束掉整个循环)
Break;和continue;语句通常写在分支里
假设有如下的for循环语句
For(1;2;3){4}
它的执行顺序:【1、2】【4、3、2】【4、3、2】…【4、3、2】
第一组和其他所有组都不同
循环嵌套可以解决复杂的循环问题
首先把所有问题分组,为每组找一个代表数字使用一个循环描述所有组代表数字的变化过程在这个循环内部再写一个循环负责处理这一组内部的所有任务
内循环的开始数字和结束数字可能是不固定的,需要根据外循环的循环变量计算得到
作业:1编写程序打印99惩罚表
2假设一个面包店卖三种面包,重量分别是20克,25克,30克,编写程序吧所有能凑成200克的情况打印
Day07
For循环的多种写法:
1、当大括号里只有一条语句时,大括号可以省略
2、小括号里可以使用逗号操作符
3、在小括号里临时定义循环变量(c99规范中才可以使用)。当循环结束后临时定
义的循环变量不再能使用
4、如果大括号里没有语句则可以直接在小括号后用;结束,这种写法叫空语句
5、只保留小括号里之间的逻辑表达式
6、可以省略小括号中间的逻辑表达式(这个时候计算机认为这个逻辑表达式的结果
永远是真,这种循环无法正常结束,所有叫死循环)
While 循环也是一种实现循环的方式
如何编写循环的时候不知道循环要执行多少次就可以考虑采用while格式编写While循环和for循环可以互相替代,仅仅是两种不同的编写思路
While循环格式:
While(逻辑表达式1){
反复执行的语句 2
}
反复执行大括号里由直到逻辑表达式为假时结束
执行顺序:【1】【2 1】【2 1】…【2 1】
如果某一组最后编号为1的逻辑表达式结合为假则循环结束,否则启动下一组While循环也可以编写空语句和死循环(把1作为逻辑表达式就可以实现死循环)While循环中也可以使用break;和continue;语句
Do … while也是编写循环的方式,格式如下:
Do{
2
}while (1 );
它按照如下顺序分组执行:【2 1】【2 1】【2 1】【2 1】…【2 1】
相当于把while循环中第一组排除掉
它的结束方式和while循环一样
这种格式可以保证大括号里的语句至少执行一次
编写程序是无法预知的数字叫随机数
计算机生成的随机数叫伪随机数
Rand 标准寒素可以用来获得随机数
把函数调用语句当数字使用就得到随机数
为了使用这个函数需要包含stdlib.h函数
Srand标准函数可以用来设置随机数种子
这个函数把一个整数作为种子使用
为了使用这个标准函数需要包含stdlib.h文件
Srand函数调用语句只应该在主函数的开始执行一次
Time标准函数可以用来获得当前时间
把函数调用语句当数字使用结束得到的时间(1970---00:00:00到现在的秒数)
为了使用这个标准函数需要包含time.h文件
Goto也是流程控制语句,它可以指定任何一条语句作为下一条语句
不要使用goto语句
数组可以代表内存中一组连续的同类型存储区数组。需要先声明再使用
声明数组时需要指定存储区类型,数组名称以及存储区域个数
数组创建后内部所包含的存储区个数不可以改变
数组不可以当作整体使用,一次只能使用其中某一个存储区
数组中每个存储区有一个专门的编号,这个编号叫下标
第一个存储区的下表是0,向后依次递增
最大下标是存储区个数减一
超过范围的下标不可以使用
数组名称不代表存储区,而只代表第一个存储区的地址(数组名称不可以被赋值)数组名称加N可以计算出下标位N的存储区地址
数组中下标为N的存储区还可以使用如下方式表示:*(数组名称+ N)
可以使用一个for循环依次处理数组中每个存储区,循环中循环变量依次代表所有存储区的下标
数组也应该初始化
初始化数组的时候需要提供多个初始化数据,每个数据用来初始化一个存储区
所有初始化数据写在一对大括号里,不同数据之间使用逗号分开
初始化数据的使用顺序是从前向后
如果初始化的时候提供过多的初始化数据则多余的会被丢掉
如果初始化数据过少则没有对应初始化数据的存储区自动被初始化成0
如果初始化数据个数和存储区个数一样则可以省略数组声明中存储区个数
可以采用sizeof关键字对数组名称进行计算,计算结果是数组中包含的字节个数
Int arr[5] = {}; Sizeof(arr) = 4*5 = 20
声明变长数组的时候可以使用变量表示数组中存储区的个数,这种数组只能在C99规范中使用(变长数组只表示声明是不确定长度,可一旦确定就不可以再改变了)int arr[num]; / /变长数组
变长数组不可以初始化!
Day08
二位数组采用循环嵌套的处理方式对它每一个
二位数组的初始化:
二维数组既可以作为一个一维数组进行初始化,也可以作为多个一维数组进行初始化
二维数组名称加N跨越了N组存储区的大小,结果是下标为N那组第
一个存储区的地址
对二维数组组名称进行sizeof计算结果是整个二维数组中所有存储区的大小
可以把二维数组名称转换成一维数组使用
转换方式是二维数组名称后面加一个组下标
这个一维数组中包含组下标
对一维数组名称进行取地址操作结果可以看成是一个二维数组
这个二位数组中只有一个分组,这个分组里包含原来一维数组中所有存储区Day09
函数
C语言中可以采用分组的方式管路所有的语句
最简单的分组方式可以把所有语句分成多个函数,每个函数中包含多个语句
所有C语言程序一定由一个或多个函数构成
每个函数有自己的名字,名字用来区分不同的函数
C语言规定每个程序中必须包含一个叫做main的函数,这个函数叫主函数
多函数程序执行的时候遵守如下规则:
1、任何时候只能有一个函数工作
2、任何时候也必然有一个函数在工作
3、如果函数A在工作过程中停下来让函数B开始工作,则函数B结束所有工作后
必须要让函数A继续后面的工作
如果函数A在工作过程中停下来让函数B开始工作,则它们之间存在调用关系
函数调用关系一定发生在两个函数之间
调用关系中先开始工作的函数叫调用函数,后开始工作的函数叫被调用函数
函数A和函数B之间的调用只在函数B工作期间有效
存储区是有主人的
存储区的主人可以任意使用它所拥有的存储区
同一个主人的存储区不可以重名,不同主人的存储区可以重名
声明在函数内部的存储区它的主人是这个函数的某一次运行过程
绝大多数函数调用过程中存在双方之间数据的传递
数据传递有两个完全相反的方向,它们分别使用不同的方法实现
任何一个方向的数据传递都需要一组专门的存储区来记录要传递的数字
所有这些存储区的主人都是被调用函数
从被调用函数向调用函数只能传递一个数据,这个数据叫做被调用函数的返回值
为此只需要准备一个存储区
只能由被调用函数向这个存储区里放数字
被调用函数只能在最后一条语句使用return关键组向这个存储区放数字
只有调用函数才能从这个存储区里获得数字
把函数调用语句当作数字使用就可以获得这个数字
这个存储区的类型名称要写在函数名称前面
调用函数在得到返回值以后必须立刻使用或者转存到其他存储区
一个函数可以选择不使用返回值存储区,这时需要在函数名称前写void
如果函数名称前没有写数据类型名称则计算机认为函数使用一个整数类型的返回值存储区
如果没有使用return关键字返回值存储区赋值,则调用函数从这个存储区里获得的数字是随机的
在对返回值存储区进行赋值的时候最好保证数据和存储区的类型一致
Exit标准函数可以随时结束一个程序的执行;为了使用这个函数需要包含stdlib.h文件
为了把数据从调用函数传递给被调用函数需要被调用函数提供一组存储区(这些存储区的个数和类型都是任意的)
为了使用这些存储区需要被调用函数声明一组变量
这些变量必须声明在函数名称后面的小括号里面
这些变量叫做形式参数
函数名称后面小括号里的内容叫形式参数列表
形式参数列表中每个形式参数都需要专门写类型名称,用逗号分隔不同的形式参数声明
函数调用语句中需要在小括号路位每个形式参数提供一个对应的数字。被调用函数在工作的时候就可以通过形式参数获得这些数字。这些数字叫实际参数
如果存在多个实际参数,一个实验逗号把它们分隔开
所有可以当作数字使用的内容都可以作为实际参数使用
形式参数和实际参数的存储区完全不同,对形式参数的修改不会影响实际参数
如果函数名称后面的小括号里什么都没有则表示函数可以接受任意个数任意类型的实际参数
在小括号里写void表示函数没有形式参数
利用数组作为形式参数可以传递大量数据,声明在小括号里的数组就是形式参数
地址数据可以作为实际参数和数组形式参数配合使用(大多数情况下使用数组名称)数组作为形式参数使用时可以省略中括号里的数字,但是必须要另外提供一个形式参数表示数组中存储区个数
数组形式参数并不是数组,而是一个可以当作数组使用的存储区
预习:
1、函数(数组形参,函数隐式声明和显示声明)
2、递归函数
3、变量的生命周期和作用域
4、程序的分段
5、声明变量时可以使用的关键字
作业:
1、编写函数解决鸡兔同笼问题,调用函数提供头和脚的个数,函数负责计算出兔
子的个数
2、编写程序在屏幕上打印如下内容
1x9=9
2x8=17
3x7=21
4x6=24
5x5=25
每行使用一个函数调用语句打印
Day10
Rabbit 兔子chicken 鸡
数组作为形式参数的时候,真正的形式参数并不是数组,而是一个可以作为数组使用的单个存储区
函数调用的时候,这个真正的形式参数只记录了一个地址数据
数组形式参数的名称代表了这个存储区
数组作为形式参数的时候,数组名称所代表的存储区主人是被调用函数,数组里所包含的所有存储区主人一定不是被调用函数
使用数组形式参数可以让被调用函数使用其他主人的存储区
使用数组作为形式参数可以让调用函数和被调用函数共用同样的存储区
使用数组形式参数可以实现双向数据传递,这个参数叫输入输出参数
普通变量作为形式参数只能吧数组从调用函数传递给被调用函数,这个参数叫输入参数
被调用函数可以通过数组形参改变调用函数里的数组的数据
函数可以分成函数声明和函数体(大括号里的叫函数体,大括号前的叫函数声明)函数声明可以独立作为一条语句,这个时候可以省略所有形式参数的名称
当编译器首先遇到函数调用语句时会猜测函数的格式,这个猜测的结果叫函数的隐式声明