第 8章 数组类型第 8章 数组类型
8.1 一维数组
8.2 二维数组与多维数组
8.3 字符数组与字符串
8.4 重命名类型
8.5 程序设计举例第 8章 数组类型
8.1 一维数组
8.1.1 一维数组的定义形式,类型标识符 数组名[常量];
类型标识符描述的是数组分量的类型,是定义数组类型的基类型,可以是任何类型。数组名代表数组所占存储空间的首地址。 常量表示数组的长度,即数组中分量的个数。
第 8章 数组类型例如,定义数组,描述下列数据:
(1) 100个整数:
int num[ 100];
(2) 1000个学生 C语言课程的成绩:
float ccj[ 1000];
(3) 一年中每月的天数:
int month[ 12];
(4) 100种商品的价格:
float price[ 100];
(5) 500个字符类型的数据:
char ch[ 500];
第 8章 数组类型说明:
(1) 数组名命名规则和变量名命名规则相同,都遵循标识符命名规则 。
(2) 数组的长度可以用符号常量描述,但不能用变量,C语言不提供动态数组 。
(3) 数组以线性方式将数组分量依次存储,所占空间等于各分量所占空间之和,即数组分量个数乘以基类型数据所占空间 。
第 8章 数组类型
8.1.2
数组元素称为下标变量,下标变量通过数组名,下标表达式和中括号运算来描述 。
下标变量的形式为,数组名 [ 下标表达式 ]
例如,对以上定义的 num数组,ccj数组,num数组的 100个分量为 num[ 0],num[ 1],…,num
[ i],…,num[ 99],每个分量存放一个整数,num
[ i] 相当于一个 int型变量; ccj数组的 1000个分量为 ccj
[ 1],ccj[ 2],…,ccj[ i],…,ccj[ 999],每个分量对应一个学生的成绩,ccj[ i] 相当于一个 float型变量 。
第 8章 数组类型说明:
(1) 下标的取值范围从 0到数组长度减 1。
(2) 下标变量相当于基类型变量 。
(3) 下标往往对应于循环控制变量,通过循环,通过下标的变化完成数组所有元素的操作,即整个数组的操作 。
(4) 下标往往隐含有特定的含义 。
(5) 对于下标出界,C语言不进行语法检查。
第 8章 数组类型如果希望下标为 i的分量对应第 i个数据,可将定义数组的大小增 1,如:
int num[ 101] ;
float ccj[ 1001] ;
100 个 整 数 用 num 数组的分量 num [ 1 ],num
[ 2],…,…num[ 1] …,num[ 100] 描述,num[ i]
对应于第 i个整数 。 1000个学生的 C语言成绩用 ccj数组的分量 ccj[ 1],ccj[ 2],…,ccj[ i],ccj[ 1000] 描述,
ccj[ i] 对应于第 i个学生的成绩 。
第 8章 数组类型
8.1.3 一维数组的初始化初始化形式:
存储类别 类型 数组名 [ 常量 ] ={常量 1,
常量 2,…,常量 n};
初始化数据用花括号括起。
第 8章 数组类型例如:
(1) static int month[ 12] ={31,29,31,30,31,30,
31,31,30,31,30,31};
month[ 0] =31,month[ 1] =29,month[ 2] =31,
month[ 3] =30,month[ 4] =31,month[ 5] =30,month
[ 6] =31,month[ 7] =31,month[ 8] =30,month[ 9]
=31,month[ 11] =30,month[ 12] =31
(2) static char ch[ 5] ={′a′,′e′,′i′,′o′,′u′};
ch[ 0] =′a′,ch[ 1] =′e′,ch[ 2] =′i′,ch[ 3] =′o′,
ch[ 4] =′u′
第 8章 数组类型说明:
(1) 对静态存储数组和外部存储数组,默认初值为 0。
(2) 可以只给一部分数组元素初始化 。 例如:
static int a [ 50] ={70,75,60,80,90};
相当于 a[ 0] =70,a[ 1] =75,a[ 2] =60,a[ 3] =80,
a[ 4] =90,后面没有给出的数组元素之值全部为 0。
第 8章 数组类型
(3) 对数组中全部元素给定初值,可以不给定数组长度,它的长度为后面给出的初值个数 。 例如:
static float x[ ] ={1.5,2.5,3.5,4.5,5.5};
数组 x有 5个数组元素 x[ 0],x[ 1],x[ 2],x
[ 3],x[ 4],长度为 5。
(4) 若仅给部分数组元素赋值,则不能省略数组长度。
第 8章 数组类型例 8 – 1 求 10个数的最大值与最小值,10个数用数组描述。
/*程序 8 – 1 求 10个数的最大值与最小值 */
main (
{float a[ 10];
int i;
float max=-1e20,min=1e20;
for ( i=0; i<=9; i++) /*输入 10 个数 */
scanf (″%f″,&a[ i] );
for ( i=0; i<=9; i++) /*求最大值与最小值 */
{if( a[ i] >max) max=a[ i];
if( a[ i] <min) min=a[ i];
}
printf ( ″最大值 =%f,最小值 =%f″,max,min);
}
第 8章 数组类型例 8 – 2 求某班 50个学生 C语言课程的平均成绩及每个学生与平均成绩之差 。
/*程序 8 - 2〓 求 C语言课程的平均成绩及每个学生与平均成绩之差 */
main(
{float ccj[ 51]; /*C语言成绩数组 */
int i;
float tcj=0.0;
float av,cav[ 51]; /*平均成绩 av,与平均成绩之差数组 cav*/
for ( i=1; i<=50; i++) /*输入每个学生成绩 */
第 8章 数组类型
{printf( ″请输入第 %d个学生成绩,″,i);
scanf (―%f‖,&ccj[ i] );
}
for ( i=1; i<=50; i++) /*求平均成绩 */
tcj+=ccj[ i];
av=tcj/50;
for ( i=1; i<=50; i++) /*求与平均成绩之差 */
cav[ i] =ccj[ i] -av;
printf( ″C语言课程的平均成绩 =%5.2f\n″,av); /*输出 */
for ( i=1; i<=50; i++
printf( ″第 %d个学生与平均成绩之差 =%5.2\n″,i,cav[ i]);
}
第 8章 数组类型例 8 - 3 用一维数组求 Fibonacci数列前 20项,要求每行输出 5个数 。
/
*
程序
8
-
3
,
求
F
i
b
o
n
a
c
/*程序 8-3,求 Fibonacci数列前 20项 */
main( )
{static int a[ 20] ={1,1}; /*存放 Fibonacci数列前 20项的数组 */
int i;
for( i=2; i<20; i++
f[ i] =f[ i-1] +f[ i-2];
printf( ″Fibonacci数列前 20项如下,\n″);
for( i=2; i<20; i++
{printf( ″%8d″,f[ i]);
if( i%5==0) printf( ″\n″); /*if语句用来控制换行 */
}
}
第 8章 数组类型运行结果:
Fibonacci数列前 20项如下:
1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
第 8章 数组类型
8.1.4 一维数组作函数参数例 8-4 将例 8-2中求 C语言课程平均成绩改用函数实现 。
函数如下:
float avf( xcj) /*求 C语言课程平均成绩 */
float xcj[ 51] ;
{int i;
float sum=0.0,tav;
for ( i=1; i<=50; i++)
sum+=xcj[ i] ;
tav=sum/50;
return( tav) ;
}
第 8章 数组类型主函数中调用函数 avf( ) 来求平均成绩,
av=avf( ccj) ;
此时,实参数组为 ccj,对应的形参数组为 xcj,调用时将实参数组 ccj首地址传递给形参数组 xcj。 请注意本例中数组的第一个分量 ccj[ 0],xcj[ 0] 无意义 。
对形参数组可以不指定数组大小,在定义数组时数组名后跟空的中括号 。 在函数中另设一个参数,传递数组元素的个数 。 如此在函数中实现变相动态数组 。
第 8章 数组类型例 8-5 将上例中函数延伸考虑为求 n个学生 C语言课程平均成绩 。
函数如下:
float avf( xcj,n) /*求 n个学生 C语言课程平均成绩 */
float xcj[ ],n;
{int i;
float sum=0.0,tav;
for ( i=1; i<=n; i++)
sum+=xcj[ i] ;
tav=sum/n;
return( tav) ;
}
第 8章 数组类型
8.2 二维数组与多维数组
8.2.1 二维数组的定义形式:类型标识符 数组名 [ 常量 1] [ 常量 2] ;
n维数组的定义形式,类型标识符 数组名 [ 常量 1]
[ 常量 2] …[ 常量 n] ;
类型标识符描述的同样是数组分量的类型,是定义数组类型的基类型,可以是任何类型 。 数组名代表数组所占存储空间的首地址 。 常量分别表示数组相应维的长度,数组长度以及数组中分量个数分别等于常量 1,常量 2,…,
常量 n。
第 8章 数组类型
(1) 上述 100个班,每班 50个学生一门课程的成绩,
定义如下二维数组描述:
float cj[ 100] [ 50] ; /*第一维对应班级,第二维对应学生 */
(2) 1000个学生,30门课程的成绩,定义如下二维数组描述:
float acj[ 1000] [ 30] ; /*第一维对应学生,第二维对应课程 */
(3) 上述某高校社会实践调查数据,定义如下三维数组描述:
int b[ 3] [ 2] [ 3] ; /*第一维对应年级,第二维对应性别,第三维对应交通工具 */
第 8章 数组类型
8.2.2 二维数组的引用下标变量的形式为,数组名 [ 下标表达式 1] [ 下标表达式 2]
多维数组下标变量的形式为:数组名 [ 下标表达式 1]
[ 下标表达式 2] …[ 下标表达式 n]
例如,对以上定义的 acj数组 3000个分量分别为,acj[ 0]
[ 0],acj[ 0] [ 1],…,acj[ 0] [ 29],acj[ 1] [ 0],
acj[ 1] [ 1],…,acj[ 1] [ 29],…,acj[ 999] [ 0],
acj[ 999] [ 1],…,acj[ 999] [ 29],左边下标变化最慢,右边下标变化最快,右边下标变化一遍,左边下标才变化一次 。
每个分量对应一个学生一门课程的成绩,acj[ i][ j]
相当于一个 float型变量。
第 8章 数组类型说明:
(1) 每个下标的取值范围从 0到数组长度减 1,下标变量同样相当于基类型变量 。
(2) 对于多维数组整体操作的完成需用多重循环,
一个下标对应于一重循环控制变量 。 二维数组的整体操作用两重循环完成,外重循环对应下标 1,内重循环对应下标 2。
(3) 其它类似于一维数组处理。
第 8章 数组类型
8.2.3 二维数组的初始化初始化形式:
存储类别 类型 数组名 [ 下标 1] [ 下标 2] ={常量 1,常量
2,…,常量 n};
例如:
static int a[ 3] [ 4] ={1,2,3,4,5,6,7,8,9,10,11,12};
a[ 0] [ 0] =1,a[ 0] [ 1] =2,a[ 0] [ 2] =3,a[ 0] [ 3] =4,
a[ 1] [ 0] =5,a[ 1] [ 1] =6,a[ 1] [ 2] =7,a[ 1] [ 3] =8,
a[ 2][ 0] =9,a[ 2][ 1] =10,a[ 2][ 2] =11,a[ 2][ 3] =12
第 8章 数组类型说明:
(1) 二维数组的初始化可以分行进行 。 例如,上面的 a
数组初始化还可以表示为:
static int a[ 3] [ 4] ={ {1,2,3,4},{5,6,
7,8},{9,10,11,12}};
而定义 4行 3列的 b数组可以表示为:
static int b[ 4] [ 3] ={{1,2,3},{4,5,6},
{7,8,9},{10,11,12}};
(2) 可以只对数组中部分元素初始化 。 例如:
a[ 0] [ 0] =1,a[ 0] [ 1] =2,a[ 1] [ 0] =5,a
[ 2] [ 0] =9,其它分量初值取默认值,为 0。
第 8章 数组类型
(3) 如果对二维数组中全部元素初始化,则定义数组时第一维的长度可以省略,但第二维的长度不能省略 。 例如:
static int a[ 3] [ 4] ={1,2,3,4,5,6,7,8,9,
10,11,12};
static int a[ ] [ 4] = {1,2,3,4,5,6,7,8,
9,10,11,12};
static int a[ ] [ ] = {1,2,3,4,5,6,7,8,
9,10,11,12};
因为两个维数都省略时,可以理解为 1*12,12*1,3*4、
4*3,2*6,6*2等多种形式,会发生混淆,故只能省略第一个维数 。
第 8章 数组类型
(4) 如果对二维数组按行进行初始化,则定义数组时第一维的长度也可以省略 。
static int a[ ] [ 4] ={{1,2},{5},{9}};
对于二维数组与多维数组作函数参数跟一维数组作函数参数类同处理,但对形参数组,只有第一维的大小可以省略,第二维及其它高维的大小均不能省略 。
第 8章 数组类型例 8-6 从键盘输入 50个学生 8门课程成绩,求每个学生的总成绩与平均成绩 。
/*程序 8-6,求总成绩及平均成绩 */
main(
{float cj[ 51][ 9];
int i,j;
float tcj[ 51],acj[ 51];
void tcjf( );
void acjf( );
for( i=1; i<=50; i++) /*输入成绩 */
{printf( ″请输入第 %d个学生 8门课程成绩,″,i);
for( j=1; j<=8; j++
scanf( ″%f″,&cj[ i][ j]);
}
第 8章 数组类型
tcjf( cj,tcj); /*调用函数 tcjf( )求总成绩 */
acjf( tcj,acj); /*调用函数 acjf ( )求平均成绩 */
printf( ″所求学生总成绩与平均成绩如下,\n″); /*输出处理结果 */
for( i=1; i<=50; i++
printf( ″第 %d个学生总成绩 =%6.2f,平均成绩 =%5.2f\n″,tcj[ i],
acj[ i]);
}
void tcjf( xcj,xtcj) /*求总成绩函数 */
float xcj[ 51][ 9],xtcj[ 51];
{int i,j;
for( i=1; i<=50; i++)
for( xtcj[ i] =0.0,j=1; j<=8; j++
xtcj[ i] +=xcj[ i][ j];
}
void acjf( xtcj,xacj) /*求平均成绩 */
float xtcj[ 51],xacj[ 51];
{int i;
for( i=1; i<=50; i++)
xacj[ i] = xtcj[ i] /8;
}
第 8章 数组类型例 8-7 编写程序,求两个 3× 4的整数矩阵之和。
/*程序 8-7,求两个 3× 4的矩阵之和 */
main( )
{int a[ 3][ 4],b[ 3][ 4];
int i,j;
int c[ 3][ 4];
for( i=0; i<3; i++) /*输入矩阵 a */
for( j=0; j<4; j++
scanf( ″%d″,&a[ i][ j]);
for( i=0; i<3; i++) /*输入矩阵 b */
for( j=0; j<4; j++
scanf( ″%d″,&b[ i][ j]);
for( i=0; i<3; i++) /*计算矩阵 c */
for( j=0; j<4; j++
第 8章 数组类型
c[ i][ j] =a[ i][ j] +b[ i][ j];
printf( ″所求和矩阵如下,\n″); /*输出处理结果 */
for( i=0; i<3; i++) /*输出矩阵 c */
{for( j=0; j<4; j++
printf( ″%6d″,c[ i][ j]);
printf( ″\n″);
}
}
输入数据,1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2
运行结果:
所求和矩阵如下:
3 3 3 3
3 3 3 3
3 3 3 3
第 8章 数组类型
8.3 字符数组与字符串
8.3.1 字符数组
1,字符数组的定义字符数组的定义和上面讲述的数组定义形式完全一样,只是字符数组的基类型为特定的字符类型 。 例如:
char ch1[ 10],ch2[ 3] [ 4],ch3[ 2] [ 3] [ 4] ;
定义了一个一维字符数组 ch1,含有 10个元素; 定义了一个二维字符数组 ch2,含有 12个元素;定义了一个三维字符数组 ch3,含有 24个元素 。
第 8章 数组类型
2.
字符数组的引用通过字符数组的下标变量进行 。 字符数组的下标变量相当于字符类型的变量 。
3.
对于字符数组的初始化,最易理解的方式是将字符一一赋给字符数组元素。
第 8章 数组类型例如:
(1) static char city[ 8] ={′c′,′h′,′a′,′n′,′g′,′s′,
′h′,′a′};
如果只给一部分字符数组的元素初始化,没有给出值的字符数组元素之默认值为空格字符 。
(2) char city[ 8] ;
city[ 0] =′c′,city[ 1] =′h′,city[ 2] =′a′,city[ 3]
=′n′,city[ 4] =′g′; city[ 5] =′s′,city[ 6] =′h′,
city[ 7] =′a′;
第 8章 数组类型
8.3.2 字符串
1,输入输出输入输出用 scanf( ),printf( )函数完成,采用 ″%s″格式 。 输入输出参数用字符数组名 。 如:
main( )
{char comp[ 9] ;
scanf( ″%s″,comp) ; /*本身就是地址,不需加地址运算符 */
printf( ″COMP=%s″,comp) ;
}
输入数据,CHINAONE
运行结果,COMP=CHINAONE
第 8章 数组类型
2,
puts( )与 gets( )函数包含在头文件 stdio.h中,字符串处理函数包含在头文件 string.h中,用# include ″string.h″指明 。
在以下的函数中,参数 str,str1,str2为字符数组类型或指向字符的指针类型 。
(1) puts( str)
输出指定字符串。 参数可以为字符串常量。
第 8章 数组类型
(2) gets( str)
从键盘输入字符串至字符数组 str中,输入的字符串可以包含空格 。
函数的返回值是字符数组 str的首地址 。
(3) strcpy( str1,str2)
将 str2的值复制到 str1中,实际上完成字符串的赋值操作 。
要求 str1的长度大于 str2的长度,第二个参数可以是字符串常量。
第 8章 数组类型
(4) strcat ( str1,str2)
将 str2的值连接到 str1中原有值的后面 。
(5) strcmp( str1,str2)
比较 str1和 str2,若两者相同,返回函数值为 0;若
str1大于 str2,返回函数值为一个正整数; 若 str1小于
str2,返回函数值为一个负整数 。
第 8章 数组类型
(6) strlen( str)
函数的返回值为字符串的实际长度 。
(7) strlwr( str)
将字符串中大写字母转换成小写字母 。
(8) strupr( str)
将字符串中小写字母转换成大写字母。
第 8章 数组类型
8.3.3 字符串数组
(1) 100
char city[ 100] [ 16] ; /*假定城市名不超过 16个字符 */
100个城市名分别用 city[ 0],city[ 1],…,city
[ i],…,city[ 99] 描述,city[ i] 相当于一字符数组 。
(2) 1000
char book[ 1000] [ 30] ; /*假定书名不超过 30个字符 */
1000本书名分别用 book[ 0],book[ 1],…,book[ 999]
描述,book[ i] 相当于一字符数组 。
第 8章 数组类型例 8-8 用字符数组输出下面图案:
***
*****
***
程序如下:
/*程序 8-8,用字符数组输出图案 */
main( )
{static char ch[ 3][ 5] ={″ ***″,″*****″,″ ***″};
puts( ch[ 0]);
printf( ″\n″);
puts( ch[ 1]);
printf( ″\n″);
puts( ch[ 2]);
printf( ″\n″);
}
第 8章 数组类型例 8-9 输入一行字符,统计数字字符,字母字符及其它字符的个数。
/*程序 8-9,统计数字字符,字母字符及其它字符的个数 */
main( )
{char line[ 81]; /*假定一行不超过 80个字符 */
int i;
int num[ 3] ={0,0,0};
gets( line);
for( i=0; line[ i]! =′\0′; i++
if( line[ i] >=′0′&&line[ i] <=′9′) num[ 0] ++;
else if(( line[ i] >=′a′&&line[ i] <=′z′)‖ (line[ i] >=′A′&&line
[ i] <=′Z′)) num[ 1] ++;
else num[ 2] ++;
printf( ″数字字符数 =%d字母字符数 =%d其它字符数 =%d″,num
[ 0],num[ 1],num[ 2]);
}
第 8章 数组类型例 8-10 求 80个字符串中的最大者。
main( )
{char str[ 80][ 20]; /*假定字符串的最大长度不超过 20个字符 */
int i;
char mstr[ 20];
for( i=0; i<20; i++
gets( str[ i]);
strcpy( mstr,str[ 0]);
for( i=1; i<20; i++
if( strcmp( str[ i],mstr) >0) strcpy( mstr,str[ i]);
printf( ″字符串中的最大者 =%s″,mstr);
}
第 8章 数组类型
8.4 重命名类型
8.4.1 重命名类型方法一般形式,typedef 已有类型 新类型名;
如:
(1) typedef int integer; /*重命名整型 */
integer i,j;
第 8章 数组类型
(2) typedef int COUNT; /*命名一计数类型 COUNT*/
COUNT n1,n2;
(3) typedef int NUM[ 100]; /*命名一整型数组类型 NUM*/
NUM n;
(4) typedef char STRING[ 81]; /*命名一字符串类型
STRING*/STRING str1,str2;
(5) typedef struct
{int day;
int month;
int year;
} DATE; /*命名一结构体类型 DATE*/
DATE date1,date2;
第 8章 数组类型
8.4.2 重命名类型的作用
(1) 有利于加强数据描述的针对性,增加程序的可读性。
(2) 有利于程序的通用和移植。
(3) 有利于减少程序书写的工作量。
第 8章 数组类型
8.4.3 几点说明
(1) 用 typedef只能对已有类型增加一个名字,而不能自己去创造一个新的类型 。
(2) 用 typedef可以对各种已有类型增加新的类型名,但不能用来定义变量 。
(3) 重命名类型,可以将数组类型与数组变量分离开来 。
(4) 重命名类型与编译预处理不同,是在编译时处理,
实际上也并不是作简单的字符串替换 。
(5) 常将一些常用的重命名类型单独放一文件中,需要时用# include指令将它们包含至程序中 。
第 8章 数组类型
8.5 程序设计举例例 8-11 求 n个实数的和,积,最大值,最小值 。
/*程序 8-11,求 n个数的和,积,最大值,最小值 */
# define N 100
main( )
{float a[ N];
int n;
int i;
float sf( );
float mf( );
float max( );
float min( );
scanf( ″%d″,&n);
for( i=1; i<=n; i++
scanf( ″%f″,&a[ i]);
第 8章 数组类型
printf( ″和 =%8.3f\n″,sf( a,n));
printf( ″积 =%8.3f\n″,mf( a,n));
printf( ″最大值 =%8.3f\n″,max( a,n));
printf( ″最小值 =%8.3f\n″,min( a,n));
}
float sf( xa,xn) /*求和 */
float xa[ ];
int xn;
{int i;
float s=0;
for( i=1; i<=xn; i++
s+=xa[ i];
return( s);
}
第 8章 数组类型
float mf( xa,xn) /*求积 */
float xa[ ];
int xn;
{int i;
float m=1;
for( i=1; i<=xn; i++
m*=xa[ i];
return( m);
}
float max( xa,xn) /*求最大值 */
float xa[ ];
int xn;
{int i,k=1; /*k存放最大值下标 */
for( i=1; i<=xn; i++
if( xa[ i] >xa[ k] ) k=i;
return( xa[ k]);
}
第 8章 数组类型
float min( xa,xn) /*求最小值 */
float xa[ ];
int xn;
{int i,k=1; /*k存放最小值下标 */
for( i=1; i<=xn; i++
if( xa[ i] <xa[ k] ) k=i;
return( xa[ k]);
}
第 8章 数组类型例 8-12 给定一 4× 3的整数矩阵,求矩阵中最小值及最小值所在行,列号 。
/*程序 8-12,求矩阵中最小值及位置 */
main( )
{int a[ 4][ 3]; /*存放矩阵 */
int i,j;
int min,row,col; /*存放最小值及最小值所在行,列号 */
for( i=0; i<4; i++) /*输入矩阵 */
for( j=0; j<3; j++
scanf( ″%d″,&a[ i][ j]);
row=0; col=0; min=a[ 0][ 0]; /*初始化最小值及最小值所在行,列号 */
for( i=0; i<4; i++) /*求最小值及最小值所在行,列号 */
for( j=0; j<3; j++
if( a[ i][ j] <min
{min=a[ i][ j];
row=i; col=j;
}
printf( ″最小值为 %d,处在 %d行 %d列 ″,min,row,col);
第 8章 数组类型例 8-13 将 n个实数由大到小排序。
void sort1( a,n) /*选择排序函数 */
float a[
int n;
{int k,i,j; /*k最大值下标,i,j循环控制变量 */
float t; /*中间变量,用于两个数的交换 */
for( i=0; i<n-1; i++
{k=i; /*求最大值下标 */
for( j=i+1; j<n; j++
if( a[ j] >a[ k] ) k=j;
t=a[ i]; a[ i] =a[ k]; a[ k] =t; /*进行交换 */
}
}
第 8章 数组类型算法二,冒泡排序。
void sort2( a,n) /*冒泡排序函数 */
float a[ ];
int n;
{int i; /*一轮比较的循环控制变量 */
int flag; /*标志变量,为 1有交换,为 0无交换 */
float t; /*中间变量,用于两个数的交换 */
do
{flag=0; /*先假定无交换,已排好序 */
for( i=0; i<n—2; i++
if( a[ i+1] >a[ i
{t=a[ i]; a[ i] =a[ i+1]; a[ i+1] =t; /*进行交换 */
flag=1; /* 有交换,标志变量的值改变为 1*/
}
}while( flag==1);
}
第 8章 数组类型例 8-14 筛法求 2~1000之间的所有素数。
/*程序 8-14,筛法求 2至 1000之间的所有素数 */
main( )
{int a[ 1000]; /*筛子数组 */
int i;
int minp,double; /*minp筛选种子,double倍数 */
int n=0; /*素数个数,用于输出格式控制 */
for( i=2; i<1000; i++) /*建立筛子 */
a[ i] =1;
minp=2; /*筛选种子初始化 */
while( minp<500) /*完成整个筛选 */
{double=2*minp; /*倍数初始化 */
第 8章 数组类型
while( double<1000 ) /*完成一轮筛选 */
{a[ double] =0; /*筛去当前倍数 */
double+=minp; /*计算下一个倍数 */
}
do/*计算下一轮筛选种子 */
{minp++; }
while( a[ minp] ==0);
}
printf( ″2至 1000之间的所有素数如下,\n″);
for( i=2; i<1000; i++
if( a[ i] ==1
{printf( ″%6d″,i);
n++;
if( n%5==0) printf( ″\n″); /*5个素数输出在一行 */
}
}
第 8章 数组类型例 8-15 求 10~1000之间的回文数。
/*程序 8-15,求 10~1000之间的回文数 */
main( )
{int i,x;
int a[ 8],j;
int b,e;
int flag;
for( i=10; i<1000; i++
{j=0; x=i; /*将数字分离,用一数组存放 */
while( x>0
{a[ j] =x%10;
x/=10;
j++;
}
第 8章 数组类型
flag=1; /*先假定 i为完数 */
b=0; e=j-1;
while( b<e&&flag) /*判断 i是否为完数 */
if( a[ b]! =a[ e]) flag=0;
else {b++; e- -; }
tf(flag) printf( ″%6d″,i);
}
}
第 8章 数组类型例 8-16 从 n个数据中查找一个数。
float serach( a,n,x) /* 折半查找函数 */
float a[ ],x;
int n;
{int k,flag;
int b=0,e=n-1,d;
flag=0;
do
{d=( b+e)/2;
if( a[ d] ==x) {k=d; flag=1; }
else if( a[ d] >x) e=d;
else b=d;
}while( b<e&&![KG-*4]flag);
if( flag==0) k=0; /*没找到 */
return( k);
}
第 8章 数组类型例 8-17 某班有 50个学生,期终考试 8门课程 。 求每个学生总成绩,平均成绩,并按总成绩高分到低分输出 。
/*程序 8-17,成绩处理程序 */
char st[ 51][ 12]; /*采用外部数组实现数据传递 */
float cj[ 51][ 9];
float tacj[ 51][ 3];
main( )
{void input( ); /*调用函数申明 */
void count( );
void sort( );
void output( );
input( ); /*调用输入函数 */
count( ); /*调用计算函数 */
sort( ); /*调用排序函数 */
output( ); /*调用输出函数 */
}
第 8章 数组类型
void input( ); /*输入函数 */
{int i,j;
for( i=1; i<=50; i++
{printf( ″请输入第 %d个学生姓名,成绩,\n″);
scanf( ″%s″,st[ i]);
for( j=1; j<=8; j++
scanf( ″%f″,&cj[ i][ j]);
}
}
void count( ); /*计算函数 */
{int i,j;
for( i=1; i<=50; i++)
第 8章 数组类型
{tacj[ i][ 1] =0;
for( j=1; j<=8; j++
tacj[ i][ 1] +=cj[ i][ j];
tacj[ i][ 2] =tacj[ i][ 1] /8;
}
}
void sort( )/*排序函数 */
{int i,flag;
char ts[ 12];
float tc;
do
{flag=0;
for( i=1; i<=50; i++
if( tacj[ i+1][ 1] >tacj[ i][ 1
{strcpy( ts,st[ i]); strcpy( st[ I],st[ i+1]);
第 8章 数组类型
strcpy( st[ i+1],st); /*交换姓名 */
for( j=1; j<=8; j++) /*交换 8门课程成绩 */
{t=cj[ i][ j]; cj[ i][ j] =cj[ i+1][ j]; cj[ i+1]
[ j] =t; }
t=tacj[ i][ 1]; tacj[ i][ 1] =tacj[ i+1][ 1]; tacj
[ i+1][ 1] =t; /*交换总成绩 */
t=tacj[ i][ 2]; tacj[ i][ 2] =tacj[ i+1][ 2]; tacj
[ i+1][ 2] =t; /*交换平均成绩 */
flag=1;
}
}while( flag==1);
}
第 8章 数组类型
void output( )/*输出函数 */
{int i;
printf( ″50个学生成绩处理结果如下,\n″);
printf( ″ 姓名 课程 1 课程 2 课程 3 课程 4 课程 5 课程 6 课程 7
课程 8 总成绩 平均成绩 名次 \n″);
for( i=1; i<=50; i++
{printf( ″%8s″,st[ i]);
for( j=1; j<=8; j++
printf( ″%7.2f ″,cj[ i][ j]);
printf( ″%7.2f%7.2f%5d″,tacj[ i][ 1],tacj[ i][ 2],
i);
printf( ″\n″);
}
}
8.1 一维数组
8.2 二维数组与多维数组
8.3 字符数组与字符串
8.4 重命名类型
8.5 程序设计举例第 8章 数组类型
8.1 一维数组
8.1.1 一维数组的定义形式,类型标识符 数组名[常量];
类型标识符描述的是数组分量的类型,是定义数组类型的基类型,可以是任何类型。数组名代表数组所占存储空间的首地址。 常量表示数组的长度,即数组中分量的个数。
第 8章 数组类型例如,定义数组,描述下列数据:
(1) 100个整数:
int num[ 100];
(2) 1000个学生 C语言课程的成绩:
float ccj[ 1000];
(3) 一年中每月的天数:
int month[ 12];
(4) 100种商品的价格:
float price[ 100];
(5) 500个字符类型的数据:
char ch[ 500];
第 8章 数组类型说明:
(1) 数组名命名规则和变量名命名规则相同,都遵循标识符命名规则 。
(2) 数组的长度可以用符号常量描述,但不能用变量,C语言不提供动态数组 。
(3) 数组以线性方式将数组分量依次存储,所占空间等于各分量所占空间之和,即数组分量个数乘以基类型数据所占空间 。
第 8章 数组类型
8.1.2
数组元素称为下标变量,下标变量通过数组名,下标表达式和中括号运算来描述 。
下标变量的形式为,数组名 [ 下标表达式 ]
例如,对以上定义的 num数组,ccj数组,num数组的 100个分量为 num[ 0],num[ 1],…,num
[ i],…,num[ 99],每个分量存放一个整数,num
[ i] 相当于一个 int型变量; ccj数组的 1000个分量为 ccj
[ 1],ccj[ 2],…,ccj[ i],…,ccj[ 999],每个分量对应一个学生的成绩,ccj[ i] 相当于一个 float型变量 。
第 8章 数组类型说明:
(1) 下标的取值范围从 0到数组长度减 1。
(2) 下标变量相当于基类型变量 。
(3) 下标往往对应于循环控制变量,通过循环,通过下标的变化完成数组所有元素的操作,即整个数组的操作 。
(4) 下标往往隐含有特定的含义 。
(5) 对于下标出界,C语言不进行语法检查。
第 8章 数组类型如果希望下标为 i的分量对应第 i个数据,可将定义数组的大小增 1,如:
int num[ 101] ;
float ccj[ 1001] ;
100 个 整 数 用 num 数组的分量 num [ 1 ],num
[ 2],…,…num[ 1] …,num[ 100] 描述,num[ i]
对应于第 i个整数 。 1000个学生的 C语言成绩用 ccj数组的分量 ccj[ 1],ccj[ 2],…,ccj[ i],ccj[ 1000] 描述,
ccj[ i] 对应于第 i个学生的成绩 。
第 8章 数组类型
8.1.3 一维数组的初始化初始化形式:
存储类别 类型 数组名 [ 常量 ] ={常量 1,
常量 2,…,常量 n};
初始化数据用花括号括起。
第 8章 数组类型例如:
(1) static int month[ 12] ={31,29,31,30,31,30,
31,31,30,31,30,31};
month[ 0] =31,month[ 1] =29,month[ 2] =31,
month[ 3] =30,month[ 4] =31,month[ 5] =30,month
[ 6] =31,month[ 7] =31,month[ 8] =30,month[ 9]
=31,month[ 11] =30,month[ 12] =31
(2) static char ch[ 5] ={′a′,′e′,′i′,′o′,′u′};
ch[ 0] =′a′,ch[ 1] =′e′,ch[ 2] =′i′,ch[ 3] =′o′,
ch[ 4] =′u′
第 8章 数组类型说明:
(1) 对静态存储数组和外部存储数组,默认初值为 0。
(2) 可以只给一部分数组元素初始化 。 例如:
static int a [ 50] ={70,75,60,80,90};
相当于 a[ 0] =70,a[ 1] =75,a[ 2] =60,a[ 3] =80,
a[ 4] =90,后面没有给出的数组元素之值全部为 0。
第 8章 数组类型
(3) 对数组中全部元素给定初值,可以不给定数组长度,它的长度为后面给出的初值个数 。 例如:
static float x[ ] ={1.5,2.5,3.5,4.5,5.5};
数组 x有 5个数组元素 x[ 0],x[ 1],x[ 2],x
[ 3],x[ 4],长度为 5。
(4) 若仅给部分数组元素赋值,则不能省略数组长度。
第 8章 数组类型例 8 – 1 求 10个数的最大值与最小值,10个数用数组描述。
/*程序 8 – 1 求 10个数的最大值与最小值 */
main (
{float a[ 10];
int i;
float max=-1e20,min=1e20;
for ( i=0; i<=9; i++) /*输入 10 个数 */
scanf (″%f″,&a[ i] );
for ( i=0; i<=9; i++) /*求最大值与最小值 */
{if( a[ i] >max) max=a[ i];
if( a[ i] <min) min=a[ i];
}
printf ( ″最大值 =%f,最小值 =%f″,max,min);
}
第 8章 数组类型例 8 – 2 求某班 50个学生 C语言课程的平均成绩及每个学生与平均成绩之差 。
/*程序 8 - 2〓 求 C语言课程的平均成绩及每个学生与平均成绩之差 */
main(
{float ccj[ 51]; /*C语言成绩数组 */
int i;
float tcj=0.0;
float av,cav[ 51]; /*平均成绩 av,与平均成绩之差数组 cav*/
for ( i=1; i<=50; i++) /*输入每个学生成绩 */
第 8章 数组类型
{printf( ″请输入第 %d个学生成绩,″,i);
scanf (―%f‖,&ccj[ i] );
}
for ( i=1; i<=50; i++) /*求平均成绩 */
tcj+=ccj[ i];
av=tcj/50;
for ( i=1; i<=50; i++) /*求与平均成绩之差 */
cav[ i] =ccj[ i] -av;
printf( ″C语言课程的平均成绩 =%5.2f\n″,av); /*输出 */
for ( i=1; i<=50; i++
printf( ″第 %d个学生与平均成绩之差 =%5.2\n″,i,cav[ i]);
}
第 8章 数组类型例 8 - 3 用一维数组求 Fibonacci数列前 20项,要求每行输出 5个数 。
/
*
程序
8
-
3
,
求
F
i
b
o
n
a
c
/*程序 8-3,求 Fibonacci数列前 20项 */
main( )
{static int a[ 20] ={1,1}; /*存放 Fibonacci数列前 20项的数组 */
int i;
for( i=2; i<20; i++
f[ i] =f[ i-1] +f[ i-2];
printf( ″Fibonacci数列前 20项如下,\n″);
for( i=2; i<20; i++
{printf( ″%8d″,f[ i]);
if( i%5==0) printf( ″\n″); /*if语句用来控制换行 */
}
}
第 8章 数组类型运行结果:
Fibonacci数列前 20项如下:
1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
第 8章 数组类型
8.1.4 一维数组作函数参数例 8-4 将例 8-2中求 C语言课程平均成绩改用函数实现 。
函数如下:
float avf( xcj) /*求 C语言课程平均成绩 */
float xcj[ 51] ;
{int i;
float sum=0.0,tav;
for ( i=1; i<=50; i++)
sum+=xcj[ i] ;
tav=sum/50;
return( tav) ;
}
第 8章 数组类型主函数中调用函数 avf( ) 来求平均成绩,
av=avf( ccj) ;
此时,实参数组为 ccj,对应的形参数组为 xcj,调用时将实参数组 ccj首地址传递给形参数组 xcj。 请注意本例中数组的第一个分量 ccj[ 0],xcj[ 0] 无意义 。
对形参数组可以不指定数组大小,在定义数组时数组名后跟空的中括号 。 在函数中另设一个参数,传递数组元素的个数 。 如此在函数中实现变相动态数组 。
第 8章 数组类型例 8-5 将上例中函数延伸考虑为求 n个学生 C语言课程平均成绩 。
函数如下:
float avf( xcj,n) /*求 n个学生 C语言课程平均成绩 */
float xcj[ ],n;
{int i;
float sum=0.0,tav;
for ( i=1; i<=n; i++)
sum+=xcj[ i] ;
tav=sum/n;
return( tav) ;
}
第 8章 数组类型
8.2 二维数组与多维数组
8.2.1 二维数组的定义形式:类型标识符 数组名 [ 常量 1] [ 常量 2] ;
n维数组的定义形式,类型标识符 数组名 [ 常量 1]
[ 常量 2] …[ 常量 n] ;
类型标识符描述的同样是数组分量的类型,是定义数组类型的基类型,可以是任何类型 。 数组名代表数组所占存储空间的首地址 。 常量分别表示数组相应维的长度,数组长度以及数组中分量个数分别等于常量 1,常量 2,…,
常量 n。
第 8章 数组类型
(1) 上述 100个班,每班 50个学生一门课程的成绩,
定义如下二维数组描述:
float cj[ 100] [ 50] ; /*第一维对应班级,第二维对应学生 */
(2) 1000个学生,30门课程的成绩,定义如下二维数组描述:
float acj[ 1000] [ 30] ; /*第一维对应学生,第二维对应课程 */
(3) 上述某高校社会实践调查数据,定义如下三维数组描述:
int b[ 3] [ 2] [ 3] ; /*第一维对应年级,第二维对应性别,第三维对应交通工具 */
第 8章 数组类型
8.2.2 二维数组的引用下标变量的形式为,数组名 [ 下标表达式 1] [ 下标表达式 2]
多维数组下标变量的形式为:数组名 [ 下标表达式 1]
[ 下标表达式 2] …[ 下标表达式 n]
例如,对以上定义的 acj数组 3000个分量分别为,acj[ 0]
[ 0],acj[ 0] [ 1],…,acj[ 0] [ 29],acj[ 1] [ 0],
acj[ 1] [ 1],…,acj[ 1] [ 29],…,acj[ 999] [ 0],
acj[ 999] [ 1],…,acj[ 999] [ 29],左边下标变化最慢,右边下标变化最快,右边下标变化一遍,左边下标才变化一次 。
每个分量对应一个学生一门课程的成绩,acj[ i][ j]
相当于一个 float型变量。
第 8章 数组类型说明:
(1) 每个下标的取值范围从 0到数组长度减 1,下标变量同样相当于基类型变量 。
(2) 对于多维数组整体操作的完成需用多重循环,
一个下标对应于一重循环控制变量 。 二维数组的整体操作用两重循环完成,外重循环对应下标 1,内重循环对应下标 2。
(3) 其它类似于一维数组处理。
第 8章 数组类型
8.2.3 二维数组的初始化初始化形式:
存储类别 类型 数组名 [ 下标 1] [ 下标 2] ={常量 1,常量
2,…,常量 n};
例如:
static int a[ 3] [ 4] ={1,2,3,4,5,6,7,8,9,10,11,12};
a[ 0] [ 0] =1,a[ 0] [ 1] =2,a[ 0] [ 2] =3,a[ 0] [ 3] =4,
a[ 1] [ 0] =5,a[ 1] [ 1] =6,a[ 1] [ 2] =7,a[ 1] [ 3] =8,
a[ 2][ 0] =9,a[ 2][ 1] =10,a[ 2][ 2] =11,a[ 2][ 3] =12
第 8章 数组类型说明:
(1) 二维数组的初始化可以分行进行 。 例如,上面的 a
数组初始化还可以表示为:
static int a[ 3] [ 4] ={ {1,2,3,4},{5,6,
7,8},{9,10,11,12}};
而定义 4行 3列的 b数组可以表示为:
static int b[ 4] [ 3] ={{1,2,3},{4,5,6},
{7,8,9},{10,11,12}};
(2) 可以只对数组中部分元素初始化 。 例如:
a[ 0] [ 0] =1,a[ 0] [ 1] =2,a[ 1] [ 0] =5,a
[ 2] [ 0] =9,其它分量初值取默认值,为 0。
第 8章 数组类型
(3) 如果对二维数组中全部元素初始化,则定义数组时第一维的长度可以省略,但第二维的长度不能省略 。 例如:
static int a[ 3] [ 4] ={1,2,3,4,5,6,7,8,9,
10,11,12};
static int a[ ] [ 4] = {1,2,3,4,5,6,7,8,
9,10,11,12};
static int a[ ] [ ] = {1,2,3,4,5,6,7,8,
9,10,11,12};
因为两个维数都省略时,可以理解为 1*12,12*1,3*4、
4*3,2*6,6*2等多种形式,会发生混淆,故只能省略第一个维数 。
第 8章 数组类型
(4) 如果对二维数组按行进行初始化,则定义数组时第一维的长度也可以省略 。
static int a[ ] [ 4] ={{1,2},{5},{9}};
对于二维数组与多维数组作函数参数跟一维数组作函数参数类同处理,但对形参数组,只有第一维的大小可以省略,第二维及其它高维的大小均不能省略 。
第 8章 数组类型例 8-6 从键盘输入 50个学生 8门课程成绩,求每个学生的总成绩与平均成绩 。
/*程序 8-6,求总成绩及平均成绩 */
main(
{float cj[ 51][ 9];
int i,j;
float tcj[ 51],acj[ 51];
void tcjf( );
void acjf( );
for( i=1; i<=50; i++) /*输入成绩 */
{printf( ″请输入第 %d个学生 8门课程成绩,″,i);
for( j=1; j<=8; j++
scanf( ″%f″,&cj[ i][ j]);
}
第 8章 数组类型
tcjf( cj,tcj); /*调用函数 tcjf( )求总成绩 */
acjf( tcj,acj); /*调用函数 acjf ( )求平均成绩 */
printf( ″所求学生总成绩与平均成绩如下,\n″); /*输出处理结果 */
for( i=1; i<=50; i++
printf( ″第 %d个学生总成绩 =%6.2f,平均成绩 =%5.2f\n″,tcj[ i],
acj[ i]);
}
void tcjf( xcj,xtcj) /*求总成绩函数 */
float xcj[ 51][ 9],xtcj[ 51];
{int i,j;
for( i=1; i<=50; i++)
for( xtcj[ i] =0.0,j=1; j<=8; j++
xtcj[ i] +=xcj[ i][ j];
}
void acjf( xtcj,xacj) /*求平均成绩 */
float xtcj[ 51],xacj[ 51];
{int i;
for( i=1; i<=50; i++)
xacj[ i] = xtcj[ i] /8;
}
第 8章 数组类型例 8-7 编写程序,求两个 3× 4的整数矩阵之和。
/*程序 8-7,求两个 3× 4的矩阵之和 */
main( )
{int a[ 3][ 4],b[ 3][ 4];
int i,j;
int c[ 3][ 4];
for( i=0; i<3; i++) /*输入矩阵 a */
for( j=0; j<4; j++
scanf( ″%d″,&a[ i][ j]);
for( i=0; i<3; i++) /*输入矩阵 b */
for( j=0; j<4; j++
scanf( ″%d″,&b[ i][ j]);
for( i=0; i<3; i++) /*计算矩阵 c */
for( j=0; j<4; j++
第 8章 数组类型
c[ i][ j] =a[ i][ j] +b[ i][ j];
printf( ″所求和矩阵如下,\n″); /*输出处理结果 */
for( i=0; i<3; i++) /*输出矩阵 c */
{for( j=0; j<4; j++
printf( ″%6d″,c[ i][ j]);
printf( ″\n″);
}
}
输入数据,1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2
运行结果:
所求和矩阵如下:
3 3 3 3
3 3 3 3
3 3 3 3
第 8章 数组类型
8.3 字符数组与字符串
8.3.1 字符数组
1,字符数组的定义字符数组的定义和上面讲述的数组定义形式完全一样,只是字符数组的基类型为特定的字符类型 。 例如:
char ch1[ 10],ch2[ 3] [ 4],ch3[ 2] [ 3] [ 4] ;
定义了一个一维字符数组 ch1,含有 10个元素; 定义了一个二维字符数组 ch2,含有 12个元素;定义了一个三维字符数组 ch3,含有 24个元素 。
第 8章 数组类型
2.
字符数组的引用通过字符数组的下标变量进行 。 字符数组的下标变量相当于字符类型的变量 。
3.
对于字符数组的初始化,最易理解的方式是将字符一一赋给字符数组元素。
第 8章 数组类型例如:
(1) static char city[ 8] ={′c′,′h′,′a′,′n′,′g′,′s′,
′h′,′a′};
如果只给一部分字符数组的元素初始化,没有给出值的字符数组元素之默认值为空格字符 。
(2) char city[ 8] ;
city[ 0] =′c′,city[ 1] =′h′,city[ 2] =′a′,city[ 3]
=′n′,city[ 4] =′g′; city[ 5] =′s′,city[ 6] =′h′,
city[ 7] =′a′;
第 8章 数组类型
8.3.2 字符串
1,输入输出输入输出用 scanf( ),printf( )函数完成,采用 ″%s″格式 。 输入输出参数用字符数组名 。 如:
main( )
{char comp[ 9] ;
scanf( ″%s″,comp) ; /*本身就是地址,不需加地址运算符 */
printf( ″COMP=%s″,comp) ;
}
输入数据,CHINAONE
运行结果,COMP=CHINAONE
第 8章 数组类型
2,
puts( )与 gets( )函数包含在头文件 stdio.h中,字符串处理函数包含在头文件 string.h中,用# include ″string.h″指明 。
在以下的函数中,参数 str,str1,str2为字符数组类型或指向字符的指针类型 。
(1) puts( str)
输出指定字符串。 参数可以为字符串常量。
第 8章 数组类型
(2) gets( str)
从键盘输入字符串至字符数组 str中,输入的字符串可以包含空格 。
函数的返回值是字符数组 str的首地址 。
(3) strcpy( str1,str2)
将 str2的值复制到 str1中,实际上完成字符串的赋值操作 。
要求 str1的长度大于 str2的长度,第二个参数可以是字符串常量。
第 8章 数组类型
(4) strcat ( str1,str2)
将 str2的值连接到 str1中原有值的后面 。
(5) strcmp( str1,str2)
比较 str1和 str2,若两者相同,返回函数值为 0;若
str1大于 str2,返回函数值为一个正整数; 若 str1小于
str2,返回函数值为一个负整数 。
第 8章 数组类型
(6) strlen( str)
函数的返回值为字符串的实际长度 。
(7) strlwr( str)
将字符串中大写字母转换成小写字母 。
(8) strupr( str)
将字符串中小写字母转换成大写字母。
第 8章 数组类型
8.3.3 字符串数组
(1) 100
char city[ 100] [ 16] ; /*假定城市名不超过 16个字符 */
100个城市名分别用 city[ 0],city[ 1],…,city
[ i],…,city[ 99] 描述,city[ i] 相当于一字符数组 。
(2) 1000
char book[ 1000] [ 30] ; /*假定书名不超过 30个字符 */
1000本书名分别用 book[ 0],book[ 1],…,book[ 999]
描述,book[ i] 相当于一字符数组 。
第 8章 数组类型例 8-8 用字符数组输出下面图案:
***
*****
***
程序如下:
/*程序 8-8,用字符数组输出图案 */
main( )
{static char ch[ 3][ 5] ={″ ***″,″*****″,″ ***″};
puts( ch[ 0]);
printf( ″\n″);
puts( ch[ 1]);
printf( ″\n″);
puts( ch[ 2]);
printf( ″\n″);
}
第 8章 数组类型例 8-9 输入一行字符,统计数字字符,字母字符及其它字符的个数。
/*程序 8-9,统计数字字符,字母字符及其它字符的个数 */
main( )
{char line[ 81]; /*假定一行不超过 80个字符 */
int i;
int num[ 3] ={0,0,0};
gets( line);
for( i=0; line[ i]! =′\0′; i++
if( line[ i] >=′0′&&line[ i] <=′9′) num[ 0] ++;
else if(( line[ i] >=′a′&&line[ i] <=′z′)‖ (line[ i] >=′A′&&line
[ i] <=′Z′)) num[ 1] ++;
else num[ 2] ++;
printf( ″数字字符数 =%d字母字符数 =%d其它字符数 =%d″,num
[ 0],num[ 1],num[ 2]);
}
第 8章 数组类型例 8-10 求 80个字符串中的最大者。
main( )
{char str[ 80][ 20]; /*假定字符串的最大长度不超过 20个字符 */
int i;
char mstr[ 20];
for( i=0; i<20; i++
gets( str[ i]);
strcpy( mstr,str[ 0]);
for( i=1; i<20; i++
if( strcmp( str[ i],mstr) >0) strcpy( mstr,str[ i]);
printf( ″字符串中的最大者 =%s″,mstr);
}
第 8章 数组类型
8.4 重命名类型
8.4.1 重命名类型方法一般形式,typedef 已有类型 新类型名;
如:
(1) typedef int integer; /*重命名整型 */
integer i,j;
第 8章 数组类型
(2) typedef int COUNT; /*命名一计数类型 COUNT*/
COUNT n1,n2;
(3) typedef int NUM[ 100]; /*命名一整型数组类型 NUM*/
NUM n;
(4) typedef char STRING[ 81]; /*命名一字符串类型
STRING*/STRING str1,str2;
(5) typedef struct
{int day;
int month;
int year;
} DATE; /*命名一结构体类型 DATE*/
DATE date1,date2;
第 8章 数组类型
8.4.2 重命名类型的作用
(1) 有利于加强数据描述的针对性,增加程序的可读性。
(2) 有利于程序的通用和移植。
(3) 有利于减少程序书写的工作量。
第 8章 数组类型
8.4.3 几点说明
(1) 用 typedef只能对已有类型增加一个名字,而不能自己去创造一个新的类型 。
(2) 用 typedef可以对各种已有类型增加新的类型名,但不能用来定义变量 。
(3) 重命名类型,可以将数组类型与数组变量分离开来 。
(4) 重命名类型与编译预处理不同,是在编译时处理,
实际上也并不是作简单的字符串替换 。
(5) 常将一些常用的重命名类型单独放一文件中,需要时用# include指令将它们包含至程序中 。
第 8章 数组类型
8.5 程序设计举例例 8-11 求 n个实数的和,积,最大值,最小值 。
/*程序 8-11,求 n个数的和,积,最大值,最小值 */
# define N 100
main( )
{float a[ N];
int n;
int i;
float sf( );
float mf( );
float max( );
float min( );
scanf( ″%d″,&n);
for( i=1; i<=n; i++
scanf( ″%f″,&a[ i]);
第 8章 数组类型
printf( ″和 =%8.3f\n″,sf( a,n));
printf( ″积 =%8.3f\n″,mf( a,n));
printf( ″最大值 =%8.3f\n″,max( a,n));
printf( ″最小值 =%8.3f\n″,min( a,n));
}
float sf( xa,xn) /*求和 */
float xa[ ];
int xn;
{int i;
float s=0;
for( i=1; i<=xn; i++
s+=xa[ i];
return( s);
}
第 8章 数组类型
float mf( xa,xn) /*求积 */
float xa[ ];
int xn;
{int i;
float m=1;
for( i=1; i<=xn; i++
m*=xa[ i];
return( m);
}
float max( xa,xn) /*求最大值 */
float xa[ ];
int xn;
{int i,k=1; /*k存放最大值下标 */
for( i=1; i<=xn; i++
if( xa[ i] >xa[ k] ) k=i;
return( xa[ k]);
}
第 8章 数组类型
float min( xa,xn) /*求最小值 */
float xa[ ];
int xn;
{int i,k=1; /*k存放最小值下标 */
for( i=1; i<=xn; i++
if( xa[ i] <xa[ k] ) k=i;
return( xa[ k]);
}
第 8章 数组类型例 8-12 给定一 4× 3的整数矩阵,求矩阵中最小值及最小值所在行,列号 。
/*程序 8-12,求矩阵中最小值及位置 */
main( )
{int a[ 4][ 3]; /*存放矩阵 */
int i,j;
int min,row,col; /*存放最小值及最小值所在行,列号 */
for( i=0; i<4; i++) /*输入矩阵 */
for( j=0; j<3; j++
scanf( ″%d″,&a[ i][ j]);
row=0; col=0; min=a[ 0][ 0]; /*初始化最小值及最小值所在行,列号 */
for( i=0; i<4; i++) /*求最小值及最小值所在行,列号 */
for( j=0; j<3; j++
if( a[ i][ j] <min
{min=a[ i][ j];
row=i; col=j;
}
printf( ″最小值为 %d,处在 %d行 %d列 ″,min,row,col);
第 8章 数组类型例 8-13 将 n个实数由大到小排序。
void sort1( a,n) /*选择排序函数 */
float a[
int n;
{int k,i,j; /*k最大值下标,i,j循环控制变量 */
float t; /*中间变量,用于两个数的交换 */
for( i=0; i<n-1; i++
{k=i; /*求最大值下标 */
for( j=i+1; j<n; j++
if( a[ j] >a[ k] ) k=j;
t=a[ i]; a[ i] =a[ k]; a[ k] =t; /*进行交换 */
}
}
第 8章 数组类型算法二,冒泡排序。
void sort2( a,n) /*冒泡排序函数 */
float a[ ];
int n;
{int i; /*一轮比较的循环控制变量 */
int flag; /*标志变量,为 1有交换,为 0无交换 */
float t; /*中间变量,用于两个数的交换 */
do
{flag=0; /*先假定无交换,已排好序 */
for( i=0; i<n—2; i++
if( a[ i+1] >a[ i
{t=a[ i]; a[ i] =a[ i+1]; a[ i+1] =t; /*进行交换 */
flag=1; /* 有交换,标志变量的值改变为 1*/
}
}while( flag==1);
}
第 8章 数组类型例 8-14 筛法求 2~1000之间的所有素数。
/*程序 8-14,筛法求 2至 1000之间的所有素数 */
main( )
{int a[ 1000]; /*筛子数组 */
int i;
int minp,double; /*minp筛选种子,double倍数 */
int n=0; /*素数个数,用于输出格式控制 */
for( i=2; i<1000; i++) /*建立筛子 */
a[ i] =1;
minp=2; /*筛选种子初始化 */
while( minp<500) /*完成整个筛选 */
{double=2*minp; /*倍数初始化 */
第 8章 数组类型
while( double<1000 ) /*完成一轮筛选 */
{a[ double] =0; /*筛去当前倍数 */
double+=minp; /*计算下一个倍数 */
}
do/*计算下一轮筛选种子 */
{minp++; }
while( a[ minp] ==0);
}
printf( ″2至 1000之间的所有素数如下,\n″);
for( i=2; i<1000; i++
if( a[ i] ==1
{printf( ″%6d″,i);
n++;
if( n%5==0) printf( ″\n″); /*5个素数输出在一行 */
}
}
第 8章 数组类型例 8-15 求 10~1000之间的回文数。
/*程序 8-15,求 10~1000之间的回文数 */
main( )
{int i,x;
int a[ 8],j;
int b,e;
int flag;
for( i=10; i<1000; i++
{j=0; x=i; /*将数字分离,用一数组存放 */
while( x>0
{a[ j] =x%10;
x/=10;
j++;
}
第 8章 数组类型
flag=1; /*先假定 i为完数 */
b=0; e=j-1;
while( b<e&&flag) /*判断 i是否为完数 */
if( a[ b]! =a[ e]) flag=0;
else {b++; e- -; }
tf(flag) printf( ″%6d″,i);
}
}
第 8章 数组类型例 8-16 从 n个数据中查找一个数。
float serach( a,n,x) /* 折半查找函数 */
float a[ ],x;
int n;
{int k,flag;
int b=0,e=n-1,d;
flag=0;
do
{d=( b+e)/2;
if( a[ d] ==x) {k=d; flag=1; }
else if( a[ d] >x) e=d;
else b=d;
}while( b<e&&![KG-*4]flag);
if( flag==0) k=0; /*没找到 */
return( k);
}
第 8章 数组类型例 8-17 某班有 50个学生,期终考试 8门课程 。 求每个学生总成绩,平均成绩,并按总成绩高分到低分输出 。
/*程序 8-17,成绩处理程序 */
char st[ 51][ 12]; /*采用外部数组实现数据传递 */
float cj[ 51][ 9];
float tacj[ 51][ 3];
main( )
{void input( ); /*调用函数申明 */
void count( );
void sort( );
void output( );
input( ); /*调用输入函数 */
count( ); /*调用计算函数 */
sort( ); /*调用排序函数 */
output( ); /*调用输出函数 */
}
第 8章 数组类型
void input( ); /*输入函数 */
{int i,j;
for( i=1; i<=50; i++
{printf( ″请输入第 %d个学生姓名,成绩,\n″);
scanf( ″%s″,st[ i]);
for( j=1; j<=8; j++
scanf( ″%f″,&cj[ i][ j]);
}
}
void count( ); /*计算函数 */
{int i,j;
for( i=1; i<=50; i++)
第 8章 数组类型
{tacj[ i][ 1] =0;
for( j=1; j<=8; j++
tacj[ i][ 1] +=cj[ i][ j];
tacj[ i][ 2] =tacj[ i][ 1] /8;
}
}
void sort( )/*排序函数 */
{int i,flag;
char ts[ 12];
float tc;
do
{flag=0;
for( i=1; i<=50; i++
if( tacj[ i+1][ 1] >tacj[ i][ 1
{strcpy( ts,st[ i]); strcpy( st[ I],st[ i+1]);
第 8章 数组类型
strcpy( st[ i+1],st); /*交换姓名 */
for( j=1; j<=8; j++) /*交换 8门课程成绩 */
{t=cj[ i][ j]; cj[ i][ j] =cj[ i+1][ j]; cj[ i+1]
[ j] =t; }
t=tacj[ i][ 1]; tacj[ i][ 1] =tacj[ i+1][ 1]; tacj
[ i+1][ 1] =t; /*交换总成绩 */
t=tacj[ i][ 2]; tacj[ i][ 2] =tacj[ i+1][ 2]; tacj
[ i+1][ 2] =t; /*交换平均成绩 */
flag=1;
}
}while( flag==1);
}
第 8章 数组类型
void output( )/*输出函数 */
{int i;
printf( ″50个学生成绩处理结果如下,\n″);
printf( ″ 姓名 课程 1 课程 2 课程 3 课程 4 课程 5 课程 6 课程 7
课程 8 总成绩 平均成绩 名次 \n″);
for( i=1; i<=50; i++
{printf( ″%8s″,st[ i]);
for( j=1; j<=8; j++
printf( ″%7.2f ″,cj[ i][ j]);
printf( ″%7.2f%7.2f%5d″,tacj[ i][ 1],tacj[ i][ 2],
i);
printf( ″\n″);
}
}