• 1. 第7章 数 组掌握一维数组、二维数组的定义、初始化和引用。 掌握字符串和字符数组的概念及其处理函数。 掌握用数组进行编程的技术。
  • 2. 例:给出10个儿童的体重,要求计算平均体重 并打印出低于平均体重的数值。用变量来解决问题: main() { int w1, w2, w3, w4, w5, w6, w7, w8, w9, w10; float t; scanf( "%d%d%d%d%d%d%d%d%d%d",&w1, &w2, &w3, &w4, &w5 , &w6, &w7, &w8, &w9, &w10); 7.1 问题的提出与程序示例
  • 3. t=(w1+w2+w3+w4+w5+w6+w7+w8+w9+w10)/10.0; if( w1 < t ) printf( "%d\n", w1 ); if( w2 < t ) printf( "%d\n", w2 ); if( w3 < t ) printf( "%d\n", w3 ); if( w4 < t ) printf( "% d\n", w4 ); if( w5 < t ) printf( "%d\n", w5 ); if( w6 < t ) printf( "%d\n", w6 ); if( w7 < t ) printf( "%d\n", w7 ); if( w8 < t ) printf( "%d\n", w8 ); if( w9 < t ) printf( "%d\n", w9 ); if( w10 < t ) printf( "%d\n", w10 ); }
  • 4. 用数组来解决问题: main() { int w[10], i; /* 定义 1 个整型数组存放体重 */ float t; for( i=0; i<10; i++ ) scanf( "%d", &w[i] ); for( t=0, i=0; i<10; i++ ) t = t + w[i]; t = t/10; for( i=0; i<10; i++ ) if( w[i] < t )printf( "%d\n", w[i] ); }
  • 5. 数组及其相关概念 数组是一组有序的、类型相同的数据的集合,这些数据被称为数组的元素。数组下标
  • 6. 每个数组都有一个名字,我们称之为数组名。 为标识数组中的每个元素,我们需要对它们进行编号,这种编号我们称之为数组元素的下标。 由于有了下标,元素在数组中的位置(或排列顺序)就被唯一地确定下来。我们用数组名加上下标就可以准确地访问数组中的某个元素了。如:w[0]代表数组w中的第一个元素 w[9]代表数组w中的第十个元素 注意:C语言规定下标从0开始。说明:数组名代表数组的起始地址。 数组元素在内存中是连续存储的。
  • 7. 7.2 一维数组7.2.1 一维数组的定义定义一维数组的一般方式: 类型标识符 数组名[常量表达式];指明数组元素的数据类型指明数组所含的元素个数例如:int a[10]; /*定义的整型数组a含10个元素*/ float b[20]; /*定义的实型数组b含20个元素*/
  • 8. 说明:⑴ 数组名的命名规则同变量名的命名规则一样;⑵数组名后用方括号[ ],不能用()⑶常量表达式必须是大于0的整型常量表达式(包括符号常量),不能包含变量。即C语言不允许对数组的大小作动态定义,即定义数组时,数组的长度必须是确定的,其大小不依赖程序运行过程中变量的值。int a(10); 例如:int n; int a[n];char name[0]; float weight[10.3]; float array[-100];
  • 9. 7.2.2 一维数组的初始化1 .定义时初始化方法:将初值依此写在花括号{ }内。如: int a[5]={ 2 , 4 , 6 , 8 , 10 };存储形式:存储单元
  • 10. 说明:⑴如果在定义一维数组时给出了全部元素的初值, 则数组的下标允许省略。此时编译系统将自动 根据初始化数据的个数来确定数组的长度。如: int a[ ]={ 2 , 4 , 6 , 8 , 10 }; int b[ ]; ╳
  • 11. 说明:⑵初始化的数据个数允许少于数组的长度,但不  能多于数组的长度。当初始化的数据个数(至  少要有一个)少于数组的长度时,未初始化部  分将被编译系统自动用 0 赋值。如:int a[5]={ 2 , 4 }; 相当于:a[0]=2, a[1]=4, a[2]=0, a[3]=0, a[4]=0 int a[5]={1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }; ╳
  • 12. 2 .使用其它方法初始化⑴利用赋值语句初始化 main() { char a[26],ch; int i; for(i=0;i<26;i++) a[i]=i; …... }
  • 13. ⑵利用输入语句初始化 main() { char as[26]; int i ; for(i=0; i<26; i++) scanf("%c",&as[i]); …... }
  • 14. 7.2.3 一维数组的引用 数组元素类似于单个变量,可以自由地存取。但是,它与一般变量相比,有以下特殊之处: 数组元素是通过数组名加上该元素在数组中的位置(即数组元素的下标)来访问的。 表示形式: 数组名[下标] 如: a[3]
  • 15. 1. 下标可以是整型常量、整型变量或整型表达式。如: int a[10] ; float i=3 ; a[i]=10 ;2.数组元素的下标是从0开始的。如:int a[2]; scanf(“%d,%d”,&a[1],&a[2]); 3.注意数组元素的下标不要出界。
  • 16. 4.数组元素的赋值是逐个元素进行的,不允许把一个数组作为一个整体赋给另一个数组。除了数组初始化外,也不允许用在花括号中列表的方式对数组整体赋值。例1: int a[5]={ 2 , 4 , 6 , 8 , 10 } , b[5] ; b[5]=a[5] ;例2 :int a[5] ; a[5]={ 2 , 4 , 6 , 8 , 10 } ;
  • 17. 5.数组名a代表的是数组a在内存中的首地址,因此,可以用数组名a来代表数组元素a[0]的地址。 等价于scanf(“%d”,&a[0]); scanf(“%d”,a); 只能逐个的使用每个数组单元进行操作,而不能一次引用整个数组。 不能将数组名置于赋值号的左边,若s是数组名,则语句s=5;是错误的。
  • 18. 7.2.4 一维数组应用举例例1:从键盘上输入10个实型数存入数组,然 后按输入顺序的逆序输出这10个数。main() { float a[10]; int i; for(i=0 ; i<10 ; i++) scanf(“%f”,&a[i]); for(i=9 ; i>=0 ; i--) printf(“%10.2f”,a[i]); }
  • 19. 例2:用数组来处理求斐波纳契数列: 1,1,2,3,5,8…的前20个数。main() { int f[20]={1,1}; for(i=2 ; i<20 ; i++) /*f[2]是数组第3个元素*/ f[i]=f[i-2]+f[i-1]; for(i=0 ; i<20 ; i++) { printf(“%10d”,f[i]); if(i%2==0) printf(“\n”); /*每行打印2个数*/ } }数学表示:f(0)=f(1)=1, f(n)=f(n-2)+f(n-1)
  • 20. 例3:用冒泡法对10个数排序(由小到大)。冒泡法的思路是:将相邻两个数比较,将小的 调到前头。 9 8 8 8 8 8 8 9 5 5 5 5 5 5 9 4 4 4 4 4 4 9 2 2 2 2 2 2 9 0 0 0 0 0 0 9 第一轮排序,比较了5次 ,获得第一次结果。剩数 轮数 5 1 4 2 3 3 2 4 1 5
  • 21. main() { int a[11], i , j , t ; printf(“Input 10 numbers : \n”); for(i=1 ; i<11 ; i++) scanf(“%d”,&a[i]); printf(“\n”); for(j=1 ; j<=9 ; j++) /* 控制9轮排序 */ for(i=1 ; i<=10-j ; i++) /* 每轮排序比较次数*/ if(a[i]>a[i+1]) { t=a[i]; a[i]=a[i+1]; a[i+1]=t; } for(i=1 ; i<=10 ; i++) printf("%d",a[i]); }
  • 22. 7.3 二维数组类型说明符 数组名[常量表达式1][常量表达式2]; 如: float a[3][4], b[4][3]; 定义a为3行4列的实型数组. b为4行3列的实型数组. a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]7.3.3 二维数组的定义
  • 23. 存储形式: 二维数组在内存中是按行的顺序存放的,即先存放第一行的元素,再存放第二行的元素。
  • 24. 说明:二维数组除了维数比一维数组多一维外, 其它性质与一维数组是全部类似的。 看看下面写法是否正确? ① int a[0][3]; 用于定义数组长度的常量表达式的值必须是大于0的正整数。 ② int i=3 , j=4 ; int a[i][j] ; 定义数组元素的个数必须使用常量表达式,而不能使用变量。
  • 25. 7.3.2 二维数组的引用 数组名[行下标][列下标] 其中,行下标和列下标是整型常量、整型变量或整型表达式。其编号是从0开始的。说明:数组名a代表的是数组a在内存中的首地址, 因此,可以用数组名a来代表数组元 素 a[0][0]的地址。
  • 26. 7.3.3 二维数组的初始化 ⑴分行初始化 例如:int a[2][3]={{1 , 2 , 3 } , { 4 , 5 , 6 }}; 第一个花括号的数据赋值给第一行 第二个花括号的数据赋值给第二行 ⑵把所有要赋值的数组都写在一个花括号内 即按数组元素在内存中排列的顺序赋初值。 例如:int a[2][3]={1 , 2 , 3 , 4 , 5 , 6 };
  • 27. (3) 给部分元素赋值 未被初始化的数组元素将自动赋 0 Int a[3][4]={{2,5},{7},{6,1,4}}; 250070006140该方法对数组中比较多的元素为0时比较方便
  • 28. (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}; 如果只对部分元素赋值,也可以省略第一维,但必须分行赋值. int a[][3]={{3},{ },{5,1},{4}}; 300000510400
  • 29. 例:矩阵的转置。a=1 2 3 4 5 6b=1 4 2 5 3 6转换成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("\n array b:\n"); for(i=0;i<3;i++) { for(j=0;j<2;j++) printf("%6d",b[i][j]); printf("\n"); } }
  • 30. 例:求3*4数组中的最大值及其下标。main() { int max,row,colum,i,j; int a[][4]={{1,2,3,4},{9,8,7,6},{-10,10,-5,2}}; max=a[0][0]; for(i=0;i<3;i++) for(j=0;j<4;j++) if(a[i][j]>max) { max=a[i][j]; row=i; colum=j; } printf("max=%d,row=%d,colum=%d",max,row,colum); }
  • 31. 7.4 数组作为函数的参数数组名实际上表示的是整个数组的首地址,因此如果调用函数的实参是数组名,则被调用函数的形参也应该是数组类型。 如果实参是数组名,形参是数组类型,调用函数与被调用函数存取的将是相同的一组空间,即使实参数组名和形参数组名不一样。因为实参传给形参的是一组空间的首地址。
  • 32. 7.5 字符串和字符串函数7.5.1 字符数组 当数组的元素类型为字符型时,被称为字符数组。 字符数组的每一个元素中存放一个字符。如:char c[10]; 则c为字符数组。
  • 33. 7.5.2 字符数组的初始化1. 逐个元素初始化. 如: char a[5]={’c’,’h’,’i’,’n’,’a’}; 注意字符型常量要用单引号括起来初始化的字符个数允许少于字符数组的长度,但不能多于字符数组的长度。当初始化的字符少于字符数组的长度时,将这些字符赋值给前面的元素,未初始化部分将被自动赋值为空字符‘\0’如:char c[8]={‘H’,‘e’,‘l’,‘l’,‘o’};Hello\0\0\0
  • 34. 如果提供的初值个数与数组的长度相同,则定义数组时可以省略数组的长度,系统根据初值的个数自动确定数组的长度。 char a[ ]={’a’,’ ’ , ’s’,’t’,’u’,’d’,’e’,’n’,’t’}; 则系统自动将数组a的长度确定为9 这种方法可以不必去数字符的个数。
  • 35. 2. 将一个字符串整体赋值给一个字符数组. 如: char a[ ]={“a student”}; 也可以把花括号去掉,写成: char a[ ]=“a student”; 注意字符串应用双引号括起来.
  • 36. 3.可以定义和初始化一个二维字符数组. char s[4][8]={“basic”,”foxbase”,”pascal”,”fortran”}; 可以省略第一维,但不能省略第2维. char week[ ][4]={“mon”,”tue”,”wed”,”thu”,”fri”,”sat”,”sun”};
  • 37. 格式: 数组名[下标] 数组名[下标1][下标2] a[3]=‘w’; scanf(“%c”,&a[0]); printf(“%c”,s[1][1]);7.5.3 字符数组的引用
  • 38. 字符串常量是用双引号括起来的一串字符,由系统自动加上一个字符串结束标志‘\0’。它占内存,但不记入字符串长度。如:“china” 占内存6个字节,但字符串长度是5 在C语言中用字符数组来处理字符串,每个元素存放一个字符型数据。使用字符串常量初始化字符型数组,则该数组的长度是字符串的长度+1如: char m[]=“Hello”; (这时,数组m的长度是6)7.5.4 字符串
  • 39. 注意:两种初始化方式的区别 char m[ ]={‘h’, ‘e’, ‘l’, ‘l’, ‘o’};数组长度为5数组长度为6说明:字符数组本身并不要求它的最后一个元素一定是‘\0’,例如:char ch[2]={‘A’, ‘B’};是合法的。当定义字符数组用字符串常量赋初值时,最后有一个元素其值为‘\0’。hellochar m[ ]=“hello”;hello\0
  • 40. 7.5.5 字符串的输入输出字符串的输入输出可以有以下两种方法:⑴逐个字符输入输出 用格式符“%c”输入或输出一个字符。char s[11]; int i; for (i=0;i<11;i++) scanf(“%c”,&s[i]); for (i=0;i<11;i++) printf(“%c”,s[i]);
  • 41. ⑵将整个字符串一次输入或输出 用格式符“%s”输入输出字符串。例如:char c[ ]=“Hello” ; printf(“%s”, c) ;注意:⑴输出字符不包括结束符‘\0’。⑵用“%s”格式符输入输出时,输入输出的对象是数组名,而不是数组元素。并且输入时数组名前不再加地址运算符& (数组名本身就代表数组的起始地址)。char a[9]; scanf(“%s”,a); printf(“%s”,a);
  • 42. ⑶输出字符数组时,遇到第一个‘\0 ’,输出就结束。(4)用scnaf命令的“%s”格式符输入字符串时,从键盘输入的字符串应短于已定义的字符数组的长度。系统自动在后面加一个‘\0’结束符。(5)利用scanf函数输入多个字符串时,是以空格、回车、跳格(按TAB)分隔。因此不要试图利用scanf函数从键盘输入How are you? 赋给一个字符串。
  • 43. 7.5.6 字符串处理函数㈠字符串输入输出函数1.字符串输入gets()函数格式:gets(字符串变量)功能:从终端输入一个字符串(直到回车键) 到字符串变量中。例如:char str[20]; gets(str); 若从键盘输入:Hello World! 则将字符串“Hello World!”送到字符串变量str中。
  • 44. 2.字符串输出puts()函数格式: puts(字符串变量)功能:将一个以\0结束的字符序列输出到终端。 输出完字符串后自动换行。 字符串中可包含转义字符例如:char str[]={“China\nBeijing”}; puts(str); 输出:China Beijing注意:使用puts和gets函数前,要用预编译命令: #include “stdio.h”
  • 45. 3.字符串连接strcat()函数 格式:strcat(字符串变量1,字符串2)功能:连接两个字符串,把字符串2连接到字符串变量1的后面,连接后的字符串放在字符串变量1中。 说明:⑴字符串变量1必须足够大以便能够容纳字符串2。 ⑵连接时只在新串最后保留一个‘\0’。 注意:使用下面几个函数前,要用 #include “string.h”
  • 46. 4. 字符串复制strcpy()函数 格式: strcpy(字符串变量1,字符串2 )功能:将字符串2复制到字符串变量1中 (其后自动加一个‘\0’)。例如:char str1[20], str2[10] ; strcpy(str1,“hello world”); strcpy(str2,str1); 其中,字符串2可以是字符串常量或字符数组。
  • 47. 说明:⑴字符串变量1必须足够大以便能够容纳被复制的字符串。 ⑵不能用赋值语句将一个字符串常量或字符 数组直接赋值给一个字符数组。 例如:char str1[20], str2[20]; str1={“hello”}; str2=str1 ;
  • 48. 5. 字符串比较strcmp()函数格式: strcmp(字符串1,字符串2)其中,字符串可以是字符串常量或字符数组。 功能:比较两个字符串。函数值是一个数值。 比较的原则:两个字符串从左至右逐个对应字 符按其 ASCII码值大小相比较, 直到出现不同的字符或遇到‘\0’为止。 若设n=strcmp(字符串1,字符串2); n>0; 串1>串2 则: n=0; 串1=串2 n<0; 串1<串2
  • 49. 例如:char str1[20], str2[10] ; (将str1[20]和str2[10]赋初值) if(strcmp(str1,str2)>0) puts(str1);注意:不能写成 if(str1>str2) puts(str1);strcmp(“China”,”Korea”);
  • 50. 6. 求字符串长度strlen()函数格式: strlen(字符串)功能:计算字符串长度,函数值是字符串中‘\0’ 之前的字符个数(不包括‘\0’字符)。 例如:char str[80]={“ab\n\\012/\\\””} ; printf(“%d”,strlen(str)) ;输出:10 char str[80]={“ab\n\0y\012/\\\””} ; printf(“%d”,strlen(str)) ;输出:3
  • 51. 7.将字符串中大写字母换成小写字母strlwr()函数 格式: strlwr(字符串 )8.将字符串中小写字母换成大写字母strupr () 函数格式: strupr(字符串 )
  • 52. 学习数组这一章要注意的几个问题: 1.在C语言中数组的下标是从0开始; 2.C语言不进行下标的越界检查,不论是在编译阶段还是 在运行阶段,这个问题交给程序员。这样就给初学者 带来一定的风险。 3.数组名是地址,这在字符串处理中已经看到,这个我 们要先强记,以后在讲指针时再详细讲。 4.字符数组在定义时必须考虑到串结束符的位置,因为 它要占一个字符的位置。 5.要注意数组初始化的方法与简单变量的区别,特别是 字符数组的初始化方法。 6.字符串的操作有许多专用函数,请注意掌握并运用。