1 / 94

第四章 简单构造数据类型

第四章 简单构造数据类型. 短整型 short int. 整型 int. 整型. 长整型 long int. 单精度 float. 实型. 基本类型. 双精度 double. 字符型 char. 数组类型. C 数据类型. 结构体类型. 构造类型. 共用体类型. 枚举型. 指针类型. 空类型. 引例:输入全班 30 名同学的成绩,求平均分,并将 30 名同学的成绩由高到低排序。. for(i=1;i<=30;i++) {scanf(“%f”,&x); s=s+x; } aver=s/30;.

garan
Télécharger la présentation

第四章 简单构造数据类型

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第四章 简单构造数据类型

  2. 短整型 short int 整型int 整型 长整型 long int 单精度 float 实型 基本类型 双精度 double 字符型 char 数组类型 C数据类型 结构体类型 构造类型 共用体类型 枚举型 指针类型 空类型

  3. 引例:输入全班30名同学的成绩,求平均分,并将30名同学的成绩由高到低排序。引例:输入全班30名同学的成绩,求平均分,并将30名同学的成绩由高到低排序。 for(i=1;i<=30;i++) {scanf(“%f”,&x); s=s+x; } aver=s/30; • 问题:30名同学的成绩没有同时保留下来,无法进行排序。 • 一批变量的特点:类型相同(float),意义相同(成绩)

  4. 数组的概念和含义 数组是一批具有相同数据类型的变量的集合。 例:float score[30]; 数组的特点 • 数组各元素在内存中的存储单元是连续的。 • 数组元素通常批量操作。

  5. 4.1 一维数组 4.2 二维数组 4.3 字符数组 4.4 数组与指针 4.5 数组及指针作为函数参数 目录

  6. 4.1 一维数组

  7. 一、定义和使用: 1、定义形式: 数据类型 数组名[元素个数] int a[10]; float b[6]; char c[10];

  8. 2、元素引用: × 数组元素的下标从0开始。例如:int a[5]; 其元素的表示为a[0]、 a[1]、 a[2]、 a[3]、 a[4]。 如果用a[5]则是错误的。

  9. 3、补充说明: ①、数组名由用户定义,命名规则和变量名相同。 ②、元素个数为常量表达式而不能是变量表达式。 如下错误:int n; scanf(“%d”,&n); int a[n]; ③、每一个元素相当于一个变量。

  10. 数组类型的编程,通常和循环程序紧密联系在一起。数组类型的编程,通常和循环程序紧密联系在一起。 例:输入10个数,求它们的和。 用数组类型来解决。 二、数组的编程使用特色

  11. 总结: 1、循环变量的起始和终值; 2、循环中元素的表达。 例:输入10个数,求它们的和。 main() {int a[10]; int i,s=0; for(i=0;i<=9;i++) {printf(“enter %d number:”,i+1); scanf(“%d”,&a[i]); s=s+a[i]; } printf(“the total is %d:”,s); } 或 i<10

  12. 注意:对下标的引用不要超过下标的最大值。尽管超过最大值时不出现编译错误,但数组越界,取的是下一个单元的值,这个单元有可能存放的是其它的变量值,运算结果错误,甚至出现严重错误。

  13. 学生练习 定义一个长度为5的一维整型数组,将一个5位数的各个位存入该一维数组中,然后将各个位数逆序输出。 例:一个5位数为12345,将其各个位数求出来,并依次存入数组各元素中后,将各元素逆序输出,结果应该为54321。要求该数应由用户从键盘上输入。 编程提示: 1、数据类型的准备 2、算法的设计:输入数据→循环结构求取位数并存入数组中→循环结构输出数组中各元素值。 3、如何求取各个位数?

  14. main() { } int x, a[5], i; printf(“enter a 5 bits number:”); scanf(“%d”,&x); for(i=0;i<=4;i++) { } a[i]=x%10; x=x/10; for(i=4;i>=0;i++) printf(“the revert number is:”,a[i]);

  15. 三、一维数组初始化:在程序运行之前,使数组各下标变量有一个初值。三、一维数组初始化:在程序运行之前,使数组各下标变量有一个初值。 1、在数组定义的同时对数组元素初始化。 int a[5]={1,2,3,4,5}; 2、可以仅对一部分下标元素赋初值。 如:static int a[5]={1,2,3}; 如果不对某些下标元素赋初值,则对于数值型元素初值均为0,对于字符型元素均为空操作符’\0’. 3、如果想对所有的元素全部赋初值,可以省略定义元素个数。如:static int aa[ ]={1,2,3,4,5};

  16. 四、一维数组程序举例 题目:对输入到数组中的6个整数升序排序。 1、最原始的排序算法——比较法。 38 23 17 78 6 1 从数组的第一个元素开始,依次和后面的元素比较,如果比当前元素值小则互换值。 1: 6 38 23 78 17 17 38 23 78 1 38 23 78 17 6 23 38 17 38 23 2: 1 6 38 78 23 17 3: 1 617 78 38 23 4: 1 617 23 78 38 5: 1 617 2338 78

  17. main() { int a[6],i,j,t; printf("Please input 6 numbers :\n"); for (i=0;i<6;i++) scanf("%d",&a[i]); for (i=0;i<5;i++) { for (j=i+1;j<6;j++) { if (a[i]>a[j]) { t=a[i]; a[i]=a[j]; a[j]=t; } } } for (i=0;i<6;i++) printf("%d ",a[i]); } 比较法排序算法简单易于实现,但是算法执行效率低,排序过程中有多次数据交换的操作。

  18. 2、冒泡排序法 38 23 17 17 6 1 23 17 23 6 1 6 17 38 6 1 17 17 78 6 1 23 23 23 6 1 38 38 38 38 1 78 78 78 78 78

  19. 思想:将相邻两个数比较,将小的调到前头。 每趟比较,小数上升,大数下沉。 如果有n个数,就要进行n-1趟比较。 17 1 23 6 38 78 第二趟 1 17 6 23 38 78 第三趟 1 6 17 23 38 78 第四趟 1 6 17 23 38 78 第五趟 17 23 38 1 78 6 初始 17 23 1 38 6 78 第一趟

  20. main() { int a[6],i,j,t; printf("Please input 6 numbers :\n"); for (i=0;i<6;i++) scanf("%d",&a[i]); for (i=0;i<5;i++) { for (j=0;j<5-i;j++) { if (a[j]>a[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } for (i=0;i<6;i++) printf("%d ",a[i]); } 冒泡法排序比较和交换数据次数减少,算法执行效率有所提高。

  21. 选择法排序,每轮比较后只交换一次数据,因此算法执行效率最高。选择法排序,每轮比较后只交换一次数据,因此算法执行效率最高。 3、自学:选择法排序 分析:设min为每轮比较的最小值元素的下标值, 第一轮先假设a[0]为最小值,min=0;用a[min]和a[1],a[2],…,a[n-1]比较,出现比a[min]小的值,让min=j;比较完毕,a[min]为第一轮最小值,将a[0]与a[min]互换,此时a[0]里存放最小值。 第二轮假设a[1]为最小值,min=1;用a[min]和a[2],…,a[n-1]比较,出现比a[min]小的值,让min=j;比较完毕,a[min]为第二轮最小值,将a[1]与a[min]互换,此时a[1]里存放次小值。 重复以上操作。外循环为n-1次,内循环比较n-i次.

  22. 4.2 二维数组

  23. 问题引出: 如果统计全班同学总分,并求总分最高者。假设全班40名同学成绩,而每个同学的成绩共有6门课,那么怎么定义数组呢? 此处应定义为二维数组:第一维表示班级人数,第二维表示每人共有6门课成绩,定义形式如下: float score[40][6]; 总结:二维数组由两个[ ]组成,前面为第一维,后面为第二维。

  24. 提问: 二维数组各元素如何表达? score[0][0]、 score[0][1]、……、 score[0][5]、 score[1][0]、 score[1][1]、……、 score[1][5]、 …… score[39][0]、 score[39][1]、……、 score[39][5] 共有40×6=240个元素

  25. 提问: 二维数组各元素在内存中如何存储? 按照先行后列的顺序,如下: score[0][0]、 score[0][1]、……、 score[0][5]、 score[1][0]、 score[1][1]、……、 score[1][5]、 …… score[39][0]、 score[39][1]、……、 score[39][5]

  26. main() { float s[40][6],sum[40],x,max; int i,j; max=0; for(i=0;i<40;i++) { printf("input three course score of student%d\n:",i+1); x=0; for(j=0;j<6;j++) { printf("course1 is:"); scanf("%f",&s[i][j]); x=x+s[i][j]; } sum[i]=x; if(sum[i]>max) max=sum[i]; } for(i=0;i<40;i++) printf("student%d is %.f\n",i+1,sum[i]); } 程序4-5.c 编程方法总结: 二维数组的编程通常用循环嵌套来解决,外循环由数组的一维长度控制,内循环由数组的二维长度控制,依次遍历数组各元素。

  27. 二维数组定义格式 类型 数组名[行数][列数]; 如:int aa[2][3]; 表示整型数组aa共2行,每行3列,共2×3=6个下标元素,每一个元素相当于一个整型变量。 二维数组通常用于处理矩阵问题

  28. 二维数组元素的引用: • aa[行号][列号] • 行号和列号都是从0开始的,并注意行号和列号不要超过数组定义的范围。 • 二维数组在内存中,是按行存放的。数组的存储是按先行后列的顺序,各个元素的存储顺序:aa[0][0],aa[0][1],aa[0][2],aa[1][0],aa[1][1],aa[1][2]。 • 每行相当于一个一维数组,如上例相当于由2个一维数组组成。

  29. 二维数组元素的初始化 • 1、按行给二维数组赋初值。 • 如:static int aa[2][3]={{0,0,1},{1,0,0}}; • 2、也可以把数值写在一块: • static int aa[2][3]={0,0,1,1,0,0} • 则 • aa[0][0]=0, aa[0][1]=0, aa[0][2]=1, • aa[1][0]=1, aa[1][1]=0, aa[1][2]=0,

  30. 3、给部分下标变量赋初值,其它的元素值默认为0,3、给部分下标变量赋初值,其它的元素值默认为0, • 如:static int a[4][5]={{1,2},{ },{0,1,3}} • 则各值为:1 2 0 0 0 • 0 0 0 0 0 • 0 1 3 0 0 • 0 0 0 0 0 • 说明:a.一行中的最后几列元素赋初值为0,这些元素可省。 • b.一行中的前一列或n列元素赋初值为0,这些元素不能省。 • c.一整行元素都赋初值0,若该行是最后一行,整行 • 的赋值可省。如不是最后一行,则必须用一个空大 • 括号表示。

  31. 如果对二维数组的所有元素都赋值,则数组的第一维可以省略。如果对二维数组的所有元素都赋值,则数组的第一维可以省略。 • 如:int m[ ][3]={1,2,3,4,5,6,7,8,9};则默认的第一维的值是3。 • 如仅对部分元素赋初值,要想省略数组的行数,则必须分行赋值,如: • static int a[ ][5]={{1,2},{ },{0,1,3}} 建议使用分行赋值的方法。

  32. 牢记 二维数组的编程特点:使用双重循环,外循环控制“行”,内循环控制“列”。

  33. 四、二维数组程序举例: 1、对以下矩阵进行转置: 1 2 3 4 5 6 7 8 9 10 11 12 说明:该矩阵是非对称矩阵,所以利用两个二维数组进行存储原矩阵和转置矩阵。 源程序4-8.c • 1 5 9 • 2 6 10 • 7 11 • 8 12

  34. 2、P84页例5.5:有四个学生,每个学生学3门课程,已知所有学生的各门课成绩,分别求每门课的平均成绩和每个学生的平均成绩。2、P84页例5.5:有四个学生,每个学生学3门课程,已知所有学生的各门课成绩,分别求每门课的平均成绩和每个学生的平均成绩。 cour1 cour2 cour3 stu1 78 86 92 stu2 62 73 65 stu3 90 93 95 stu4 82 73 86 源程序4-7.c

  35. 重点内容回顾 • 一维数组定义:int a[10]; • 数组下标:从0到N-1; • 元素按顺序存放。 • 常用循环操纵: • for(i=0;i<N;i++)

  36. 二维数组定义:int a[3][10]; • 元素按先行后列的顺序存放。 • 常用循环操纵: • for(i=0;i<N;i++) • for(j=0;j<M;j++)

  37. 4.3 字符数组与字符串

  38. 4.3.1 字符数组的引出 字符数组主要是用于处理字符串信息的。 C语言中没有字符串类型,只有char单字符类型。如果存放并处理一个字符串(由多个字符组成的字符序列)信息,就需要定义字符数组。 字符数组中每一个元素存放一个字符信息,若干个元素的信息连在一起就表达了一串字符序列,通常就是字符串。 在实际使用使许多数据都是字符型的,如姓名、单位、用户名、密码、英文单词、简介等。

  39. 1、定义格式: char 数组名[字符个数]; 回忆字符串常量的特点:“China” 末尾有一个系统自动加上的‘\0’结束标记,因此存储时占用的实际字节数是6个。 注意:字符串数据的特点: 实际存储的字符个数通常是实际字符数+1。这是在定义时需要考虑的特征。

  40. char 数组名[字符个数]; 思考一个问题:实际输入时,输入字符串长度可能不固定,怎么定义数组的长度呢? 考虑实际可能的最大长度,尽量定义的长度大些,如50、80、100等,防止丢失部分数据。

  41. 字符数组初始化; char s[6]={‘C’,”h’,’i’,’n’,’a’,’\0} char s[6]=“China”; 思考以下两种初始化形式有什么不同?char s[ ]=“China”; char s[ ]={‘C’,”h’,’i’,’n’,’a’} 后一种是普通的字符数组,其中存放的字符序列不能作为一个字符串对待,因为没有‘\0’结束标记。

  42. 注意:一个字符数组存放的一串字符型数据,只有当它末尾有‘\0’时才能称之为字符串。否则只能是普通的字符数组,里面的数据不能成串的使用,也不能使用字符串操作函数,例如gets()、puts()注意:一个字符数组存放的一串字符型数据,只有当它末尾有‘\0’时才能称之为字符串。否则只能是普通的字符数组,里面的数据不能成串的使用,也不能使用字符串操作函数,例如gets()、puts()

  43. 有许多专门的字符串操作函数。 • 字符串的整体输入/输出函数:gets(a)、puts(a) • 字符串比较是否相等的函数:strcmp(a,b); • 字符串拷贝或整体赋值函数:strcpy(a,”name”); 注意:字符数组不能定义后整体赋值,如下是错误的:char s[10]; s=“China” × 正确的赋值方法:strcpy(s,”China”); √

  44. [例4.7] 用户预先设置一个N位长度的密码,密码由数字、字母、符号等组成。当计算机开机时要求用户输入密码。3次之内,按用户输入的密码正确与否,输出“欢迎!”、“密码错误!”;超过3次后输出“退出!”。

  45. [分析] 解决这个问题,首先要预设一个长度为N的密码,一个密码为一串的字符,这样就需要定义字符数组来存放这些字符串信息。 那么定义的字符数组长度多大呢? 考虑到字符串还有一个结束标记,也需要占据一个字节的存储空间。因此字符数组的长度需要定义成N+1。

  46. [程序设计过程解析] 用户预先设置一个N位长度的密码,密码由数字、字母、符号等组成。当计算机开机时要求用户输入密码。3次之内,按用户输入的密码正确与否,输出“欢迎!”、“密码错误!”;超过3次后输出“退出!”。 1、定义数组并初始化密码字符串。 2、让用户输入密码字符串。 3、判断两个串是否相等(双分支) 4、循环输入,因此应从步骤2前设置循环,并记录循环次数,当出错3次,结束程序运行。

  47. 观察程序,回答如下问题: 1、字符数组的定义及如何赋初始字符串值? 2、新字符串的值是怎样输入的? 3、两个字符串是如何比较相等或不等的。? 4、循环次数的累加和判断位置在哪里?

  48. 注意:一个字符数组存放的一串字符型数据,只有当它末尾有‘\0’时才能称之为字符串。否则只能是普通的字符数组,里面的数据不能成串的使用,也不能使用字符串操作函数,例如gets()、puts()注意:一个字符数组存放的一串字符型数据,只有当它末尾有‘\0’时才能称之为字符串。否则只能是普通的字符数组,里面的数据不能成串的使用,也不能使用字符串操作函数,例如gets()、puts()

  49. 字符数组与普通数值型数组的使用区别: • 定义时长度控制不同。 • char ch[100]; int a[15]; • 2. 赋初值的形式不同: • char ch[100]=“china”; • int a[15]={1,2,3,6,5}; • 3. 输入/输出数据不同 • gets(ch); puts(ch); (整体操作) • 或scanf(“%s”,ch); printf(“%s”,ch); • for(i=0;i<15;i++) scanf(“%d”,&a[i]); • (单个操作)

  50. 4. 循环控制不同。 for(i=0;ch[i]!=‘\0’;i++) …… for(i=0;i<n;i++) …… 5. 数组赋值不同。 字符数组:strcpy(str1,str2); 整型数组不能整体赋值,只能用循环逐个赋值:for(i=0;i<n;i++) b[i]=a[i];

More Related