c语言中二维数组中维数的计算,数组指针字符串C语言程序设计-第4章.ppt
《数组指针字符串C语言程序设计-第4章.ppt》由会员分享,可在线阅读,更多相关《数组指针字符串C语言程序设计-第4章.ppt(132页珍藏版)》请在人人文库网上搜索。
1、程序设计语言(C),王正杰,第四章 数组、指针与字符串,本章重点数组的定义、初始化和使用;指针的定义、访问和运算;指针与数组和函数的联系;字符串与数组和指针的关系;结构体的应用;几种常用的算法和数据结构。 本章难点指针的定义、赋值和运算;数组、字符串、结构体的操作以及动态存储分配。,在C中,除了前面介绍的基本类型外,还有一种用基本类型数据按一定的规则组成的构造类型,构造类型的每一个分量可以是一个简单的类型变量,也可以又是一个构造类型的变量,它们可以像简单变量一样使用。C语言的构造类型有数组、结构体、共同体等。指针是C语言区别于其他程序设计语言的主要特征,指针可用于有效的表示数据之间复杂的逻辑关。
2、系,也可用于动态分配内存,还可以简单有效地处理数组。用来存放字符串的数组是字符数组,除了用访问数组的方式来,操纵字符串外,我们还可以利用指针来使用字符串。本章将介绍典型的构造类型数组和结构体,以及与数组和结构体密切相关的指针和字符串。,数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。 一维数组通常用于表示由固定多个同类型的具有线性次序关系的数据所构成的复合数据,如向量、某个学生的各门课成绩、学生的姓名表等。在语言中使用数组必须先进行定义,一维数组的定义形式为: 存储类型说明符 数据类型标识符 数组名 常量表达式; int a5;,数组名是用户定义的数组标识符,。
3、数组名的命名规则要遵循标识符命名规则。方括号中的常量表达式表示数组元素的个数,也称为数组的长度。 对于数组定义应注意以下几点:1)数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。2)数组名不能与其它变量名相同。3)不能在方括号中用变量来表示元素的个数,可以用符号常数或常量表达式,如arrry10表示数组arrry有 10个元素,其下标从0开始。,一维数组的初始化,数组的初始化就是在定义的同时,给部分或全部元素赋值,一维数组的初始化的格式是: 数据类型标识符 数组名常量表达式=初值表; 其中,初值表用一对花括号括起,每个初始值之间用逗号隔开。例如: int。
4、 array5= 1,2,3,4,5; 该语句定义了一个包含5个整型元素的数组array并对其进行了初始化,初始化后array 0=1、array1=2、array2=3、array3=4、array4=5。,初值表元素的数量可以少于数组长度,也就是可以只对数组的部分元素赋初值。例如: int array5=1,2,3; 初始化后前三个元素的值为array 0=1、array1=2、array2=3,其余没赋初值的元素的值都为0,即array3=0、array4=0。,也可以省略数组长度,例如: int array= 1,2,3,4,5; 初始化后数组的长度为5。,一维数组的访问,像普通变量一。
5、样,数组定义之后,就可以在程序中访问数组中的元素。我们只能逐个访问其中的元素,对于数组元素的访问可以通过以下形式表示:数组名下标 int array5= 1,2,3,4,5; a=array3; array3=6;,void main() int array5,i ; /使用循环语句对数组的5个元素分别赋值 for (i=0; i5; i+) arrayi=i*i; /分别输出数组元素的值 for (i=0; i5; i+) cout下标为i的元素的值是:arrayiendl; ,C语言系统对数组的下标越界不做任何检查,即对有n个元素的数组,既可访问下标小于0的元素,也可访问下标大于n的元素。。
6、当然,这样的元素是不存在的,所以越界访问元素会给程序运行造成不可预测的后果,所以程序员应当自己控制下标越界的检查。,用数组来处理求Fibonacci数列问题,void main() int i; int f20=1,1; /初始化第0、1个数 for(i=2;i20;i+) fi=fi-2+fi-1; /求第219个数 for(i=0;i20;i+) /输出,每行5个数 if(i%5=0) coutendl; coutfi ; ,向函数传递一维数组,当需要把一个一维数组传给一个函数时,调用者需要把该一维数组的变量名以及数组元素的个数传给被调函数,而被调函数的形参应为不带数组大小的一维数组定义以。
7、及数组元素的个数,下面我们通过一个例子来了解向函数传递一维数组的过程。,int min ( int a, int length) int i,m=0; /m用于记录最小元的下标 for (i=1; ilength; i+) if(aiam) /逐个比较数组的元素 m=i; /找出最小的元素 return m; /函数 min将返回最小 /元素的下标: ,void main() int array10=18,26,23,13,15,25,27, 14,29,31,tag; tag=min(array,10); /调用函数min,并将数组 /名作为参数传给函数 cout数组中最小的元素是:arra。
8、ytagendl; ,简单选择排序,假设排序过程中,待排记录序列的状态为:,有序序列R1.i-1,无序序列 Ri.n,第 i 趟 简单选择排序,从中选出 关键字最小的记录,有序序列R1.i,无序序列 Ri+1.n,对主调函数传递的数组进行排序,void sort(int a,int length) /定义变量tag以标记当前最小元素之下标,/定义交换变量buffer int i,j,tag,buffer; for(i=0;ilength;i+) ,tag=i; /每次外循环,都将tag的值置为 /内循环处理的第一个元素的下标 /内循环的任务是找出数组中下标 /从i到length的元素的最小者 。
9、for(j=i;jaj) tag=j; /标记小元素的下标 /将当前未排好序数组的最小元素atag /和元素ai交换 buffer=atag; atag=ai; ai=buffer;,void main() int array10=6,2,10,3,7,5,9,4,8,1,i; coutendl排序前数组array:; for(i=0;i10;i+)coutarrayi ; sort(array,10);/调用函数sort,并将数组array /和数组长度作为参数传递给函数 coutendl排序后数组array为:; for(i=0;i10;i+)coutarrayi“ ”; /输出排序 /后。
10、的数组array coutendl; ,该程序使用的是选择排序,其思想是,第一次从所有元素中选取最小值,与a 0交换;第二次从剩余元素中选取最小值,与a 1交换;直至完成整个数组的排序。函数sort中,每轮内循环结束后tag中存放的就是剩余元素中最小者的下标;第i次外循环结束后,数组前i个元素就都是已经排好序的元素。当排序完成返回主调函数main后,主调函数的数组array就是已经完成排序的数组,这是因为main函数中的数组array和sort函数中的数组a代表同一块存储空间,从本质上讲它们是同一个数组。,用起泡法对10个数排序(由小到大)。 起泡法的思路是:将相邻两个数比较,将大的调到后头。。
11、,起泡排序,假设在排序过程中,记录序列R0.n-1的状态为:,第 i 趟起泡排序,无序序列R1.n-i+1,有序序列 Rn-i+2.n,n-i+1,无序序列R1.n-i,有序序列 Rn-i+1.n,比较相邻记录,将关键字最大的记录交换到 n-i+1 的位置上,void main() int a10=6,2,10,3,7,5,9,4,8,1; int i,j,t; for(j=1;jai+1) t=ai;ai=ai+1;ai+1=t; coutthe sorted numberS :endl; for(i=0;i10;i+) coutai ; ,二维数组,前面介绍的数组只有一个下标,称为一维数组。
12、,而在实际问题中经常要处理多维的量,需要构造二维数组或更多维的数组。简单地说,二维数组就是具有两个下标的数组,其元素有两个下标,以标识它在数组中的位置。数组维数的概念与几何中维数的概念是相似的,如果说一维数组的元素是线性排列的,只要给出一个下标就可以确定某一特定元素。那么,二维数组就类似于几何中的X-Y坐标系,坐标系中只要指出X坐标和Y坐标就能确定一个点,而要确定二维数组中的某一个元素也只需指出元素所在的行和列。,二维数组定义,存储类型说明符 数据类型标识符 数组名常量表达式1常量表达式2; 其中存储类型说明和数据类型说明与一维数组相同,常量表达式1表示第一维下标的长度,常量表达式2 表示第二。
13、维下标的长度,两个常量表达式中不能包含变量。例如: int array23; 定义了一个二维数组array,该数组有两行,每行有三个元素。,二维数组的行下标和列下标都是从0开始的,对于n行m列的二维数组,行下标的取值范围为0n-1,列下标取值范围为0m-1。 二维数组的所有元素占有的内存空间是连续的,因此只要知道数组在内存中的起始地址就可以很容易的算出其它元素的存储单元地址。,二维数组的初始化,二维数组赋初值的方式有两种,一种是不分行给二维数组所有元素赋初值,比如int array23=1,2,3,4,5,6;,另一种更直观的方法是分行给二维数组所有元素赋初值,如int array23=1,2。
14、,3,4,5,6;。,同一维数组一样,二维数组也可以只给部分元素赋初值,例如: int array23=1,2,3; 对数组前三个元素array00、array01、array02分别赋以1、2、3,其他剩余元素都为0。 此外二维数组还可以用分行的方法给部分元素赋值,例如: int array23=0,2,4; 初始化后各元素的值是array00=0、array01=2、array02=0、array10=4、array11=0、array12=0,,对二维数组赋初值可以省略说明第一维的长度,但是无论何种情况,都不能省略说明第二维的长度。在给全部元素赋值时,例如: int array23=1,。
15、2,3,4,5,6; 编译系统会根据初值个数分配相应的存储单元。在分行给元素赋初值时,如: int array3=2,4,5,6; 编译系统也会根据所分的行数确定第一维的长度。,二维数组的使用,对二维数组的访问同一维数组类似,也是通过下标运算符“”和下标值来进行的。访问的形式如下: 数组名 行下标列下标 例如: int array23= 1,2,3,4,5,6; a=array10; array10=6; 这几条语句的功能是访问数组array中,第二行第一列的那个元素,将其值4赋予变量a后,赋予其新值6。,求4*4二维数组各行和各列元素之,void main() int c4,r4, i,j;。
16、 /定义c4存放列元素的和, / r4存放行元素的和 int array44= 1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16; for(i=0;i4;i+) ri=ci=0; /初始化一维数组 . for(i=0;i4;i+) /输出行元素的和 cout“第”i+1“行元素的和为: riendl; for(i=0;i4;i+) /输出列元素的和 cout“第”i+1“列元素的和为: ciendl; ,for(i=0;i4;i+) for(j=0;j4;j+) /将第i行第j列的元素的值加入ri ri=ri+arrayij; /将第i行第j列的元素的值加入cj 。
17、ci=ci+arrayji; /一次循环就好 /或cj=cj+arrayij;多次循环才行 ,二维数组名作函数的参数,主函数中初始化一个矩阵并将每个元素都输出,然后调用子函数,分别计算每一行的元素之和,将和直接存放在每行的第一个元素中,返回主函数之后输出各行元素的和。,void RowSum(int A4, int nrow) int sum; for (int i = 0; i nrow; i+) sum = 0; for(int j = 0; j 4; j+) sum += Aij; cout Sum of row i is sum endl; Ai0=sum; ,void main(vo。
18、id) int i; int Table34 = 1,2,3,4,2,3,4,5,3,4,5,6; for (i = 0; i 3; i+) for (int j = 0; j 4; j+) cout Tableij ; cout endl; RowSum(Table,3); for (i = 0; i 3; i+) cout Tablei0; ,指 针,指针是C+语言最主要的风格之一,也是C+语言最重要的内容之一,利用指针变量不仅可以有效地表示各种数据结构,也可以用于参数传递和动态分配存储空间,并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针的应用使得C+语言具有灵活、实用、高。
19、效的特点。,在计算机中,所有的数据都是存放在存储器中的。计算机的存储器就像一个巨大的一维数组,每个数组元素就是一个存储单元。一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型数据占4个单元,字符型数据占1个单元,为了正确地访问这些内存单元,必须为每个内存单元编上号,根据一个内存单元的编号即可准确的找到该内存单元,内存单元的编号也叫做地址。,关于内存地址,内存空间的访问方式 通过变量名访问 通过地址访问 地址运算符: 则 int *p; /说明p是一个指针变量,它的值是某个整型变量的地址 float *q; /说明q是指向浮点变量的指针变量 char f ,*。
20、r; /说明f是字符变量,r是指向字符变量的指针变量,指针的赋值,在定义一个指针的同时也可以对它进行初始化赋值,通常是用一个与说明的指针具有相同类型的变量的地址来进行赋值的。初始化赋值的形式如下: 数据类型说明符 *指针变量名=地址; 其中地址可以是同类型变量的地址、数组的地址或数组元素的地址。地址可以用取地址运算符 语句执行完后,变量a的地址将赋给指针变量p,或称将指针p指向变量a,指针变量也可以在定义后赋值,如上述语句就可以改为int a=5, *p; p= 需要注意的是,没有赋值的指针变量中存放的是一个随机值,使用没有赋过值的指针是相当危险的。如果要使指针变量中的指针不指向任何存储单元,。
21、那么可以将空指针赋给指针变量,空指针的值为0,也可以用在stdio.h中定义的符号常量NULL表示。,指针的访问,前面介绍的是如何对指针变量进行赋值,对指针变量赋值后就可以对其进行访问了。 对指针值的访问有两种形式, 一种是将一个指针的值赋给另一个指针 另一种是用指针运算符*将指针所指向的变量的值取出用以访问。,void main() int a=10,b,*p= ,以指针作为函数参数,以地址方式传递数据(传入地址),可以用来带回函数处理结果。 实参是数组名时形参可以是指针。,读入三个浮点数,将整数部分和小数部分分别输出,void splitfloat(float x, int *intpar。
22、t,float *fracpart) /形参intpart、 fracpart是指针 *intpart = int(x);/ 取x的整数部分 *fracpart = x - *intpart; /取x的小数部分 ,void main(void) int i, n; float x, f; cout x; splitfloat(x, ,使用指针来完成两个整数的交换,Swap(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; ,void main() int a,b; int *pointer_1,*pointer_2; cinab; 。
23、pointer_1= ,指针的运算,指针变量可以进行赋值运算、部分算术运算及关系运算。 指针的算术运算主要有指针变量加减一个整数(例如p+、p-、p+i、p-i、p+=i、p-=i)和两个同类型的指针变量的相减(例如p-q)。 两指针之间的关系运算表示他们指向的变量在内存中的位置关系。例如: p=q表示p和q指向同一元素;pq表示p处于高地址位置;pq表示p处于低地址位置。上述指针的关系运算一般用于对数组的访问。,指针变量加或减一个整数i的意义是把指针的当前位置(指向某数组元素)向前或向后移动i个位置。例如: short array8,*p; p=array; p=p+5; 其中第二条语句将指。
24、针p指向数组array即指向a0,第三条语句将p指向array5,设p是指向数组array的指针变量,则p+i,p-i,p+,p-,p+=i等运算都是合法的。需要注意的是,一个指针变量加(减)1并不是简单地将原值加(减)1,而是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数加(减)。同样,指针移动i个位置不等于指针移动i个字节 。 short *p; p+; 指针p指向的地址向高地址移动了2个字节(因为一个短整型数占2个字节 int *p; p+; 则指针p指向的地址向高地址移动了4个字节,两指针变量相减的得到一个整数。如果两个指针变量指向同一个数组的元素,则两个指针变量。
25、相减所得的整数是两个指针所指数组元素之间相差的元素个数。例如: int array10,*p,*q,n; p=array; q=p+2;n=q-p; 其中第二条语句将指针p指向数组array即指向a0,第三条语句将p指向array2,第四条语句将指针变量q和p相减得到的值赋给变量n,此时变量n的值是2。,指针与0比较,指针变量可以与0比较,例如: p=0表明p是空指针,它不指向任何变量; p!=0表示p不是空指针。需要再次强调的是,空指针不同于未赋值指针,指针变量未赋值时,它的值不确定,是不能使用的,否则将造成意外错误。而指针变量赋0值后,它就成为空指针,它不指向具体的变量。 int *p; 。
26、int b=*p;这里没有给p赋值,就使用*p,是绝对错误的!,指针与数组,数组名是一个不允许赋值运算的指针,这个指针的值就是数组的起始地址,例如,对整型一维数组array10,array就是一个指向数组起始地址的指针,它指向数组的第一个元素,array的值与array0的地址相同 用array+i可以表示arrayi的地址,也就是说array+i与 pa= 通过指针引用数组元素 经过上述声明及赋值后: *pa就是a0,*(pa+1)就是a1,. ,*(pa+i)就是ai. ai, *(pa+i), *(a+i), pai都是等效的。 不能写 a+,因为a是数组首地址是常量。,设有一个int型。
27、数组a,有10个元素。用三种方法输出各元素: 使用数组名和下标 使用数组名和指针运算 使用指针变量,数组名和下标 for(i=0; i10; i+) coutai; 使用数组名指针运算 for(i=0; i10; i+) cout*(a+i); 使用指针变量 for(p=a; p(a+10); p+) cout*p;,行指针和列指针,定义一个二维数组int array34来说明,由于二维数组可以看作特殊的一维数组,其中每一个元素又是一个一维数组,所以可以把数组array看作是由array0、 array1、 array2三个元素组成的特殊一维数组,而array0、 array1、 array2。
28、又可以分别看作一维数组,所以array0、 array1、 array2也表示一维数组的起始地址。,既然array和array0、 array1、 array2都表示地址(指针),它们之间有什么区别呢?区别就在于array+1指向的是第2行元素的起始地址,也就是array1指向的地址,而array0+1指向的是元素array01的起始地址。array每加1,就跳过一行,所以被称为行指针,而array0、 array1、 array2被称为列指针。,通过运算符*将行指针转换成列指针,*array与array0 相等,*array+1与array0+1是相等的,这里*只是将行指针转换成了列指针,*。
29、array还是表示地址,而不是取地址的内容。若要取元素array00的内容,可以用* array0或*array,这里*array的后一个*表示先将行指针转换成列指针,前一个*表示取内容。,array0+1和*(array +0)+1,是array01的地址,那么,*(array0+1)就是array01的值。同理,*(*(array +0)+1)或*(* array +1)也是array01的值。*(arrayi+j)或*(*(array +i)+j)是arrayij的值。务请记住*(array +i)和arrayi是等价的。,array、array+i、array i、*(array+i)。
30、、*(array+i)+j、array i+j都是地址。 *(arrayi+j)、*(*(array+i)+j)、 array ij是二维数组元素array ij的值。,指向包含4个元素的一维数组的指针,void main() int a34=1,3,5,7,9,11,13,15,17,19,21,23; int (*p)4,i,j; p=a; cinij; coutaij=*(*(p+i)+j)endl; ,多维数组的地址可作函数参数传递,在用指针变量作形参以接受实参数组名传递来的地址时,有两种方法: 用指向变量的指针变量; 用指向一维数组的指针变量。,有一个班,3个学生,各学4门课,计算总。
31、平均分数,以及第n个学生的成绩。 用函数average()求总平均成绩,用函数search ()找出并输出第i个学生的成绩。,void average(float *p,int n); void search(float (*p)4,int n); void main() float score34=65,67,70,60, 80,87,90,81,90,99,100,98; average(*score,12);/求12个分数的平均分 search(score,2); /求第2个学生成绩 ,void average(float *p,int n) float *p_end; float su。
32、m=0,aver; p_end=p+n-1; for(;p=p_end;p+) sum=sum+(*p); aver=sum/n; coutaverage=averendl; ,void search(float (*p)4,int n) int i; coutthe score of No.n are:endl; for(i=0;i4;i+) cout*(*(p+n)+i) ; ,指针数组,指针数组就是由指针组成的数组,也就是说数组中的每个元素都是相同数据类型的指针变量。指针数组的声明方式和普通数组相似: 数据类型说明符 *数组名常量表达式; 例如: char *pc5; 声明了一个一维指针。
33、数组,其中包括5个元素,均为指向字符类型的指针,void main() int line1=1,0,0; int line2=0,1,0; int line3=0,0,1; int *p_line3;/声明整型指针数组 p_line0=line1;/初始化指针数组元素 p_line1=line2; p_line2=line3; coutMatrix test:endl; for(int i=0;i3;i+)/对指针数组元素循环 for(int j=0;j3;j+)/对矩阵每一行循环 coutp_lineij ; coutendl; ,函数的指针,我们知道程序只有在代码装入内存后才能运行,函数本。
34、身作为程序的一部分,也要在内存中占有一片存储区域,这个区域的起始地址,就是函数的指针,也称之为函数的入口地址。函数的指针与数组的指针类似,数组名代表数组的指针,即数组的首地址,同样函数名就代表函数的指针,也就是函数的入口地址。,函数原型为int fun(int x,int y ,int z),则定义函数指针变量的语句为int(*pfun)(int,int,int),需要注意的是,在声明指向函数的变量时,变量名外的括号不能少。若是没有括号,如 int *pfun(int,int,int)就成为定义返回指针的函数。 定义好的指针变量可以存放函数的指针,例如: pfun=fun; 该函数返回值的数据。
35、类型,函数参数个数、类型都应与定义指针变量时说明的一致 。,int minx(int x,int y) if(xy) return x; else return y; ,void main() int a,b,c; int (*pmin)(int x,int y); /定义指向函数的指针 pmin=minx; /将该指针指向函数min / 可以写成pmin= ,返回指针值的函数,函数名前的数据类型标识符用于表示该函数的返回值是什么类型的,函数的返回值可以是整型、字符型或浮点型,也可以是指针型,这时应该将函数的返回值说明成相应数据类型的指针,返回指针值的函数定义格式如下: 数据类型标识符 *函数。
36、名 ( 形式参数说明列表 ),其中数据类型标识符和函数名之间的*表示该函数的返回值是指针,数据类型标识符表示指针指向的是何种类型的数据,例如: float *fun(int a , int b); 就声明了一个返回值为单精度浮点型指针的函数。,float *compute(float x,float y) /定义float型指针result用以返回计算结果,并为 /其分配的空间(动态存储分配下一节将介绍) float *result=new float4; /将计算结果依次存入result所指向的存储空间中 *result=x+y; *(result+1)=x-y; *(result+2)=x。
37、*y; *(result+3)=x/y; return result; /返回指针result ,void main() float a,b,*p; /定义float型指针p用以接受返回值 couta; coutb; p=compute(a,b);/调用函数,p和result指向同一内存 if(p) /如果result申请的空间得到了允许 /利用指针p依次输出计算结果 cout两数的和是:*pendl; cout两数的差是:*(p+1)endl; cout两数的积是:*(p+2)endl; cout两数的商是:*(p+3)endl; delete p; /释放申请的内存空间 ,compute函。
38、数申请了4个单精度浮点单元的内存空间,并将这个空间的首地址赋给指针变量result,计算的结果存放在这块存储空间内,并将指针变量返回给主调函数main。主函数使用指针p来接受compute返回的指针result的值,再使用p将计算结果逐个输出,最后释放p指向的内存空间。,动态存储分配,到目前为止,程序中使用的变量和数组的类型、数目和大小是在编写程序时由程序员确定下来的,因此在程序运行时这些数据占用的存储空间数也是一定的,这种存储分配方法被称为静态存储分配,静态存储分配的缺点是程序无法在运行时根据具体情况灵活调整存储分配情况。C+提供了内存空间动态管理的机制,使程序在运行过程中可以按照实际需要申。
39、请适量的内存,使用结束后,还可以释放所申请的内存,在程序运行过程中申请或释放的内存单元称为堆,动态申请和释放内存的过程称作建立和删除。,自由存储区也称堆区,是一块可以动态管理的内存区,C+中用指针和new运算符来动态地申请一块内存单元,用delete运算符来释放被申请的内存单元。动态申请变量空间与申请数组空间的格式略有不同,我们分别进行讨论。 使用new运算符动态申请变量空间的格式如下: new 数据类型标识符 (表达式);,数据类型标识符表示开辟的空间中存放何种类型的数据,表达式表示对动态定义的变量进行赋初值,可以省略。如果存储空间的动态开辟成功,则返回指向那块开辟的内存单元地址,否则返回N。
40、ULL,即空指针。例如: int *p; p=new int(2); 这两条语句的含义是,使用new运算符从自由存储区中分配一块与int类型相适应的存储空间,并赋初值2,然后将这个存储空间的首地址存入事先定义好的整型指针p,如果分配失败,则置指针p为空指针,使用new运算符动态申请一维连续空间格式: new 数据类型标识符 整型表达式; 其中,数据类型标识符表示要申请何种数据类型的存储空间,整型表达式表示一维数组的长度。如果申请分配成功,返回的是数组的指针,失败则返回空指针NULL 。需要注意的时候,动态开辟数组时,无法对其中的元素进行初始化。例如: int *parr; parr=new i。
41、nt 5; /申请的是长度为5的整型数组的存储区域,使用动态存储分配时要注意在确认分配成功后才能使用,否则可能造成严重后果;分配成功后最好不要变动指针的值,否则在释放这片存储时会引起系统内存管理混乱;动态分配的存储空间不会自动释放,只能通过delete释放。 使用delete运算符释放动态分配的变量和数组存储空间的形式分别如下: delete p ; / delete 指针:释放变量空间 delete parr; / delete 指针:释放连续空间 编写程序时,动态的开辟内存一定要有相应的内存释放,否则会造成内存空间的浪费。,输入任意个数的数据,然后输出所有数据,void main() fl。
42、oat *parr; /定义指针用来指向分配存储区的首地址 int i,length; /length用以记录要输入数据的个数 coutlength; parr=new floatlength; /申请长度为length的float数组if(parr) /如果内存分配成功,继续输入数据 else cout内存分配失败endl; ,for(i=0;iparri; cout你刚才输入的数据是:endl; for(i=0;ilength;i+) coutparri ;/输出数组 coutendl; delete parr; /释放申请的内存空间,C语言编译系统的内存管理函数,void *malloc。
43、(unsigned int size); 其作用是在内存的动态存储区中分配一个长度为size的连续空间。此函数的值(即“返回值”)是一个指向分配域起始地址的指针(基类型为void)。如果此函数未能成功地执行(例如内存空间不足),则返回空指针(NULL)。,void free(void *p); 其作用是释放由p指向的内存区,使这部分内存区能被其他变量使用。p是调用malloc函数时返回的值。free函数无返回值。,字 符 串,C+语言中的文字数据有两种:一种是单个的字符,一种是字符串。在前面我们了解到,单个的字符可以用字符变量存放。C+中没有字符串数据类型,对字符串数据的存放是通过字符数组或指。
44、针指向的一块连续内存空间来实现的。,一维字符数组的定义和普通数组是类似的,只不过数据类型标识符为char型。如: char c10; / 定义了一个长度为10的一维字符数组 一维字符数组初始化的常用方式是以字符串的形式进行初始化,即将整个字符串直接赋值给数组。例如: char c10= “hello c+”;或者 char c10=“hello c+”; 也可以不指定数组长度进行赋值,例如: char c2= “hello c+”;,字符串的结束标志,字符串总是以0作为串的结束符,因此当把一个字符串存入一个数组时,编译系统会自动把结束符0存入数组,并以此作为该字符串是否结束的标志,二维字符数组。
45、,字符型的二维数组也可以看成由多个一维字符数组组成的,所以可以用二维字符数组来存放多个字符串。 char week3=“Sun”,”Mon”,”The”, ”wed”,”Thu”,”Fri”; 定义了一个6行的二维字符数组week,每行又可以看作包含3个元素的一维字符数组。注意,在初始化时,元素是用双引号括起的,这是因为相当于对一维字符数组赋予一个字符串作初值。,输入ASCII码,查找并输出其对应的大写英文字母,void main() char letter=ABCDEFGHIJKLMNOPQRSTUVWXYZ; intasc; /保存输入的十进制ASCII编码 coutasc; if(asc。
46、=A ,void main() intasc; coutasc; cout(char)ascendl; ,指针访问字符串,对字符数组的访问同样也可以使用指针法,所谓字符串的指针就是该字符串在内存中所占空间的起始地址,由于字符串可以用字符数组来实现,所以字符数组名就可以表示该字符串的起始地址,即字符串的指针。我们可以定义指针变量来存放字符串的指针。 char *string, c10=“hello c+”; string=c;,求字符串长度函数,int str_len(char str) char *p=str; /指针p用以访问字符数组str while(*p!=0) /当指针指向的单元 p+。
47、; /内容为0时,表示字符串结束 return p-str; void main() char string=abcdefghijklmnopqrstuvwxyz; cout“字符串”string“的长度为: “ str_len(string)endl ,例如使用字符串指针变量如string可以进行自加自减运算,而数组名c不能进行自加、自减运算;字符串指针变量的定义和初始化可以同时进行,也可分开进行 char *string=”hello c+”; /字符串指针变量的定义和初始化同时进行,正确 char *string; / 字符串指针变量先定义,正确 string=”hello c+”; /。
48、字符串指针变量后初始化,正确,字符数组的定义和初始化则只能同时进行,不可以分开进行。 char c10=“hello c+”; /字符数组的定义 /和初始化同时进行,正确 字符数组的定义和初始化分开进行 char c10; /字符数组先定义,正确 c=“hello c+”;/ 字符数组后初始化,不正确,字符串拷贝函数,将str2内容拷入str1,void str_cpy(char str1 , char str2) char *p1=str1,*p2=str2; int i=0; while(p2i!=0) p1i=p2i; i+; /指针使用下标i完成移动 p1i=0; /必须给str1补上。
49、结束标志0 ,void main() char letter1=abcdefghijklmn, letter2=I love C+; cout字符串letter2为:letter2endl; cout字符串letter1为:letter1endl; str_cpy(letter1,letter2);/调用字符串拷贝函数 cout函数调用后字符串letter2为:letter2endl; cout函数调用后字符串letter1为:letter1endl; /输出完成拷贝的字符串 ,字符串处理函数,从前面的例子可以看到,用下标法和指针法来操作字符串非常繁琐。因此,C+提供了一批用于字符串处理的库函。
50、数以完成许多常用的字符串操作,如果要在程序中调用输入输出的字符串函数,在使用前应包含头文件stdio.h,使用其它字符串函数则应包含头文件string.h。,常用的两个字符串函数,strlen( str ) 功能:测字符串的实际长度(不含字符串结束标志0) strcpy (str1,str2) 把字符数组str2中的字符串拷贝到字符数组str1中,串结束标志“0”也一同拷贝。,结 构,在程序中往往还需要处理一些由不同类型元素所构成的复合数据,例如学生基本信息的数据,它由学号、姓名、专业号和入学成绩等元素构成,这些元素不存在像数组那样的线性关系,而且往往还具有不同的数据类型,因此不能用数组类型来。
51、表示这样的数据。由于这些数据元素之间有相当强的联系,如果使用一些不同类型的变量来表示上述的复合数据,就会破坏数据的内聚性,而且变量的数目会变得很多,极大地降低程序的可读性。,C提供了结构类型用以描述和管理这种复杂的数据结构,结构是若干相关数据项的有机结合,但各数据项的数据类型可以不同。对于上例,可用long型变量存放学号、char型数组存放姓名、int型变量存放专业号、float型变量存放入学成绩,作为结构的成员,包含在结构类型中,再用该结构定义相应的结构型变量。这样,学生的信息就可以用一个结构型变量存放,数据之间的联系得到了体现,数据的传递也大为方便。,应以关键字struct开始,结构类型名。
52、应符合标识符命名规则,数据成员为结构中的数据项,它们都是变量,其类型可以是基本数据类型,也可以是已定义的自定义数据类型。成员名在结构体内具有唯一性,但是允许成员名和程序中的变量名或是其他结构体中的成员名重名,一个结构的所有成员应括在一对花括号内,而且花括号后的分号是必需的。 struct student long num; char *name; int majornum; float scores; ;,定义结构体类型变量的方法,1. 先声明结构体,再定义变量名(普遍使用) 如上面已定义了一个结构体类型struct student,可以用它来定义变量。如: struct student st。
53、udent1, student2; 2. 在声明类型的同时定义变量(不常用),例如: structstudent student1,student2; 直接定义结构类型变量(不常用) struct student1,student2;,对结构变量的访问,有两种方式 一种是访问结构变量的某个数据成员, 另一种是访问整个结构变量。,访问一个结构变量中的某个数据成员需要用到成员运算符“.”,它是双目运算符,其左边的操作数是一个结构类型变量,右边的操作数是该结构的一个成员。例如,zhangsan.num表示访问结构类型变量zhangsan的成员num。结构类型变量的每个成员都可以看作是一个独立的变量,。
54、对成员变量可以实施像普通变量一样的操作。例如: zhangsan.num=20061001; zhangsan.majornum=10;,对整个结构变量的访问,赋值运算符 = 用于同类型变量之间的赋值操作,这个过程实际上是整个结构变量值的复制过程。例如, lisi=zhangsan; 就是将结构类型变量zhangsan所有成员的值复制给lisi的相应成员变量。,结构体定义和变量的赋值与输出,struct student long num; char *name; int majornum; float scores; ;,void main() /定义student型变量lisi、wangwu。
55、、a,初始化lisi student lisi=20061002, 李四,10,612,wangwu,a; wangwu.num=20061003;wangwu.name=王五; wangwu.majornum=10; wangwu.scores=607; cout 学号 姓名 专业号 入学成绩endl; /分别输出zangsan、lisi的各个成员 coutlisi.num lisi.name lisi.majornum lisi.scoresendl; a=wangwu; /用=将wangwu的值复制给a couta.num“ ”a.name “ a.majornum a.scoresen。
56、dl; ,结构数组的定义,所谓结构数组只不过是用结构类型来定义的数组,数组中的所有元素都是相同的结构数据类型。 student group10; 就定义了一个有10个student型元素的一维数组group。,对结构数组的访问,需要同时遵守访问数组元素和访问结构变量的规则,对单个结构数组元素访问同对结构变量一样也有两种方式: 一、使用“.”运算符访问结构数组元素的某个成员。例如:a1.num=20061002; 二、将结构数组元素的值赋予结构相同的结构变量。例如:student lisi; lisi=a1;,结构指针的定义,struct student *ps; 定义了一个student类型的。
57、结构指针。也可以将关键词struct略去。 同一般指针一样,在使用一个结构指针时,该指针必须已经赋值。结构指针的赋值可以使用取地址运算符,第一种方式,使用指针运算符*对结构变量进行复制或是来访问其中结构成员的内容。例如: student *ps= 而第三条语句则是表示将学号20061001赋值给结构变量zhangsan的成员num。需要注意的是,由于成员运算符“.”的优先级比指针运算符*高,所以(*ps) .num中的括号不能省略。否则,*p.num就等价于*(pnum)了。,第二种方式是使用指向运算符“-”。指向运算符“-”与成员运算符“.”都是双目运算符,而且它们优先级都是所有运算符当中最。
58、高的,不同的是指向运算符“-”左边的操作数是结构指针,右边的操作数是该结构的一个成员。第三条语句更多的是使用指向运算符“-”来完成: ps-num=20061001;,以线性表中第一个数据元素 的存储地址作为线性表的地址,称作线性表的头指针。,头结点,头指针,头指针,有时为了操作方便,在第一个结点之前虚加一个“头结点”,以指向头结点的指针为链表的头指针。,空指针,线性表为空表时, 头结点的指针域为空,例如:逆位序输入 n 个数据元素的值, 建立带头结点的单链表。,操作步骤:,一、建立一个“空表”;,二、输入数据元素an, 建立结点并插入;,三、输入数据元素an-1, 建立结点并插入;,an,a。
59、n,an-1,四、依次类推,直至输入a1为止。,带表头节点的单链表的基本操作,#define LEN sizeof(struct student) struct student long num; float score; struct student *next; ;,struct student *creat(void) /此函数带回一个指向链表头的指针 int n=1; struct student *head; struct student *p1,*p2; head=( struct student*) malloc(LEN); /申请单元*/ head-next=NULL; p1=。
60、(struct student*)malloc(LEN); coutp1-nump1-score; free(p1); return(head); ,while(p1-num!=0) p1-next=head-next; head-next=p1; p1=(struct student*)malloc(LEN); coutp1-nump1-score; ,void print1(struct student *head) coutnext; while (head) coutnumscorenext; ,main() struct student *head; /调用creat函数后建立了一个。
61、单向动态链表 head=creat() ; print1(head); ,插入操作,s,p,删除操作,本章小结,数组是一个由若干同类型变量组成的集合,它在内存中由连续存储单元组成,数组名本身就是指向这个起始地址的指针,所以数组作为参数传递时实际上传递的是地址。数组应用十分广泛,排序查找和字符串是其典型的应用;字符串数组实际上是元素是字符型的数组,由于C语言中字符串以0作为结束符,所以字符数组尺寸要比实际字符串包含的字符数多一个字节;,指针是C语言的重要特征之一,从本质上看,指针即变量在内存中的存储地址,它的使用可以使程序员直接对内存地址进行操作,提高程序的运行速度,还可以使用new和delete动态分配内存空间;结构体是重要的用户定义的数据类型,应用十分广泛,利用指向结构体的指针可以实现链表、二叉树等复杂的数据结构。
c语言中二维数组中维数的计算,数组指针字符串C语言程序设计-第4章.ppt相关推荐
- python二维数组表示_python中二维数组中的数如何表达
python二维数组如何挑选出一定范围的数值? 比如说有一个二维数组 13.1 13.2 13.3 13.4 15.5 15.0 45.2 22.3 22.3 3 [j for i in a for ...
- C语言:编写一个函数,计算二维数组中的最大元素,数组以指针的方式传递
/*编写一个函数,计算二维数组中的最大元素,数组以指针的方式传递*/ #include<stdio.h> #define N 4 #define M 3 int findmax(int ( ...
- php某列为键数组为值,PHP 将二维数组中某列值作为数组的键名 -- 超实用
有时候,想通过数组的中某字段值, 然后再在二维数组中获取存在该字段值的数组: 一般能想到的就是foreach 遍历比较一下跟该字段值一样,就获取到想要的数组,如下: //测试二维数组 $arr =ar ...
- 用STM32实现:摄像头扫到二维码后提取二维码中的信息分别放到数组中
摄像头扫到二维码后提取二维码中的信息分别放到数组中 把想要的信息编辑好放到二维码中(网上有好多在线生成二维码的工具) /** *作者:魏波 *时间:2017.6.6 * **/char name[6] ...
- C语言试题四十四之移动一维数组中的内容,若数组中由n个整数,要求把下标从0到p(p小于等于n-1)的数组元素平移到数组的最后。
1. 题目 请编写一个函数function,它的功能是:移动一维数组中的内容,若数组中由n个整数,要求把下标从0到p(p小于等于n-1)的数组元素平移到数组的最后. 2 .温馨提示 C语言试题汇总里可 ...
- python如何将数组里的数提取出来_python [:3] 实现提取数组中的数
搜索答案搜索不到,自己试了一把. 首先生成一维数组 a =np.array([1,2,3,4,5,6,7,8,9]) >>> print a [1 2 3 4 5 6 7 8 9] ...
- 1145: 零起点学算法52——数组中删数II
1145: 零起点学算法52--数组中删数II Time Limit: 1 Sec Memory Limit: 64 MB 64bit IO Format: %lld Submitted: 29 ...
- 找出数组中两数之和为指定值的所有整数对
一,问题描述 给定一个整型数组(数组中的元素可重复),以及一个指定的值.打印出数组中两数之和为指定值的 所有整数对 二,算法分析 一共有两种方法来求解.方法一借助排序,方法二采用HashSet 方法一 ...
- 将一个数组中的数右边为复数,左边为正数,中间为0
将一个数组中的数右边为复数,左边为正数,中间为0(不考虑大小) #include<iostream> using namespace std; void sort(int* a, int ...
最新文章
- Sitecore7.5 安装指南 -- 从.EXE文件安装Sitecore CMS
- 基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目
- [Python人工智能] 十五.无监督学习Autoencoder原理及聚类可视化案例详解
- 个税10% 人群_人群管理如何使我们的搜索质量提高27%
- 程序员面试金典 - 面试题 01.03. URL化(字符串)
- 实验一 软件工程准备
- Vue.js 运行机制全局概览
- 吴恩达深度学习 —— 2.4 梯度下降
- 201计算机基础知识,201年计算机应用基础备考练习题及答案
- html 怎么把表格不给输入,如何让用户在HTML5网页表单中输入持续时间而不会让他们烦恼?...
- wireshark之不显示ip问题(五)
- camera常见问题和调试方法
- 疯狂软件Oracle数据库视频
- 深入浅出Word2Vec原理解析
- postgresql安装postgis扩展模块
- Apache ShenYu源码阅读系列-Divide插件
- Docker升级Wekan
- 原生JS记忆翻牌小游戏
- Polar SC的C++实现
- EXCEL基础操作:隐藏,冻结,查找(搜索),锁定,保护
热门文章
- 【学习笔记】Keras库下的resnet源码分析
- 使用 DryIoc 替换 Abp 的 DI 框架
- 软件测试实验一 语句和判定覆盖测试设计
- vm虚拟机安装win11提示“这台电脑无法运行Windows 11”
- linux普通用户libusb访问usb,linux – 使用libusb-1.0作为非root用户访问USB设备
- 安防监控那些知名品牌!
- 深入浅出的webpack构建工具---HappyPack优化构建(九)
- ENVI: 如何进行图像的自动配准?
- 扩展正则表达式之花括号
- 本地破解WINDOWS XP 系统的登陆密码