null第七章 数 组第七章 数 组本章要点:
1.建立数组的概念;
2.掌握一维数组和多维数组的定义;
3.掌握数组的初始化和引用;
4.掌握字符串与字符数组.
5. 掌握用数组进行编程的技术。null 迄今为止,我们使用的都是属于基本类型的数据(整型、字符型、实型) ,C还提供了构造类型的数据,它们有数组类型、结构体类型、共用体类型。构造类型数据是由基本类型数据按一定的规则组成的,因此它们又被称为“导出类型”。本章只介绍数组。数组的基本概念:数组的基本概念:1、数组:一组具有相同数据类型的数据的有序的集合。
2、数组元素:数组中的元素。数组中的每一个数组元素具有相同的名称,不同的下标,可以作为单个变量使用。在定义一个数组后,在内存中使用一片连续的空间依次存放数组的各个元素。null3、数组的下标:是数组元素的位置的一个索引或指示。
4、数组的维数:数组元素下标的个数。根据数组的维数可以将数组分为一维、二维、三维、多维数组。
数组是同类型变量的集合,共用一个名字,用下标来区分;
◆每个变量称作数组元素;
◆按下标递增顺序在内存中存放;
◆使用几个下标区分变量,就称是几维数组。
◆一维数组与数学中的数列对应,二维数组与矩阵对应。很少使用三维及三维以上的数组。null7.1 一维数组的定义和引用
7.1.1一维数组的定义
定义方式:
类型说明符 数组名[ 常量表达式]
例:int a[10]
它表示数组名为a,此数组有10个元素。
说明:
(1)数组名定义规则和变量名相同;
(2)数组名的常量表达式用方括弧而不是圆括弧括起来
(3)常量表达式表示元素的个数,即数组长度。
例如:a[10]表示a数组共有10个元素,下标从0开始
分别为:a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]
注意:没有a[10]null (4)常量表达式中可以包括常量和符号常量,不能包含
变量,即数组的大小不能依赖于程序过程中变量的值。
例如:int n;
scanf(“%d”, &n);
int a[n];
是不合法的。
7.1.2 一维数组元素的引用
C语言规定,只能逐个引用数组元素而不能一次引用整个数组。
数组元素的表示形式为:
数组名[下标]
其中下标可以是整型常量或整型表达式。例如:
a[0]=a[5]+a[7]-a[2*3]null例7.1 数组元素的引用
main ( )
{
int i, a[10];
for ( i = 0; i <= 9; i++)
a[i] = i;
for ( i = 9; i >= 0; i--)
printf(“%d”, a[i]);
}
本例使a[0]到a[9]的值为0~9,然后按逆序输出。7.1.3 一维数组的初始化7.1.3 一维数组的初始化1、在定义数组时对数组元素赋以初值
方法:将初值依次写在花括号{ }内。
例如:
int a[4]={2,4,6,8}
其中:a[0]=2, a[1]=4, a[2]=6, a[3]=8null2、可以只给一部分元素赋值。
例如:int a[10]={0,1,2,3,4};
其中:a[0]=0, a[1]=1, a[2]=2, a[3]=3, a[4]=4,
a[5]=0, a[6]=0, a[7]=0, a[8]=0, a[9]=0
3、如果想使一个数组中全部元素值为0,可以写成:
int a[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
或:int a[10]={0}
不能写成:
int a[10]={0*10}
C语言不能给数组整体赋初值
注意:定义成static数组,不赋初值,系统会自动将全部元素赋以0值。(此处后面有介绍)null4、在对全部数组元素赋初值时,可以不指定数组长度。
例如:
int a[5]={0,1,2,3,4}
可以写成:
int a[ ]={0,1,2,3,4}
但是如果被定义的数组长度与提供初值的个数不相同时,则数组长度不能省略。
例如:
int a[10]={0,1,2,3,4};
只初始化了前5个元素,后5个元素为0。
7.1.4 一维数组程序举例7.1.4 一维数组程序举例例7.2 用数组来处理求Fibonacci数列问
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
。
main( )
{
int i;
int f[20] = {1, 1};
for( i = 2; i < 20; i++)
f[i] = f[i-2] + f[i-1];
for ( i = 0; i < 20; i++)
{
if ( i % 5 == 0)
printf(“\n”);
printf(“%12d”, f[i]);
}
}null例7.3 用冒泡法对10个数排序(由小到大)。
冒泡法:对将进行排序的数,相邻两个数进行比较,如果满足次序要求,保持两者位置不变,否则交换位置;第一次
比较第二次
比较第三次
比较第四次
比较第五次
比较第一次冒泡排序的结果n个数经过一次冒泡排序后,最大数(最小数)
将被交换到最后位置,但前面n-1数仍然无
序。下一次排序最后一位不必参加排序。第一次冒泡排序null算法结论:
如果有n个数参加冒泡排序,则要进行n-1趟比较。
在第j趟比较中有n-j+1个数参加排序,要进行n-j次两两比
较。本例中第2趟有5个数参加排序,进行了4次比较。第一次比较第二次比较第三次比较第四次比较第二次冒泡排序的结果第二次冒泡排序nullmain( )
{
int a[10];
int i, j, t;
printf(“input 10 numbers:\n”);
for ( i = 0; i < 10; i++)
scanf(“%d”, &a[i]);
printf(“\n”);
for ( j = 0; j < 9; j++)
{
for ( i = 0; i < 9 - j; i++)
{
if ( a[i] > a[i+1] )
{ t = a[i]; a[i] = a[i+1]; a[i+1] = t; }
}
}
printf(“the sorted numbers:\n”);
for( i = 0; i < 10; i++)
printf(“%d”,a[i]);
}7.2 二维数组的定义和引用7.2 二维数组的定义和引用7.2.1 二维数组的定义
二维数组定义的一般形式:
类型说明符 数组名 [ 常量表达式 ] [ 常量表达式 ]
例: float a[3][4], b[5][10];
此句定义了一个名为a的3行4列的实数数组和一个名为b的5行10列的实数的数组。
注意:不能写成:float a[3,4], b[5,10];
在C语言中,可以把二维数组看成特殊的一维数组,即把把一行看成一个元素,这些特殊的元素组成以一个特殊的一维数组。比如:我们可以把二维数组a[3][4]看成一个由
a[0], a[1], a[2]元素组成的数组,每个元素又由四个元素组成,例如a[0]由a[0][0],a[0][1], a[0][2], a[0][3]组成。null二维数组的存放顺序:
在C语言中,二维数组中的元素是按行存放的。
例如: a[2][3]的存放形式为 二维数组是多维数组的基础。其它多维数组的定义和元素存放形式类似二维数组。7.2.2 二维数组的引用7.2.2 二维数组的引用二维数组的元素的表示形式为:
数组名 [ 下标 ] [ 下标 ]
例如:a[2][3]表示的是a二维数组的第3行第4列的元素。
此处我们要特别注意下标不要超界。
注意:
1)下标可以是整型表达式,如a[2-1][2*2-1];
2)不能写成a[2,3]的形式;7.2.3 二维数组的初始化7.2.3 二维数组的初始化(1)按行给二维数组赋初值。例如:
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
(2)可以将所有数据写在一个花括号内,系统将按数组排
列顺序对各元素赋初值。例如:
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
(3)可以对部分元素赋初值。例如:
int a[3][4]={{1},{5},{9}};
它的作用是只对每行第一列赋初值,其他元素自动为0.
结果为:null也可以对各行中的某一元素赋初值,其他元素自动为0 :
int a[3][4]={{1},{0,6},{0,0,11}};
结果为:(4)如果对全部元素都赋初值,则定义数组时对第一维的长度可以不指定,但第二维的长度不能省。例如:
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
可以写成:
int a[ ][4]={1,2,3,4,5,6,7,8,9,10,11,12};7.2.4 二维数组程序举例7.2.4 二维数组程序举例例7.4 将二维数组 行和列元素互换,存到另一个二
维数组中。main( )
{
int a[2][3]={{1,2,3},{4,5,6}};
int b[3][2], i, j;
printf(“array a:\n”);
for ( i = 0; i <= 1; i++)
{
for(j =0; j <= 2; j++)
{
printf(“%5d”,a[i][j]);
b[j][i]=a[i][j];
}
printf(“\n”);
} printf(“array b:\n”);
for ( i = 0; i <= 2; i++)
{
for( j = 0; j <= 1; j++)
printf(“%5d”, b[i][j]);
printf(“\n”);
}
}null例7.5 有一个3X4的矩阵,要求编程求出其中最大的那个元素的值,以及其所在的行号和列号;nullmain ( )
{
int i, j, row = 0, colum = 0, max;
int a[3][4] = { {1, 2, 3, 4}, {9, 8, 7, 6}, {-10, 10, -5, 2} };
max = a[0][0];
for( i = 0; i <= 2; i++)
{
for(j=0;j<=3;j++)
{
if( a[i][j] > max )
{
max = a[i][j];
row = i;
colum = j;
}
}
printf(“max=%d,row=%d,colum=%d\n”,max,row,colum);
}7.3 字符数组7.3 字符数组7.3.1 字符数组的定义
字符数组的定义类似前面的数组定义。例如:
char c[4];
c[0]=‘S’; c[1]=‘U’; c[2]=‘S’; c[3]=‘E’; 上句的作用为:定义C为字符数组,包含4个元素。赋值后的状态为:
在C语言中,字符型和整型是互相通用的,因此上述定义句可以写为:
int c[4]null也可以定义和初始化一个二维字符数组,方法类似前述。
例如:
char diamond[5][5]={{‘ ’, ‘ ’, ‘*’},{‘ ’, ‘*’, ‘ ’, ‘*’},
{‘*’, ‘ ’, ‘ ’, ‘ ’, ‘*’} ,{‘ ’, ‘*’, ‘ ’, ‘*’}, {‘ ’, ‘ ’, ‘*’}};
7.3.3 字符数组的引用
可以引用字符数组中的一个元素,得到一个字符。
例7.6;输出一个字符串
main ( )
{
char c[10]={‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’,‘a’, ‘ ’, ‘b’,‘o’,‘y’};
int i;
for( i = 0; i < 10; i++)
printf(“%c”, c[i]);
printf(“\n”);
}null例7.7;输出一个
main ( )
{
char diamond[5][5]={{‘ ’, ‘ ’, ‘*’},{‘ ’, ‘*’, ‘ ’, ‘*’},
{‘*’, ‘ ’, ‘ ’, ‘ ’, ‘*’} ,{‘ ’, ‘*’, ‘ ’, ‘*’}, {‘ ’, ‘ ’, ‘*’}};
int i, j;
for( i = 0; i < 5; i++)
{
for ( j =0; j < 5; j++)
printf(“%c”, diamond[i][j]);
printf(“\n”);
}
}
运行结果为:
*
* *
* *
* *
*null7.3.4 字符串和字符结束标志
在C语言中,将字符串作为字符数组来处理。
为了测定字符串的实际长度C语言规定了一个“字符结束标志”,以字符‘\0’代表,由它前面的字符组成字符串。
系统字符串常量也自动加一个‘\0’作为结束符。
例如“C Program”共有9个字符,但在内存中占10个字节,最后一个字节‘\0’是由系统自动加上的。
结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。null另一种方法用字符串常量来使字符数组初始化。
例如
char c[ ]={“I am happy”};
也可以省略花括弧,直接写成
char c[ ]=“I am happy”;
(注意字符串的两端是用双引号而不是单引号括起来的)。
注意:上述字符串占用的空间长度是11而不是10。因为字符串常量的最后由系统加上一个‘\0’。
上述的初始化与下面的初始化等价。
char c[ ]={‘I’,‘ ’, ‘a’, ‘m ’, ‘ ’, ‘h ’, ‘a ’, ‘p ’, ‘p ’, ‘y ’, ‘ \0’};
而不与下面的等价:
char c[ ]={‘I’,‘ ’, ‘a’, ‘m ’, ‘ ’, ‘h ’, ‘a ’, ‘p ’, ‘p ’, ‘y ’};
前者的长度为11,后者的长度为10。null需要说明的是:字符数组并不要求它的最后一个字符为’\0’,甚至可以不包含’\0’ . 像以下这样写完全是合法的.
char c[5]={‘ C’, ‘ h’, ‘i ’, ‘n ’, ‘ a’ };
是否需要加上’\0’,完全根据需要决定。
系统对字符串常量自动加上一个’\0’,因此,为了使处理方法一致,便于测定字符串的实际长度,以及在程序中作相应的处理,在字符数组也常常人为加上一个’\0’,如:
char c[6]={‘ C’, ‘ h’, ‘i ’, ‘n ’, ‘ a’, ‘ \0’ };7.3.5 字符数组的输入输出7.3.5 字符数组的输入输出字符数组的输入输出可以有两种方法:
(1)逐个字符输入输出。用格式符“%c”输入或输出一个字符。如:
main ( )
{
char c[10]={‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’,‘a’, ‘ ’, ‘b’,‘o’,‘y’};
int i;
for ( i = 0; i < 10; i++)
printf(“%c”, c[i]);
printf(“\n”);
}
(2)将整个字符串一次输入或输出。用“%s”格式符。如:
char c[ ] = {“china”};
printf(“%s”,c);null注意:
1.输出字符不包括结束符’\0’ ;
2.用“%s”格式符输出字符串时,printf函数中的输出项是字符数组名,而不是字符元素名。比如不能写成:
printf(“%s”,c[0]);
正确写法为: printf(“%s”,c);
3.如果数组长度大于字符串实际长度,也只输出到遇\0’ 结束。
4.如果一个字符数组中含一个以上的’\0’ ,则遇到第一个’\0’ 输出就结束。
5、可以用scanf函数输入一个字符串,例如:
scanf(“%s”,c);
注意:scanf函数中输入项如果是字符数组名,不能再加地址
&,因为C程言中数组名代表该数组的起始地址(首地址)。7.3.6 字符串处理函数7.3.6 字符串处理函数 在C的函数库中提供了一些用来处理字符串的函数,使用方便。几乎所有版本的C都提供这些函数。下面是几种常用的函数。
1.puts(字符数组)
作用:将一个字符串(以’\0’结束的字符序列)输出到终端。
puts函数用的不多。puts函数输出字符串中可以包含转义字符。
2.gets(字符数组),
作用:从终端输入一个字符串到字符数组,并且得到一个函数值。该函数值是字符数组的起始地址。
如执行下面的函数:
gets(str)
从键盘输入:Computer
将输入的字符串” Computer”送给字符数组str(请注意送给数组的共有9个字符,而不是8个字符),函数值为字符数组str的起始地址。注意:用puts和gets函数只能输入或输出一个字符串,null3.strcat(字符数组1,字符数组2)
作用是:连接两个字符数组中的字符串,把字符串2接到字符串1的后面,结果放在字符数组1中,函数调用后得到一个函数值—字符数组1的地址。
例如: char str1[30]={“People’s Repubnic of ”};
char str2[ ]={“China”};
printf("%s",strcat(str1,str2));
输出:
People’s Republic of China
连接前后的状况见下图所示。说明:
(1)字符数组1必须足够大,以便容纳连接后的新字符串。
(2)连接前两个字符串的后面都有一个’\0’ ,连接时将字符串1后面的’\0’取消,只在新串最后保留一个’\0’ 。null4.strcpy(字符数组1,字符串2)
作用:将字符串2复制到字符数组1中去,
例如:char str1[10],str2[ ]={“China”);
strcpy(strl,str2);
执行后,str1的状态如图所示。
说明:
(1)字符数组1必须定义得足够大长度不应小于字符串2的长度;
(2)“字符数组1”必须写成数组名形式(如str1),“字符串2”可以是字符数组名,也可以是一个字符串常量。如: strcpy(str1, “China”);
(3)复制时连同字符串后面的’\0’一起复制到字符数组1中。
(4)不能用赋值语句将一个字符串常量或字符数组直接给一个字符数组。下面两行都是不合法的:
str1={“China”};
str1=str2;
而只能用strcpy函数处理。用赋值语句只能将一个字符赋给一个字符型变量或字符数组元素。
(5)可以用strncpy函数将字符串2中前面n个字符复制到字符数组1中去。例如:strncpy(str1,str2,2);null5. strcmp(字符串1,字符串2)
作用:比较字符串1和字符串2。
例如:
strcmp(str1,str2);
strcmp(”China”,”Korea”);
strcmp(str1, “Beijing”);
字符串比较规则:
对两个字符串自左至右逐个字符相比。按ASCII码值大小比较,直到出现不同的字符或遇到“\0“为止。如全部字符相同,则认为相等;若出现不相同的字符,则以第一个不相同的字符的比较结果为准。例如:
“A”<“B”,“computer”>“compare”, “CHINA”>“CANADA”
比较的结果由函数值带回。
(1)如果字符串1=字符串2,函数值为0.
(2)如果字符串1>字符串2,函数值为一正整数。
(3)如果字符串1<字符串2,函数值为一负整数。
null注意:对两个字符串比较,不能用以下形式
if(str1==str2) printf(“yes”);
而只能用
if(strcmp(str1,str2)==0) printf(“yes”);
6.strlen(字符数组)
作用:测试字符串长度的函数·函数的值为字符串中的实际长度,不包括‘\0’在内。如:
char str[10]=“china”;
printf(“%d”,strlen(str));
输出结果不是10也不是6,而是5。也可以直接测字符串常量的长度,如
strlen(“china”);
7.strlwr(字符串)
作用是将字符串中的大写字母换成小写字母。
8. strupr(字符串)
作用是将字符串中的小写字母换成大写字母。null强调:库函数并非C语言本身的组成部分,而是人们为使用方便而编写、提供大家使用的公共函数·时系统捉供的函数 数量和函数名、函数功能都不尽相同,使用时要小心,心要时查一下库函数手册。当然,有一些基本的函数。(包括函数名和函数功能)不同的系统所提供的是相同的,这就为程序的通用性提供了基础。
7.3.7字符数组应用举例7.3.7字符数组应用举例例7.8输入一行符,统计其中有多少个单词,单词之间用空格分隔开·
解题的思路:
单词间的数目由空格出现的次数决定(连续的空格做为出现一次空格;开头的空格不统计在内)
如果测出某一个字符为非空格,而它的前面的字符是空格,则表示“新的单词开始”,此时使num(单词数)累加1.如果当前字符为非空格而其前面的字符也是非空格,则意味着仍然是原来那个单词的继续,num不应再累加1.
前面一个字符是否空格可以从一个标志变量word的值看出,若word=0,则表示前一个字符是空格;如果word=1,则意味前一个字符为非空格。null程序中变量 i 作为循环变量,num用来统计单词个数,word作为单词的标志,算法见下图:null#include
main ( )
{
char string[81];
int i, num = 0, word = 0;
char c;
gets(string);
for ( i = 0; ( c = string[i]) != ‘\0’; i++)
{
if (c == ‘ ‘ )
{
word = 0;
}
else if (word == 0)
{
word = 1;
num++;
}
}
printf(“There are %d words in the line.\n”, num);
}null例7.9 有3个字符串,要求找出其中最大者。
今设一个1二维的字符数组str,大小为3X20,即有3行20列,每一行可以容纳20个.可以把str[0],str[1],str[2]看作3个一维字符数组,可以把它们如同一维数组那样进行处理,可以用gets函数分别读入。经过二次比较,可以得到最大者,把它放入一维数组string中。
main( )
{
char string[20];
char str[3][20];
int i;
for( i =0; i<3; i++ )
gets(str[i]);
if (strcmp(str[0], str[1]) > 0)
strcpy(string, str[0]);
else
strcpy(string, str[1]);
if ( strcmp(str[2], string) > 0 )
strcpy(string, str[2]);
printf(“\n the largest string is: \n %s\n”, string);
}