到目前为止,前面介绍的都是属于基本类型的数据。除此之外,C语言还提供了一些更为复杂的数据类型,称为构造类型。数组就是最基本的构造类型。若要针对一批数据进行某种操作,采用数组是一种方便可行的方法。
(1)一维数组:
1.一维数组的定义与引用
数组在引用之前必须事先定义。定义的作用是通知编译程序在内存中分配出连续的单元供数组使用。
一维数组定义的一般形式:
类型说明符 数组名[正整型常量表达式]
*正整型常量表达式可以使符号常量或字符常量。
int c['A'];
*在使用数组的过程中要注意数组下标不能越界。
2.一维数组的初始化
定义时给数组赋值,称为数组的初始化。具体实现的方法如下:
*定义时初始化:
int x[5]={2,4,6,8,10};
*给数组中部分元素赋初值:
int a[6]={3,4,5};表示仅仅把a[0],a[1],a[2]赋初值,其余为0。
*初值的个数不允许大于定义数组时限定的元素个数:
int a[2]={1,2,3};是错误的。
*对数组全部元素的赋值可以不指定元素的个数:
int b[5]={0,1,2,3,4};可以写成int b[]={0,1,2,3,4};
3.一维数组的程序举例:
3.1利用数组计算斐波那契数列的前20个数,并以每行5个数输出:(斐波那契数列的前两个数都是1,从第3个数开始,每个数都是前两个数之和,f[0]=f[1]=1,f[n]=f[n-1]+f[n-2],2<=n<=19。)
1 #include<stdio.h> 2 3 int main(){ 4 5 int i,f[20]={1,1}; 6 for(int i=2;i<20;i++){ 7 f[i]=f[i-1]+f[i-2]; 8 } 9 for(int i=0;i<20;i++){ 10 if(i%5==0&&i!=0){ 11 printf(" "); 12 } 13 printf("%6d",f[i]); 14 } 15 printf(" "); 16 return 0; 17 }
3.2采用冒泡法,实现对一维数组中元素数据,按从小到大排序。
冒泡排序的思想是:从第一个数开始,用第一个数同第二个数进行比较,如果前一个数大于后一个数,则交换两个数,否则不进行交换。再用第二个同第三个数进行比较,如果前一个数小于后一个数则不交换,否则进行交换。这样比较下去就将数组中的最大数交换到最后了。如果有n个数,第一遍要比较n-1次。然后进行下一轮的比较,共比较n-2次,将第二次大的数放在了倒数第二位置,这样继续进行下去直到整个数组排序完毕为止。n个数据一共要比较n-1遍,用程序实现时采用双层循环,外层循环控制比较多少遍,内层循环控制每一遍要比较多少次。过程如下。
1 #include<stdio.h> 2 3 int main(){ 4 5 int i,j,n,temp,a[20]; 6 scanf("%d",&n); 7 printf("The origin numbers: "); 8 for(i=0;i<n;i++){ 9 scanf("%d",&a[i]); 10 } 11 for(i=0;i<n-1;i++){ 12 for(j=1;j<n-i;j++){ 13 if(a[j-1]>a[j]){ 14 temp=a[j-1]; 15 a[j-1]=a[j]; 16 a[j]=temp; 17 } 18 } 19 } 20 printf("The sorted number: "); 21 for(i=0;i<n;i++) 22 printf("%d ",a[i]); 23 return 0; 24 }
(2)二维数组的定义与引用
1.二维数组的定义与引用:
具有两个下标的数组元素构成的数组称为二维数组。在许多实际应用中,常常需要使用二维数组,以更方便的解决问题。二维数组的形式类似数学中的矩阵。
二维数组在内存中的存储的顺序是"按行优先级原则顺序存放。"
2.二维数组的初始化:
*按行给二维数组置初值。
int a[2][3]={{1,2,3},{4,5,6}};
在赋值号后边的一对大括号中,第一对大括号代表第一行的数组元素,第二对大括号代表第二行的数组元素。
*将所有的数组元素按行顺序写在一个大括号内:
int a[2][3]={1,2,3,4,5,6};
*对部分数组元素赋初值:
int b[3][4]={{1},{4,3},{2,1,2}};
*如果对全部数组元素置初值,则二维数组的第一个下标可以省略,但第二个下标不能省略:
int a[2][3]={1,2,3,4,5,6}可以写成int a[][3]={1,2,3,4,5,6};
3.二维数组的程序举例:
3.1将矩阵a2*3转存到b3*2存储
1 #include<stdio.h> 2 3 int main(){ 4 5 int i,j,a[2][3]={{1,2,3},{3,2,1}},b[3][2]; 6 printf("Array a: "); 7 for(i=0;i<2;i++){ 8 for(j=0;j<3;j++){ 9 printf("%5d",a[i][j]); 10 b[j][i]=a[i][j]; 11 } 12 printf(" "); 13 } 14 printf("Array n: "); 15 for(i=0;i<3;i++){ 16 for(j=0;j<2;j++){ 17 printf("%5d",b[i][j]); 18 } 19 printf(" "); 20 } 21 return 0; 22 }
3.2求一个班级10名学生4门课程的平均成绩:
为了调试程序方便,使用随机数生成10名学生的各科成绩。生成随机数的函数rand(),该函数在stdlib.h中定义。rand()%b+a可以生成从a到b之间(包括a不包括b的随机整数)为了使每次生成的随机整数都不同,则在使用rand函数之前要使用包含在time.h中的srand(time(NULL))重新部署一下种子;
1 #include<stdio.h> 2 #include<time.h> 3 #include<stdlib.h> 4 5 int main(){ 6 int i,j,sum,grade[10][4]; 7 double aver; 8 srand(time(NULL));//为了产生不同的随机数,重置随机种子 9 for(i=0;i<10;i++){ 10 for(j=0;j<4;j++){ 11 grade[i][j]=rand()%60+40;//生成大于20的两位随机整数 12 } 13 } 14 for(i=0;i<10;i++){ 15 sum=0; 16 for(j=0;j<4;j++){ 17 sum+=grade[i][j];//累计每名学生的各科总成绩 18 } 19 aver=sum/4.0;//求每名学生的平均成绩 20 printf("The average score of %d student:%5.1lf ",i+1,aver); 21 } 22 return 0; 23 }
(3)字符数组
在数组中,若每个数组元素存放的都是字符型数据,则称为字符数组。
1.字符数组的定义
字符数组用char来说明其类型,一维字符数组可以用char c[5],也可以定义为int c[5];
当将一个字符常量赋给整型字符数组数组元素时,是将该字符的ASCII码的值赋给了相应的数组元素(下标变量)。字符型和整型可以互相通用。
2.字符数组的初始化
char c[7]={'p','r','o','g','r','a','m'};
*若花括号中的初值个数大于数组的长度,则按语法错误处理。
*若花括号中的初值个数小于数组的长度,其余的元素自动添入空字符' '。
3.字符数组与字符串
在c语言中,用字符数组存放字符串。在定义数组时,也可以用字符串为字符数组赋初值,例如:
char c[]={'C Program'};
或char c[]="C Program";
这时c数组的长度为10,在字符m的后面的字节中系统自动添加了空字符' '。
若采用下面的方法进行初始化:
char c[]={'T','h','e',' ','C',' ','L','a','n','g','u','a','g','e'};
与char c[]={"The C Language"};
上述字符串的长度相同,但他们在内存中占用的空间不同。前者是14,后者是15。
4.字符数组的输入和输出
字符数组的输入和输出有以下两种格式:
*%c格式用于一个字符的输入和输出。
*%s格式用于一个字符串的输入和输出。
1)在输出字符串时,遇到字符' '就停止输出。' '是空操作,不输出任何字符。所以无论后面还有多少个' ',都只有第一个起作用。
2)在scanf函数中使用%s时,再输入项中不要加地址符号'&',直接写出字符数组名即可,因为数组名表示该数组在内存的起始地址。
3)如果用scanf函数输入多个字符串,则字符串间用空格分隔。
char str1[4],str2[4],str3[5];
scanf("%s%s%s",str1,str2,str3);
若输入:
How are you!<回车>
则三个单词分别被存到字符数组里。
如果要输入带空格的字符串,最好用gets函数,若要用scanf("%s",s);则只接收字符串中第一个空格前的字符。
(4)字符串处理函数:
c语言函数库提供了字符串处理函数,这些函数定义在string.h库文件中。用户可以使用预编译命令#include<string.h>将文件string.h包含在程序中,直接引用字符串函数。
1.输出字符串函数puts();
2.输入字符串函数gets();
3.字符串连接函数strcat();
4.字符串复制函数strcpy();
5.字符串比较函数strcmp();
6.检测字符串长度函数strlen();
7.字符串小写函数strlwr();
8.字符串大写函数strupr();
实例测试如下:
1 #include<stdio.h> 2 #include<string.h> 3 4 int main(){ 5 printf("1.输出字符串函数puts()的实例: "); 6 char c[]="你好啊! 我很好!"; 7 puts(c); 8 printf(" "); 9 10 printf("2.输入字符串函数gets()的实例: "); 11 char str1[10]; 12 gets(str1);//这里不能用str2=gets(str1);因为不能将char*转化为char[10]; 13 puts(str1); 14 printf(" "); 15 16 printf("3.字符串连接函数strcat()的实例: "); 17 char st1[22]="Microsoft ";//将字符串2连接到1的后面,结果放在字符串数组1中。 18 char st2[9]="Computer";//第一个字符串定义的长度要大于连接后的字符串的长度。 19 printf("%s",strcat(st1,st2)); //后面字符串与前面的字符串连接时,去掉前面字符串后面的' '; 20 printf(" "); 21 printf(" "); 22 23 printf("4.字符串复制函数strcpy()的实例: "); 24 char c1[10]; 25 char c2[]="student!" ; 26 strcpy(c1,c2); 27 puts(c1); 28 printf(" "); 29 30 printf("5.字符串比较函数strcmp(): "); 31 char a1[10]="abcc"; 32 char a2[]="abcd"; 33 if(strcmp(a1,a2)){ 34 printf("测试成功! "); 35 } 36 printf(" "); 37 38 printf("6.检测字符串长度函数strlen()的实例: "); 39 int length; 40 char aa[]="字符串的长度为8!";//中文一个算俩,数字一个,叹号一个,' '算一个。共17个! 41 printf("The length is %d: ",strlen(aa)); 42 printf(" "); 43 44 printf("7.字符串大写函数strupr()的实例: "); 45 char string1[10]="This"; 46 printf("%s",strlwr(string1)); 47 printf(" "); 48 printf(" "); 49 50 printf("8.字符串小写函数strlwr()的实例: "); 51 char string2[10]="This"; 52 printf("%s",strupr(string2)); 53 printf(" "); 54 return 0; 55 }
(5)字符数组应用举例:
1.编写程序打印菱形图案:
1 #include<stdio.h> 2 #include<math.h> 3 #define L 3 //定义宏,代表基准行上边或下边的行数 4 #define Z 2*L+1//定义宏,代表菱形图案的总的行数 5 6 int main(){ 7 int m,n; 8 for(m=-L;m<=L;m++){ 9 for(n=0;n<fabs(m);n++){ 10 printf(" "); 11 } 12 for(n=0;n<Z-2*fabs(m);n++){ 13 printf("*"); 14 } 15 printf(" "); 16 } 17 return 0; 18 }
2.不使用strcat()函数将两个字符串连接起来:
1 #include<stdio.h> 2 3 int main(){ 4 char str1[20],str2[20]; 5 int i=0,j=0; 6 printf("请输入第一个字符串: "); 7 gets(str1); 8 printf("请输入第二个字符串: "); 9 gets(str2); 10 while(str1[i]!='