1.92k likes | 2.13k Views
第 6 章 构造类型程序设计. 本章勘误 1. P163 6.1.2 一维数组 数组是一些数据的集合,数组的每个元素都属于同一个数据类型,数组利用下标来区分不同的元素。在 C 语言中,数组具有以下特点: P164 2 .数组元素的引用 数组元素的引用形式为: 数组名 [ 下标 ] P167 /* 冒泡法排序 * / for(j=0;j<=N-2;j++) for(i=0;i<=N-2-j;i++) if(a[i]>a[i+1])
E N D
本章勘误1 • P163 6.1.2 一维数组 数组是一些数据的集合,数组的每个元素都属于同一个数据类型,数组利用下标来区分不同的元素。在C语言中,数组具有以下特点: • P164 2.数组元素的引用 数组元素的引用形式为: 数组名[下标] • P167 /* 冒泡法排序 */ for(j=0;j<=N-2;j++) for(i=0;i<=N-2-j;i++) if(a[i]>a[i+1]) { t=a[i]; a[i]=a[i+1]; a[i+1]=t; } /* 交换器 */ ……. printf(“\n”); 删除“有序”两字 删除冒号 删除数字 1 添加 2- 程序最后添加该语句 《解析C程序设计》第6章 构造类型程序设计
本章勘误2 • P168 【例6-2】用选择法对10个数排序。 … void main() { int a[N],i,j,k,x; clrscr(); /* 清屏 */ printf("Input %d numbers:\n",N-1); for(i=1;i<=N-1;i++) … • P169 例 6-3 #include <stdio.h> void main() { int i; long f[40]={1,1}; /* f[2]及其后面的元素处置为0 */ for(i=2;i<40;i++) f[i]=f[i-2]+f[i-1]; /* 计算Fibonacci数列的第i项 */ for(i=0;i<40;i++) { if(i%4==0) printf("\n"); printf("%12ld",f[i]); /* 输出Fibonacci数列 */ } } 添加 -1 , 改 ; 删除 d 添加 l 《解析C程序设计》第6章 构造类型程序设计
本章勘误3 • p174 加第一行: • fflush(stdin); /*清除scanf函数剩下的垃圾字符*/ • p175 加一行代码: #include <stdio.h> #include <string.h> #include <conio.h> void main() { int i,l,flag=1; …… scanf("%s",a); l=sizeofstrlen(a)-1; /*strlen()是求字符串长度的函数,详见6.3节*/ /* 用循环方式判断是否为“回文数” */ for(i=0;i<l/2-1;i++) { if(a[i]!=a[l-i-1]) { flag=0; /* 不等时就不是“回文数”,不再判断 */ …… 添加 修改 删除 ; 《解析C程序设计》第6章 构造类型程序设计
实参内 存空间 实参内 存空间 a a 5 3 …… 2000 2002 2000 2002 3050 3054 2000 2002 3050 3054 3 5 …… 2000 2002 形参内 存空间 形参内 存空间 b b a的地址 复制成x 2000 2002 …… 2000 2002 …… x y x y 执行 &a &b &a &b 4100 4104 4100 4104 调用函数时 函数 b的地址 复制成y 本章勘误4 红色文字为有修改的内容 • p179 p=strchr(a,ch); /* 查找字符位置函数strchr() */ if(p!=NULL) /* 查找字符位置函数strchr() */ printf("在字符串 %s 中以字符 %c 开始的子串为:%s 。\n", a,ch, p); else printf("字符 %c 在字符串 %s 中没有找到。\n",ch,a); • P188 《解析C程序设计》第6章 构造类型程序设计
本章勘误5 • P200 void main() { int a[10],10; … f(a,10); … } 在主调函数中,这种形式前面已介绍。f为自定义函数,实参为数组名a。而f的形参可以为数组名x或指针变量p两种情况。在f函数中,使用数组x的方法与主调函… • P201 【说明】的(2)、(3)两段改为: (2)当数组名或指针变量作形参和实参时,其处理方式在机器内部都是一样的。但一般来说,在定义函数声明参数时,最好能体现出它们的直接用途。如果需要作为数组使用,并从中选择元素,那么应该用数组名作参数;如果需要作为指针使用,并且对其间接引用,那么应该用指针作参数。 (3)当数组名或指针变量不是作为参数声明时,系统是根据数组的大小需要分配内存空间,而给指针变量只分配了一个字的内存空间存放一个地址,该指针变量必须指向一个分配了内存空间的变量(包括数组)才能引用。 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误6 • p204 #include <stdio.h> #include <conio.h> #define SIZE 20 int findposition(int *p,int n,int data); int insert(int *p,int n,int data,int pos); void main() { int a[SIZE],d,n,*p; clrscr(); /* 清屏 */ printf("Input array length:"); scanf("%d",&n); /* 输入插入前数组长度,n要求小于SIZE */ printf("\nInput array %d element:\n",n); for(p=a; p<a+n;p++) scanf("%d",p); /* 输入插入前已排好序的元素 */ printf("\nBefore insert:\n"); for(p=a;p<a+n;p++) printf("%d\t",*p); /* 输出插入前的数组元素 */ printf("\nInput insert data:"); scanf("%d",&d); /* 输入要插入的数据 */ p=a; n=insert(p,n,d,findposition(a,n,d)); /* 插入数据 */ printf("\nAfter insert %d:\n",d); for(p=a;p<a+n;p++) printf("%d\t",*p); /* 输出插入后的数组元素 */ } 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误7 • p208 例6-24 #include <stdio.h> void main() { char str[40],ch; int n; printf("Input string: "); scanf("%s",str); /* 输入不含空格的字符串 */ fflush(stdin); /* 清除键盘缓冲区全部内容 */ printf("Input character: "); ch=getchar(); /* 输入字符 */ n=chrn(str,ch); /* 调用统计字符个数函数 */ printf("n=%d\n",n); } • p209 例6-25 #include <stdio.h> #define N 25 void main() { int bins(int a[],int n,int x); /* 自定义函数声明 */ int a[N],i=1,x,pos; scanf("%d",&a[0]); /* 输入第0号元素 */ 《解析C程序设计》第6章 构造类型程序设计
本章勘误8 • P213 2.二维数组的引用 二维数组元素基本的引用方法是下标法: 数组名[行下标表达式][列下标表达式] • P214 ①先行输入方式 int a[2][3],i,j; for(i=0;i<2;i++) /* 先循环行下标 */ for(j=0;j<3;j++) /* 控制列下标 */ scanf("%d",&a[i][j]); /* 对每个元素赋值 */ ②先列输入方式 int a[2][3],i,j; for(j=0;j<3;j++) /* 先循环列下标 */ for(i=0;i<2;i++) /* 控制行下标 */ • p217 例6-28 int minvalue(int x[][4],int n) { int i,j,min; min=x[0][0]; for(i=0;i<n;i++) /* 循环行 */ for(j=0;j<4;j++) /* 循环列 */ if(min>x[i][j]) min=x[i][j]; return(min); } 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误9 • p219 【例6-29】将3行4列的矩阵转置(即行列互换)。 【分析】3行4列的矩阵转置后为4行3列的矩阵,它们均是12个元素,并且元素的顺序并未改变,只是转置后的行列数发生了变化。即将a[i][j]的值变成了a[j][i]的值。 倒数第4行: #include <stdio.h> void inputarray(int a[][4],int n); void outputarray(int a[][4],int n,int m); void convertarray(int a[][4],int m); …… • P220 inputarray(a, 3); /* 按先行输入3×4矩阵存放在二维数组a中 */ printf("\nBefore convert matrix:\n"); /* 输出转置前的3×4矩阵 */ outputarray(a,3,4); convertarray(a,4); /* 将3×4矩阵转置,即互换行列元素 */ printf("\nAfter convert matrix:\n"); /* 输出转置后的3×4矩阵 */ outputarray(a,4,3); } void inputarray(int a[][4],int n) /* 按先行输入3×4矩阵存放在二维数组a中 */ { int i,j; for(i=0;i<n;i++) /* 控制行 */ for(j=0;j<4;j++) /* 控制列 */ { printf("Input a[%d][%d]: ",i,j); scanf("%d",&a[i][j]); /* 输入数组元素 */ } } void outputarray(int a[][4],int n,int m) /* 输出二维数组 */ { int i,j; for(i=0;i<n;i++) { for(j=0;j<m;j++) printf("%d\t",a[i][j]); printf("\n"); } } 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误10 • p224 例6-32 scanf("%d",&n); fflush(stdin); /*消除scanf函数剩下的垃圾字符,如回车键*/ /* 输入字符串 */ printf("Intput %d string:",n); ...... • p225 例6-32 /* 定义选择法排序函数 */ void sort(char array[][20], int n) { char temp[20]; • p226 例6-34 /*将字符串的小写字母转换成大写字母*/ void Toupper(char s[]) { int i; for(i=0;s[i]!='\0';i++) if(s[i]>='a'&&s[i] <='z') s[i]-=32; } … /*求矩阵个元素的最大值函数*/ int maxvalue(int x[][4],int n) { int i,j,max; max=x[0][0]; for(i=0;i<n;i++) /* 循环行 */ for(j=0;j<4;j++) /* 循环列 */ if(max<x[i][j]) max=x[i][j]; return(max); } 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误11 • P227 6.8 查询学生信息问题 数组是非常有用的一种数据结构,但数组的所有元素的数据类型都必须相同。而现实生活中,将一组不同类型的数据看作一个整体也很重要。 • P232 3.结构体变量的引用 …… 使用圆点运算符访问结构体变量中的成员,其标准形式如下: 结构体变量名.成员名 • p235 例6-37 #include <stdio.h> #include <string.h> #define FORMAT "%d\t%s\t%f\n%f\t%f\n" struct student { int num; /* 学号 */ char name[20]; /* 姓名 */ float score[3]; /* 3门成绩 */ }; 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误12 • P241 void enter(struct student a[],int n) { int i,j,sum=0; printf("请输入 %d 个学生信息(学号,姓名,性别,5门课成绩):",n); for(i=0;i<n;i++) { printf("请输入第 %d 个学生的学号 姓名 性别:",i+1); scanf("%d %s %c",&a[i].num,&a[i].name,&a[i].sex); printf("请输入第 %d 个学生的5门成绩:",i+1); sum=0; for(j=0;j<5;j++) { scanf("%d",&a[i].score[j]); /* 输入5门成绩 */ sum=sum+a[i].score[j]; /* 求每个学生总分 */ } a[i].average=sum/5.0; /* 求平均成绩 */ } } /* 用选择法按平均分由高到低排序 */ void sort(struct student a[],int n) …… /* 输出学生信息 */ void print(struct student a[],int n) { int i,j,mc=1; /* mc表示名次 */ printf("\n按平均成绩排名的名次表:\n"); printf("学号\t姓名\t性别\tcj1\tcj2\tcj3\tcj4\tcj5\t平均分\t名次\n"); for(i=0;i<n;i++) { printf("%d\t%s\t%c\t",a[i].num,a[i].name,a[i].sex); for(j=0;j<5;j++) printf("%d\t",a[i].score[j]); printf("%6.1f\t%d\n",a[i].average,mc++); } } 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
本章勘误13 • p254 例6-44 /* 使用选择法排序(升序)*/ void sort(int num[],char name[][8],int n) { int i,j,min,temp1; …… if(min!=i) /* 职工号和姓名同步交换 */ { temp1=num[i]; /* 交换职工号 */ • p258 例 6-45 /* 初始化围成一圈的n个人的信息 */ void init(PERSON link[],int n) { int i; for(i=1;i<=n;i++) { link[i].number=i; /* 顺序号 */ if(i==n) link[i].nextp=1; /* 如果是最后一个,则下一个就是第一个 */ else link[i].nextp=i+1; } } • P259 while(count<n-1) { i=0; while(i!=m) { h=link[h].nextp; if(link[h].number) 红色文字为有修改的内容 《解析C程序设计》第6章 构造类型程序设计
学生成绩排名问题 一维数组 查找字符位置问题 字符串 查找某字符开始的子串问题 字符串处理函数 交换两个变量值的问题(另解) 指针的概念 指针作函数参数 有序数组插入数的问题 指针的运算 指针与一维数组 打印螺旋方阵问题 二维数组 求一组字符串的最小串问题 二维字符数组 查询学生信息问题 结构体变量 使用typedef定义数据类型的别名 结构体数组 如何读取一个整型数据的高字节数据问题 共用体 主要内容 《解析C程序设计》第6章 构造类型程序设计
6.1 学生成绩排名问题 • 求两个数或三个数的最大值和最小值问题,它也可以理解为对3个学生某门课程的成绩进行排序。 • 可以定义60个变量,然后编写大量的比较大小的语句(比3个变量比较大小复杂得多)实现对60个学生的数学成绩排名。 • 如果有200名学生,定义200个整型变量就很不现实。能不能用一种新的数据类型来表示这200名学生的成绩呢?下面我们就应用新的数据类型来解决这个问题。 • 例6-1 输入200个学生的数学成绩并对其排名。 《解析C程序设计》第6章 构造类型程序设计
问题的分析 • 在C语言中,除了基本类型(整型、实型、字符型、枚举类型)外,还引入了数组、结构体、共用体等构造类型,它使得C的数据类型具有层次性,可以使用简单的数据结构定义复杂的数据结构,把一些独立的数据有机的组合起来作为一个整体,从而解决更为复杂的问题。 • C语言提供了利用基本数据类型构造新的数据类型的机制,使每个元素具有相同的数据类型,而每个元素又相当于一个变量,每个元素可以使用下标来访问。 • 这就是下面要讲的一维数组,它可以用来完成例6-1的问题。 《解析C程序设计》第6章 构造类型程序设计
一维数组 • 在程序设计中,常常需要处理大量同类型的相关数据,如每个学生的成绩记录,多个相同类型数据的排序等。这类数据在计算机语言中可以通过数组来表示。所谓数组就是具有相同数据类型的有序集合。 • 在C语言中,数组具有以下几个特点: • ①数组的所有元素使用一个共同的名字,称为数组名,数组名使用标识符来表示。每个数组元素的使用由数组的下标来确定。 • ②数组元素的个数必须在定义时确定,程序中不可改变。 • ③在C语言中,数组下标是从0开始,到数组元素个数减1结束的。 • ④同一数组中的每一元素具有相同的数据类型(可以是基本类型或构造类型等)。 • ⑤同一数组在内存中占据一段连续的存储单元。 • ⑥数组中元素的作用相当于简单变量。 • ⑦数组必须先定义后使用。 《解析C程序设计》第6章 构造类型程序设计
一维数组的定义 • 一维数组是指只有一个下标的数组元素所组成的数组。一维数组的定义方式为: 数据类型 数组名[常量表达式]; • 例如:int a[10]; 它表示数组名为a,此数组有10个元素,分别为a[0]、a[1]、a[2]、a[3]、a[4]、a[5]、a[6]、a[7]、a[8]、a[9]。 • 又如:存放30个学生的数学成绩,用一维数组定义如下:int grade[30]; 其元素分别为:grade[0],…,grade[29]共30个。 • 注意:数组必须先定义,后使用。 《解析C程序设计》第6章 构造类型程序设计
一维数组的定义说明 • ①数组名定名规则和变量名相同,遵循标识符定名规则。它表示各数组元素的统一名字,用以唯一标识数组。 • ②数组名后是用方括号的常量表达式,不能用圆括号代替。 如int a(20);是错误的。 • ③常量表达式的值表示数组中所包含的元素的个数,即数组的长度。 如int a[20];表示数组a有20个元素,分别为a[0]、a[1]、…、a[19]。 • 注意不能使用数组元素a[20]。 • ④常量表达式中可以包括常量和符号常量,不能包含变量。即在C语言中不允许对数组进行动态定义,数组的大小不会随着程序运行中的变化而改变。 错误定义:int n;scanf(“%d”,&n); float b[n];。 正确定义:#define N 30 float b[N]; int i[10];。 • ⑤类型说明符表示数组元素具有的数据类型,可以是int、 short、long、char、unsigned、float、double等。 • ⑥相同类型的数组可以在同一个类型说明符下一起说明,互相间用“,”隔开。如:int a[4],b[10],c[20]; 《解析C程序设计》第6章 构造类型程序设计
内存用户数据区 … 00000001 2000 a[0]=1 00000000 00000011 2002 a[1]=3 00000000 2004 00000011 a[2]=259 00000001 2006 11111111 a[3]=-1 11111111 2008 11110110 a[4]=-10 11111111 … 一维数组元素的引用 • 数组的具体使用对象是其中的数组元素。在一个数组定义好后,在内存中分配一组连续的存储空间。如:int a[5]; 存储方式见右图。 • 数组元素的引用格式为: 数组名[下标]; • 这里的下标与数组定义时不同,不仅可以是整型常量或整型表达式,还可以是含有已赋值变量的整型表达式。数组的下标从0开始算起。 如:b[0]=b[5]+b[7]-b[2*3]; 又如:int i[15]; int n=3; i[0]=-10; i[5]=6; i[n*4]=9; 《解析C程序设计》第6章 构造类型程序设计
一维数组引用说明 • ①数组元素和普通基本型变量一样的使用,可出现在C语言表达式中的任何地方。 • ②C语言规定只能逐个引用数组元素,而不能一次引用整个数组。 • ③C语言不提供数组下标越界的保护,设计时要注意。 如:int b[5]; 只能有效引用b[0]、b[1]、b[2]、b[3]、b[4]。 • 如果程序中出现b[5] ,这时C的编译系统不会出错,但b[5]的值是不确定的。 《解析C程序设计》第6章 构造类型程序设计
内存用户数据区 … 00000001 2000 a[0]=1 00000000 00000011 2002 a[1]=3 00000000 2004 00000011 a[2]=259 00000001 2006 11111111 a[3]=-1 11111111 2008 11110110 a[4]=-10 11111111 … 一维数组的初始化 • 数组在定义后,它所占有的存储单元中的值是不确定的,引用数组元素之前,必须保证数组的元素已经被赋以确定的值。 • 对数组元素的初始化可以用以下方法实现: • ⑴通过赋值语句或输入语句对数组中的元素赋值。 • ⑵在数组定义时对数组中的元素赋值。对数组元素赋值的方法是从数组的第一个元素开始依次给出初始表,表中各值之间用逗号分开。一般格式为: [static] <类型标识符> <数组名[元素个数]> = {<初值列表>} 如:int a[5]={1,3,259,-1,-10}; static int b[5]={1,3,259,-1,-10}; char word[5]={‘a’,’b’,’c’,’d’,’e’}; 《解析C程序设计》第6章 构造类型程序设计
一维数组初始化说明 • ①<初值列表>是用逗号分隔的数据。 • ②若对数组中的所有元素都赋初值,可不必指出元素个数,即可以不指定 • 数组长度。 如: int a[]={1,3,259,-1,-10}; 也表示数组a有5个元素。它等价于: int a[5]={1,3,259,-1,-10}; 也等价于 a[0]=1;a[1]=3;a[2]=259; a[3]=-1;a[4]=-10。 • 而没有给出数组长度的赋初值,即使后面每个元素的初值全是0,也要写出来 如:int b[]={1,2,3,0,0,0}; 认为是6个元素的数组,它等价于: int b[6]={1,2,3};。 • ③<初值列表>中数据的类型必须与<类型标识符>所指定的数据类型一致。 • ④在C语言中,数组元素的下标值依次为0、1、2、…,在n个元素组成的一 • 维数组中,最后一个元素的下标为n-1。 《解析C程序设计》第6章 构造类型程序设计
一维数组初始化说明 • ⑤C语言规定对数组进行置初值时,如果是静态存储(static为关键字)数组和外部存储(extern)数组。在数组不赋初值时,系统会对所有数组元素自动赋以0值或‘\0’值。 如:static int a[3]; 等价于 static int a[3]={0,0,0}; 。 • 如果只定义int a[5];而不赋初值时,则各元素的值是不确定的。 • ⑥对数组的全部元素都赋0为初值,可以写成: int a[5]={0,0,0,0,0}; 而不能写成:int a[5]={0*5}; • ⑦可以只给数组中的前面一部分元素赋初值,后面没有赋初值的元素系统自动赋以0值或‘\0’值。 如:int a[5]={1,2,3}; 等价于:int a[5]={1,2,3,0,0}; 也等价于:int a[]={1,2,3,0,0}; 《解析C程序设计》第6章 构造类型程序设计
例6-1问题的实现 • 首先定义一个具有200个元素的一维数组,然后对200个元素进行排序。排序方法有很多种,如冒泡法、选择法等。 • 本例采用冒泡法(也称起泡法、还称交换法)排序。 • 冒泡法的思想是:将相邻的两个数进行比较,将小的调到前头。 • 冒泡法的排序过程为: • ①比较第一个数与第二个数,若为逆序a[0]>a[1],则交换;然后比较第二个数与第三个数;依次类推,直至第n-1个数和第n个数比较为止——第一趟冒泡排序,结果最大的数被安置在最后一个元素位置上; • ②对前n-1个数进行第二趟冒泡排序,结果使次大的数被安置在第n-1个元素位置; • ③重复上述过程,共经过n-1趟冒泡排序后,排序结束。 • 冒泡法在第一趟比较中要进行n-1次两两比较,在第j趟比较中要进行n-j次比较。 《解析C程序设计》第6章 构造类型程序设计
交换法排序 《解析C程序设计》第6章 构造类型程序设计
交换法排序 《解析C程序设计》第6章 构造类型程序设计
例6-1程序 /*LI6_1.c*/ #include <stdio.h> #define N 200 void main() { int a[N],i,j,t; printf("Input %d score:\n",N); for(i=0;i<=N-1;i++) scanf("%d",&a[i]); /* 输入成绩 */ printf("\n"); /* 冒泡法排序 */ for(j=0;j<=N-2;j++) for(i=0;i<=N-j;i++) if(a[i]>a[i+1]) { t=a[i]; a[i]=a[i+1]; a[i+1]=t; } /* 交换器 */ /* 输出数据 */ printf("The sorted score:\n"); for(i=0;i<=N-1;i++) { if(i%15==0) printf("\n"); printf("%4d ",a[i]); /* 排序后输出成绩 */ } } 《解析C程序设计》第6章 构造类型程序设计
8 5 4 2 9 0 8 5 9 4 2 0 8 5 4 9 2 0 8 5 4 2 0 9 8 9 5 4 2 0 9 8 5 4 2 0 第 3 次 第 4 次 第 5 次 第 1 次 第 2 次 结 果 第1趟比较 《解析C程序设计》第6章 构造类型程序设计
5 4 8 2 0 第 3 次 5 4 2 0 8 结 果 5 8 4 2 0 第 2 次 5 4 2 8 0 第 4 次 8 5 4 2 0 第 1 次 第2趟比较 《解析C程序设计》第6章 构造类型程序设计
举一反三 • 例6-2:用选择法对10个数排序。 【分析】 • 选择法的思想是:将相邻的两个数进行比较,记录最小值的下标,最后再将最小值与第一个数交换。 • 选择法的排序过程为: • ①首先通过n-1次比较,从n个数中找出最小的数的下标,通过下标找到对应的元素并与第一个数交换——第一趟选择排序,结果最小的数被安置在第一个元素位置上。 • ②再通过n-2次比较,从剩余的n-1个数中找出关键字次小的数据下标,将它与第二个数交换——第二趟选择排序。 • ③重复上述过程,共经过n-1趟排序后,排序结束。 《解析C程序设计》第6章 构造类型程序设计
k=0 k=1 选择法排序 k=1 k=2 《解析C程序设计》第6章 构造类型程序设计
k=3 选择法排序 k=4 k=3 k=4 《解析C程序设计》第6章 构造类型程序设计
例6-2程序 /*LI6_2.c*/ #include <stdio.h> #include <conio.h> #define N 11 void main() { int a[N],i,j,k,x; clrscr(); /* 清屏 */ printf("Input %d numbers:\n",N-1); for(i=1;i<=N-1;i++) scanf("%d",&a[i]); /* 使用a[1]到a[10]这10个数,因此i从1开始 */ printf("\n"); /* 选择法排序 */ for(i=1;i<=N-2;i++) { k=i; for(j=i+1;j<=N-1;j++) if(a[j]<a[k]) k=j; /* 记录最小值的下标 */ if(i!=k) /* 如果最小值不是第一个比较的数,就交换 */ { x=a[i]; a[i]=a[k]; a[k]=x; } /* 交换两个元素的值 */ } /* 输出数据 */ printf("The sorted numbers:\n"); for(i=1;i<=N-1;i++) printf("%d ",a[i]); } 《解析C程序设计》第6章 构造类型程序设计
f[0]=1,f[1]=1 for i=2 to 39 f[i]=f[i-1]+f[i-2] for i=0 to 39 输出:f[i] 例6-3 求Fibonacci数列 斐波那契(Fibonacci)数列为:1,1,2,3,5,8,13,21,…。 /*LI6_3.c*/ #include <stdio.h> void main() { long i,f[40]={1,1}; for(i=2;i<40;i++) f[i]=f[i-2]+f[i-1]; for(i=0;i<40;i++) { if(i%4==0) printf("\n"); printf("%12ld",f[i]); } } 《解析C程序设计》第6章 构造类型程序设计
例6-4:查找一个数在数组中的位置 【分析】 • 对于一个无序的数组,要在里面查找一个数的话,有两种方式: • 一种是先排序,再用折半查找法(即二分法)等查找; • 另一种方法就是直接使用顺序查找法查询数据。 • 本例中是一组无序数据,最好的办法就是采用顺序查找法。 • 顺序查找法的基本思想就是从头到尾依次比较,直到找到所要的数为止。 《解析C程序设计》第6章 构造类型程序设计
顺序查找演示 哈,找到了! 《解析C程序设计》第6章 构造类型程序设计
例6-3程序 /*LI6_3.c*/ #include <stdio.h> #define N 20 void main() { int a[N],i,j=-1,b; printf("Input %d numbers:\n",N); for(i=0;i<=N-1;i++) scanf("%d",&a[i]); printf("\n"); printf("Input other numbers:\n",N); scanf("%d",&b); /* 顺序查找法 */ for(i=0;i<=N-1;i++) { if(a[i]==b) { j=i; /* 记录所找到的数的位置 */ break; /* 找到该数后退出循环 */ } } /* 输出数据的位置 */ if(j==-1) printf("数组中值为 %d 的数据没有找到。\n",b); else printf("值为 %d 的数据是数组中的第 %d 个元素。\n",b,j+1); } 《解析C程序设计》第6章 构造类型程序设计
思考题 • 【例6-3】查找的是一个整数在整型数组中的位置,那么,对于实型数据和字符型数据如何查找呢? 《解析C程序设计》第6章 构造类型程序设计
6.2 查找字符位置问题 • 在例6-4中介绍了在整数数组中查找一个整数的位置,如果数组元素是字符数据又怎么处理呢?比如要在一串字符“abc123defg456h”中要查找字符“d”的位置。 • 例6-5:查找某个字符在一个字符串中的位置。 《解析C程序设计》第6章 构造类型程序设计
问题分析 • 实际上,对于数组来讲,每个元素只能是基本类型中的一种,当数组元素是字符型数据时,称该数组为字符数组。要完成在一串字符中查找一个字符,只需要将例6-4中的数组a和变量b定义成字符型数据,而字符‘a’赋给a[0]、字符‘b’赋给a[1]、……、‘h’赋给字符a[13]等,其它代码稍作改动即可。 • 对于字符数组来讲,如果最后一个元素是空字符‘\0’,这个字符数组就称为字符串,则该字符数组的初始化、引用等方法均可以不同于一般的数组。 • 这里将使用字符串知识解决例6-5的问题。 《解析C程序设计》第6章 构造类型程序设计
字符串 • 要完整理解字符串的含义,必须从三个方面进行: • 作为字符数组; • 作为指向一串字符的指针; • 作为具有整体概念的完整实体。 • 字符数组的定义方法与一般的数组定义方法类似。如: 一维字符数组定义:char a[10],c[20]; • 注意: • ①字符数组的每一元素存放一个字符。字符数组a可存放10个字符,字符数组b可存放30个字符。 • ②由于字符数组大多是以字符串的方式出现,而字符串在C语言中规定用一个“\0”字符为结束标志符,因此,在定义这类数组长度时必须比实际字符多一个元素。 《解析C程序设计》第6章 构造类型程序设计
字符数组的初始化 两种方式: • 用字符型数据对数组各元素初始化 • char a[5]={‘a’,‘b’,‘c’,‘d’,‘e’}; 字符数组 • char a[]= {‘a’,‘b’,‘c’,‘d’,‘e’}; 与上面等价 • char b[6] = {‘C’,‘h’,‘i’,‘n’,‘a’,‘\0’}; 字符串 • char b[6] = {‘C’,‘h’,‘i’,‘n’,‘a’}; 与上面等价 • 用字符串常量直接对数组初始化 • char a[6] = { "China"}; • char b[6] = "China"; • char c[]= "I am happy"; • char d[]= {"I am happy"}; 《解析C程序设计》第6章 构造类型程序设计
字符数组的引用 • 对于一般数组元素的引用,只能逐个引用数组元素而不能一次引用整个数组,而对字符串数组除外。可以单个引用, 也可以一次引用一个字符串。 • ①逐个引用字符串中的单个字符。 如:c[2]=‘a’+2; c[0]=c[2]+3; 等。 • ②将字符数组作为字符串来处理。 • 在一次引用整个字符串数组时,只需使用数组名即可。在遇到字符‘\0’时,表示整个字符数组(字符串)结束。 如:char a[]={“china”}; printf(“%s\n”,a); 其结果为:china 。 《解析C程序设计》第6章 构造类型程序设计
字符数组的输入输出 • ⑴逐个字符输入输出,用格式符“%c”进行。 char c[6]; scanf(“%c”,&c[1]); printf(“ %c”,c[1]); • ⑵整个字符串的输入输出,用格式符“%s”进行。 char c[6]; scanf(“%s”,c); printf(“ %s”,c); 《解析C程序设计》第6章 构造类型程序设计
o w \0 H \0 \0 H o w \0 H o w \0 字符数组输入输出说明 • 使用scanf输入字符串时,输入项是字符数组名,它本身就是地址,因此在引用c时不能加地址符&。 • 使用scanf输入字符串时,系统自动在后面加一个‘\0’字符, 因此键盘输入的字符最多不超过“数组长度-1”个字符。 • 如果利用一个scanf输入多个字符串,则以空格分开。因此,在使用scanf输入时,不能输入含空格的字符串。 • 输出字符不显示‘\0’。 • 用printf的“%s”输出字符时,输出项只能是数组名。 • 当数组长度大于字符串长度时,也只输出到第一个遇‘\0’结束。 • 由于C语言用一维数组存放字符串,而且允许用数组名进行输入输出一个字符串,因此一维字符数组相当于“字符串变量”。 《解析C程序设计》第6章 构造类型程序设计
字符数组与字符串的区别 • 字符数组作为数组类型中的一种,它具有数组变量的共性,可以用来存放和处理数值数据,并对数组元素进行操作;字符串一般都不用来存放和处理数值数据,并且一般是对字符串整体进行操作。 • 字符数组用来存放和处理字符数组且不加结束标志符‘\0’时,则在程序中只可能逐个引用字符数组中的各个字符,而不能一次引用整个字符数组。而字符串则可以对其引用整个数组。其操作的方式,一个是数组元素,另一个是数组名。 《解析C程序设计》第6章 构造类型程序设计
例6-5问题的实现 /*LI6_5.c*/ #include<stdio.h> void main() { int i,p=-1; char a[30],ch; clrscr(); /* 清屏 */ scanf("%s",a); /* 输入字符串赋给字符数组变量a */ fflush(stdin); /* 清除scanf()函数最后的非接收字符 */ ch=getchar(); /* 输入要查找的字符赋给字符变量ch */ for(i=0;a[i]!='\0';i++) { if(a[i]==ch) /* 找到该字符后就退出循环,否则到字符串结束 */ { p=i; break; } } if(p!=-1) printf("字符 %c 在字符串 %s 中的位置为:%d 。\n",ch,a,p+1); else printf("字符 %c 在字符串 %s 中没有找到。\n",ch,a); } 《解析C程序设计》第6章 构造类型程序设计
举一反三 • 例6-6 将字符串a复制为字符串b。 【分析】 • 复制字符串就是将一个字符串的每个位置的字符复制给另一个字符数组变量的相应位置上,并给字符数组的最后一位赋值字符串结束符‘\0’。 • 复制字符串的方法有两种,一种是采用循环,一种是使用字符串处理函数。 • 本例使用循环编程的方式完成。 《解析C程序设计》第6章 构造类型程序设计