c语言高级篇.docx
- 文档编号:14426730
- 上传时间:2023-04-23
- 格式:DOCX
- 页数:31
- 大小:69.64KB
c语言高级篇.docx
《c语言高级篇.docx》由会员分享,可在线阅读,更多相关《c语言高级篇.docx(31页珍藏版)》请在冰豆网上搜索。
c语言高级篇
第七章数组
学习目标:
✧数组基本概念
✧一维数组的定义和引用
✧二维数组的定义和引用
✧字符数组的定义和引用
7.1基本概念
a.回顾:
前面学过的数据类型是基本的数据类型
存储特点:
每个变量单独存储(简单变量),各个变量无任何关系
x='a';
y=0;
z=2*x;
b.构造类型的基本概念
c中,变量类型除了前面介绍的基本类型之外,还有另外的一些复杂类型,合称为构造类型
构造类型:
是由基本的类型构造而成(数组,结构体,共用体,枚举型)
构造类型的每一个元素是一个变量,它可以是一个简单的类型或者构造类型
构造类型的元素的使用方法与简单变量相同
构造类型的元素占用相邻的存储空间
对于构造类型的变量,重点是访问其元素的方法
c.数组的概念
有序数据的特点:
Ø都是由若干元素组成的
Ø数据诸元素都是同一类型
Ø数据是按一定的顺序排列的
数组:
按序排列的具有相同类型的变量的集合
用一符号名(数组名)来表示一组数
用数组名后跟下标来唯一地确定数组中的元素
数组的首地址,数组的元素的类型及个数
7.2一维数组
a.定义一维数组
类型名数组名1[exp],数组名2[exp]...
其中:
exp为常量表达式
【说明】
◆数组的命名规则与简单变量的命名相同
◆数组名后只能用方括号括起来常量表达式
◆常量表达式的值确定数组元素的个数
◆类型名决定了数组中存放元素的类型
b.一维数组的存储
在内存中用连续的内存单元存放各个元素
保存数组所需内存量与数组元素的基本类型和数组元素的个数有关:
总的字节数=sizeof(类型名)*数组元素的个数
c.一维数组的引用
数组必须先定义后引用
c规定只能逐个引用数组的元素,而不能一次引用整个数组
引用数组元素的一般形式:
数组名[下标]
【说明】
下标可以是整形常量或者是整形表达式
数组的最大的下标的值为数组元素的个数减1
d.一维数组的初始化
1.在定义数组时对数组元素赋初值
如:
inta[6]={1,2,3,4,5,6};
2.给一部分元素赋初值
如:
inta[6]={1,2,3,4};
结果为:
a[0]=1,a[1]=2,a[2]=3,a[3]=4,a[4]=0,a[5]=0;
注:
对static数组不赋初值,系统会对所有数组元素自动赋值0
7.3二维数组
C中,数组的元素可以是数组,这样就构成二维数组,所以二维数组可以看成是数组的数组,照此办法,可以还可以构成三维,四级(称为多维数组)等等.二维数组是我维数组中最简单,最常用的数组,这代表多维数组的基本特征.
a.二维数组的定义
类型名数组名[exp1][exp2]
如:
inta[2][3];
a[0]a00a01a02
a[1]a10a11a12
b.二维数组的存储
二维数组从概念上可以理解为行列构成的矩阵但存储器是一维,需按一定的规则转换
在内存中:
二维数组的元素是按行存放
右边下标比左边下标变化快
c.二维数组的引用
二维数组的引用格式为:
数组为[下标][下标]
注意下标的最大取值,即:
注意数组定义和数组元素引用的区别
如:
inta[3][4];
下标的下限值:
a[0][0],上限的值是a[2][3]
d.二维数组的初始化
1.按存放的顺序赋:
如:
inta[2][3]={1,2,3,4,5,6};
2.按行赋值:
如:
inta[2][3]={{1,2,3},{4,5,6}};
3.部分赋值:
如:
inta[2][3]={1,2,4};
4.省略第一维长度:
如inta[][3]={1,2,3,4,5,6};
e.二维数组举例
7.4字符数组
a.字符数组定义
在c语言中,没不专门的字符串变量,而是将一个字符串存入一个字符数组中来表示一个字符串变量
定义方式:
char数组名[exp1][exp2]
如:
charc[5];
c[0]='h'c[1]='a'c[2]='p'c[3]='p'c[4]='y'
intc[5];
c[0]='h'c[1]='a'c[2]='p'c[3]='p'c[4]='y'
b.字符数组的初始化
1.按元素赋值:
charc[6]={'c','h','i','n','a'};
注:
\0表示空字符null,其ascii为0
staticchars[6];
为了测定实际的字符串的长度,c语言规定一个字符串结束标志'\0'
定义字符串数组的长度和字符串的长度的区别
2.使用字符串常量组字符串数组赋值
charc[6]="china";
charc[]="china";
charc[6]={"china"};
注:
以字符串赋值时,必须保证数组元素个数>=字符个数+1
对于字符数组中,即可以逐个引用字符串中的单个字符,使用时也可以单个使用也可以一次引用整个字符串数组
整个字符串输入输出,用%s格式描述
s要求后面输出项一定要对应的地址
用%s输出,无论数组元素有多少个,只要遇到\0就结束
注:
数组名就是地址,对二维数组只写行下标时是地址
c.字符处理函数
#include"string.h"
1.gets(字符数组名)
从键盘上输入一个字符串(以回车结束)放到数组中,并且得到一个函数值,该函数值是字符数组的起始地址
scanf与gets的区别:
gets只有遇到回车才认为这个字符串接收结束,而scanf当遇到空格,TAB,回车都认为字符串接收结束
scanf可以用来除字符串外的其它类型的数据,而gets只能接收字符串
2.puts(字符数组名/字符串)
3.strcpy(字符数组1,字符串/字符数组2)
将字符串/字符数组2中的字符串拷贝到字符数组1
字符数组1的长度>=字符数组2/字符串的长度
拷贝时连同'\0'一起拷贝
不能把字符串或字符数组直接赋给一个字符数组
4.strcat(字符数组1,字符串/字符数组2)
5.strcmp(字符串数组1/字符串1,字符串数组2/字符串2)
返回值为正数:
字符串1>字符串2
返回值为0:
字符串1==字符串2
返回值为负数:
字符串1<字符串2
注:
字符串的拷贝,比较,连接都必须用函数来做
6.strlen(字符串数组名/字符串)
测试字符串的长度,不含'\0'
d.字符数组应用举例
第8章函数
学习目标:
✧概述
✧函数的定义
✧函数参数(变量,数组)和函数值
✧函数的调用
✧函数的嵌套调用
✧局部变量和全局变量的存储类别
8.1概述
C程序的结构:
a.一个C程序可以由若干个函数组成
b.每一个程序有且只有一个主函数,其他的函数都是子函数
c.子函数之间是可以相互调用,但不可以调用主函数
说明:
a.c程序都是从主函数开始执行,调用完其他的函数后仍回到主函数,程序在主函数结束时结束
b.从用户角度看,函数可以分为:
1.标准函数(库函数)
2.自定义函数
c.从函数的形式看,可以分为:
无参函数
有参函数
8.2函数定义的一般形式
类型说明函数名([形参说明]){
函数体
}
a.无参函数定义形式:
类型说明函数名(){
函数体
}
b.有参函数定义形式:
类型说明函数名(形参说明){
函数体
}
c.空函数定义形式:
类型说明函数名([形参说明]){
}
函数体:
{
[局部变量说明]
语句
}
局部变量:
在函数体内定义的变量。
其有效范围仅限于这个函数内部
8.3函数的参数和函数的值
各函数主调用时经常需要传递一些数据,即调用函数把值传递给被调用的函数,经过被调用函数处理之后,得到一个确切的结果,再返回调用它的函数。
(函数之间的信息传递过程)
各个函数之间的信息的往来是由函数的参数和返回语句来完成的
a.形式参数和实际参数:
函数的参数:
用于函数间数据的传递
实参:
引用函数时使用的参数
形参:
定义函数时使用的参数
【说明】
❑在定义函数时必须说明形参的类型,形参只能是变量或数组,不能是常量或表达式
❑函数在调用之前形参是不占内存的,函数调用结束后,形参所占的内存会被回收
❑实参可以是常量,变量和表达式
❑实参的类型和形参的类型必须一致,字符型和整形可以相互匹配
❑实参对形参的数据的传递是"值传递“,即单向传递,
8.4函数的返回值
a.返回函数值的方法:
Ø如果一个函数有返回值,必须使用return语句
Ø一个函数中可以有一个return,也可以有多个return语句,但不论执行到哪个return语句都将结束函数调用,返回主函数
Øreturn语句中的括号可以省略,return后面的值可以是一个表达式
b.函数值的类型:
●函数的类型即函数值的类型
●省略了类型,是int型
●return语句中表达式的值,一般要与函数的类型一致
●如果不一致,则需要转换,只能数值类型可以自动转换,以函数类型为准
c.不需要返回值的函数
如果函数中没有使用return语句,函数的返回是一个不确定的值
如果一个函数不需要返回值,可以用void说明函数类型
如果一个函数被声明为void类型,就不允许再引用它的返回值
8.5函数的调用
a.函数调用的一般形式
函数名([实参列表]);
【说明】
如果调用无参函数,实参列表可以省略,但括号不能省
实参个数要与形参个数一样
实参与形参的类型应一一对应
【注】
不同系统对实参的计算顺序不同,一般是从右往左计算,为了避免混乱,应在调用函数之前把实参的值计算出来
b.函数调用的方式
1.函数语句
2.函数表达式
c.函数调用的执行过程
1.从右往左计算实参中各表达式
2.按照位置,将实参的值一一对应的传给形参
3.执行被调用的函数
4.当遇到return语句时,计算表达式的值,并返回主调函数
d.函数原形说明
原型说明的形式:
类型说明函数名(参数类型,...);
在程序中调用函数需要满足以下条件:
1.被调用函数必须存在,且遵循先定义后使用的原则
2.如果被调用函数的定义在主调函数之后位置,可以先给出函数的原形说明
【说明】
库函数是在包含的头文件中说明的,通过使用include预处理命令将这些原形说明插入到程序中
8.6函数的嵌套调用
在一个函数中又调用其他的函数
8.7函数的递归调用
递归调用是指调用一个函数时又直接或间接地调用函数本身
直接递归调用:
intf(intx){
intn,y;
n=f(y);
...
returnn;
}
间接递归调用:
intf1(intx){intf2(intt){
inty,z;intu,v;
......
z=f2(y);v=f1(u);
......
returnz;returnv;
}}
8.8数组作为函数的参数
a.数组元素做为函数实参
按值传递
b.一维数组与函数参数
若函数的形参是数组,对应的实参必须是数组名
【说明】
Ø实参数组与形参数组的类型一致
Ø用数组名作参数时,传递的是这个数组的首地址,因些形参也可以不指定大小,但需要另设一个参数来接收实参数组的长度
Ø数组作为函数的参数时,形参数组和实参数组共享同一块内存,如果形参数组元素的值被修改,实参数组的值也会被修改
c.多维数组与函数参数
多维数组可以作为函数的参数,如果形参是多维数组,可以省略第一维的大小但不能省略其他维的大小
实参和形参的小结:
实参形参传递方式
常量,变量,表达式,数组元素变量传值(单向)数组名数组数组的首地址(双向)
8.9局部变量与全局变量
a.局部变量
1.在一个函数内定义的变量
2.函数的形参
3.复合语句内定义的变量
说明:
1.局部变量只在自己的范围内有效
2.如果局部变量的有效范围有重叠的情况,有效范围小的优先
b.全局变量
函数之外定义的变量
全局变量的有效范围是从定义变量的位置开始到源文件结束
利用全局变量可以在函数间传递数据
尽量少使用全局变量
如果全局变量与局部变量同名,则局部变量优先
8.10变量的存储类别
a.变量的动态存储和静态存储
全局和局部变量,是从变量的作用范围来说的
动态存储和静态存储,是从存储类别
在内存中供用户使用的存储空间包括:
1.程序区
2.静态存储区:
编译时分配空间
3.动态存储区:
执行时分配空间
变量或函数的属性:
数据类型
自动型(auto)
存储类别静态型(static)
寄存器型(register)
外部型(extern)
b.局部变量的存储类别
自动型(auto)
存储在动态存储区
intmax(intx,inty){
autointm;
m=x>y?
x:
y;
returnm;
}
自动型在函数调用结束后变量会自动释放内存空间
局部静态变量(static):
存储在静态存储区,在程序的整个运行期间都不释放存储空间
局部静态变量只能在定义它的函数内被引用
c.寄存器变量
存储在寄存器中
register说明
计算机中的寄存器的个数是有限的,要节约使用
寄存器变量对寄存器的占用是动态的
d.全局变量的存储类别
全局变量都是静态的
用extern说明一个其它文件中定义的变量
存储类别小结:
1.变量的定义方法:
[存储类别]数据类型变量名;
2.变量的划分:
自动变量
静态局部变量
寄存器变量
局部变量形式参数
按作用域:
全局变量
自动变量
寄存器变量
动态存储形式参数
按存储类型
局部静态变量
静态存储
全局变量
自动变量
动态存储区形式参数
按存放的位置
静态局部变量
静态存储区全局
寄存器寄存器变量
第9章指针
10.1地址和指针的概念
a.数据在内存中的存储和读取
内存区每一个字节有一个编号,这就是”地址”,这相当于旅馆中的房间号,在地址所标志的内存单元中存放数据,就像旅馆中住的旅客一样
注意:
区分内存单元的地址与内存单元的内容的区别
在程序中一般是通过变量名来对内存单元进行存取操作
程序经过编译后已经将变量名转换为变量的地址,对变量值的存取是通过地址进行的
按变量地址存取值的方式称为”直接访问”方式
还可以采用另一种”间接访问”.
将变量的地址存放在另一个变量中,c规定这样的一个特殊的变量,它是存放地址的
“指向”是通过地址体现的,i_pointer的值为1500,它是变量i的地址这样在i_pointer和变量i之间建立起一种关系,通过i_pointer能知道i的地址,从而找到i的内存单元,这种称为指向关系
通过地址能找到所需的变量单元,可以说,地址”指向”该变量的单元(如同,房间号”指向”某一个房间一样)
C中,将地址形象地称为”指针”,意思是通过它能找到以它为地址的内存单元
一个变量的地址称为该变量的指针,如果有一个变量专门用来存放另一个变量的地址(即指针,则它称为指针变量)
//整形变量变量中保存的整型值
//指针变量变量中保存的是指针
指针变量的值(即指针变量中存放的值)是指针(地址)
注意:
区分指针和指针变量的概念
10.2变量的指针和指向变量的指針变量
变量的指针:
变量的地址
存放变量地址的变量:
指针变量,指向另一个变量
为了表示指针变量和它所指向的变量之间的关系,我们引入了"*"指向
10.2.1定义指针变量
定义的形式:
基类型*指针变量名;
使一个指针变量指向一个整形变量
int*n_p;
intn;
n_p=&n;
注:
a.定义时,指针变量前面的*表示该变量的类型为指针型变量
b.指针变量名是n_p,而不是*n_p
c.定义时,必须指定基类型
10.2.2指针变量的引用
指针变量里面只能存放地址(指针)
//n_p=1200;
有两个有关的运算符:
1.&取地址运算符
2.*指针运算符(间接访问运算符)
若:
n_p=&n;
&*n_p&n
*&n_p
*&n*n_pn
(*n_p)++(n)++
*n_p++//*,++同级,右结合
*n_p++nn_p=n_p+1*sizeof(基类型)
10.2.3指针变量作为函数的参数
指针变量作为函数的参数,是将变量的地址传递给另一个函数
不能企图通过改变指针形参的值而使指针实参的值改变
函数的调用可以得到一个返回值,运用指针变量作参数,可以得到多个变化的值
10.3数组指针和指向数组的指针变量
指针变量可以指向变量,当然可以指向数组和数组元素
数组指针:
数组的起始地址
数组元素的指针:
指数组元素的地址
引用数组的元素可以用:
下标法也可以用指针法(通过指向数组元素的指针找到所需的元素)
10.3.1指向数组元素的指针
inta[10]={...};
int*p;//int*p=&a[0];int*p=a;
p=&a[0];
c规定数组名代表数组的首地址,也就是第0号元素的地址
p=a;
a[0]…a[9]
10.3.2通过指针引用数组元素
c规定,如果指针变量p已指向数组中的某一个元素,则p+1指向同一个数组中的下一个元素(并非将p值简单地加1)
若p=&a[0];
p+i和a+i都是a[i]的地址
*(p+i)和*(a+i)是数组元素a[i]的值
指向数组的指针变量也可以带下标,如:
p[i]与*(p+i)等价
实际上:
在编译时,对数组元素a[i]就是处理成*(a+i),即通过数组的首地址加上相对位移量得到要找元素的地址,然后找出该单元中的内容
[]实际是变址运算符
引用数组元素:
a.下标法:
a[i]
b.指针法:
*(a+i)或*(p+i)
10.3.3数组名作为函数参数
数组名代表数组首地址,用数组名作实参,在调用函数时是把数组的首地址传递给形参,这样实参数组与形参数组共占同一段内存
实际上,能够接受并存放地址值的只能是指针变量,因此,c编译系统都是将形参数组名作为指针变量来处理的
10.3.4指向多维数组的指针和指针变量
指针变量可以指向一维数组,也可以指向多维数组
1.多维数组地址
inta[3][4]={{1,3,5,7},{9,2,4,6},{8,10,11,13}};
a有三个元素:
a[0],a[1],a[2]
而每一个元素又是一个一维数组,它包含4个元素
从二维数组的角度看,a代表整个二维数组的首地址,也就是第0行的首地址,a+1代表第1行的首地址
因此,a+1的含义是a[1]的地址
同时,a[0],a[1],a[2]既然是一维数组名,c规定数组名代表数组的首地址,因此a[0]代表第0行一维数组中第0列元素的地址,即&a[0][0],a[1]的值是&a[1][0],a[2]的值是&a[2][0]
那么某一行某一列元素的地址怎么表示?
可以用a[0]+1表示第0行第1列元素的地址,其中1代表1列元素的字节数
由于a[0]与*(a+0)等价,a[1]与*(a+1)等价,a[i]与*(a+i)等价。
因此,a[0]+1与*(a+0)+1的值都是&a[0][1]
得到a[0][1]的地址后,如何取得值
a[0]+1和*(a+0)+1是a[0][1]的地址,那么*(a[0]+1)及*(*(a+0)+1)或*(*a+1)也是a[0][1]的值
*(a[i]+j)或*(*(a+i)+j)是a[i][j]的值
记住*(a+i)和a[i]是等价的,在一维数组中a[i]就是下标为i的元素的值,在二维数组中a[i]表示第i行的首地址
说明的是a[i]在一维数组中占有物理地址的,若在二维数组a[i]代表一维数组名。
a[i]本身并不占实际的内存单元,它也不存放a数组中各个元素的值,只是一个地址(如同一维数组名并不占内存单元而只代表地址一样)
表示形式含义地址
a二维数组名,数组首地址,0行首地址2000
a[0],*(a+0),*a第0行第0列元素地址2000
a+1,&a[1]第1行首地址2008
a[1],*(a+1)第1行第0列元素地址2008
a[1]+2,*(a+1)+2,&a[1][2]第1行第2列元素地址2012
*(a[1]+2),*(*(a+1)+2),a[1][2]第1行第2列元素的值13
其中a+1和*(a+1)都是2008,那么a+1的值和a+1的地址怎么都是同一个值?
a+1代表一次跳过了一行(一个数组)
好比排长管理以班为单位,他走一步就跳过1个班,班长管理以战士为单位,走一步只是指向下一个战士。
二者地址虽相同,但含义不同,前者是”纵向管理”,后者是”横向管理”,二维数组名(a)是指向行,一维数组名(a[0])是指向列元素,a[0]+1中的”1”代表一个元素所占的字节数.
在行指针前加一个”*”,就转换成列指针,反之,在列指针前加一个&,就成了行指针
不要把&a[i]简单地理解为a[i]单元的物理地址,因为并不存在a[i]这样一个变量,它只是一种地址的计算方法,能得到第i行的首地址
&a[i],a+i指向行
a[i],*(a+i)指向列
a+i=a[i]=*(a+i)=&a[i]=&a
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 高级
