490 likes | 663 Views
国家级精品课程网站 (本书配套教学网站) http://programming.xjtu.edu.cn. 第 4 章 数组与字符串. 4.1 数组 1. 一维数组 2. 二维数组 3. 多维数组 4.2 字符型数组和字符串处理库函数 1. 字符型数组的定义和初始化 2. 字符串的输入与输出 3. 字符串处理库函数. 4.1 数组. 数据类型 (1) 基本类型:整型、字符型、实型 (2) 构造类型: 由基本类型数据按一定规则组成的 , 包括数组、结构体、共用体 数组 (1) 具有相同数据类型的变量集合 , 这些变量名称相同,下标不同 , 称为数组元素
E N D
国家级精品课程网站(本书配套教学网站)http://programming.xjtu.edu.cn国家级精品课程网站(本书配套教学网站)http://programming.xjtu.edu.cn
第4章 数组与字符串 • 4.1 数组 • 1.一维数组 • 2.二维数组 • 3.多维数组 • 4.2 字符型数组和字符串处理库函数 • 1.字符型数组的定义和初始化 • 2.字符串的输入与输出 • 3.字符串处理库函数
4.1数组 • 数据类型 • (1)基本类型:整型、字符型、实型 • (2)构造类型: • 由基本类型数据按一定规则组成的,包括数组、结构体、共用体 • 数组 • (1)具有相同数据类型的变量集合,这些变量名称相同,下标不同,称为数组元素 • (2)有一个下标——一维数组 • (3)有两个下标——二维数组
4.1.1 一维数组 • 1、一维数组的定义格式 • 类型说明符 数组名[常量表达式] • 2、说明 • (1) 数组名命名规则和变量名相同。 • (2) 数组名后用方括弧括起来的常量表达式表示下标长度 • (3) C语言的下标从0开始,必须是整型变量或常量。 • (4) 数组在内存中存储时,按下标递增的顺序连续存储各元素 • 例如: int array[10]; • 表示数组名为a,有10个元素
3、一维数组的初始化 • (1) 定义数组时顺序对各元素赋以初值 • 例如:int a[10]={0,1,2,3,4,5,6,7,8,9}; • (2) 全部元素赋初值时,可以不指定数组长度 • 例如:int a[5[={1,2,3,4,5}; • 可以写成 int a[ ]={1,2,3,4,5}; • (3) 可以只给一部分元素赋值。 • 例如: int a[10[={0,1,2,3,4}; • 前面5个元素赋初值,后5个元素值为0。
A[0] A[1] A[2] A[3] A[4] 一维数组初始化 • 例:int A[5]; 在内存存储如图 • 数组的首地址是数组名A • 数组的首地址也是第一个元素的地址&A[0] • C++语言中,数组的整体不能参加数据处理,参加处理的只能是数组中的元素变量。所以要对数组进行初始化。 • 例如:int data[5]={,4,,8,};赋值如图
例4-1 • 题目:给一维数组x输入10个整数,找出x数组中的最大数和最小数。 • 算法分析: • 1、假设数组中第1个元素最大, • 令xmax=a[0] • 2、将a[i](0<= i < n)与max进行比较, • 若a[i] < xmax ,i=i+1,再执行2 • 否则,令xmax=a[i],i=i+1,再执行2 • 3、循环结束,求出最大元素并输出max。 输入 2 1 7 3 12 4 9 输出 max=12
// Example 4-1: • #include <iostream.h> • int main() • { int array[7]; • cout<<"Please input an array with seven elements: "<<endl; • for(int i=0; i<7; i++) cin>>array[i]; • int big = array[0]; • for(int j=0; j<7; j=j+1) • if(array[j]>big) big = array[j]; • cout<<"max="<<big<<endl; • return 0;}
二维数组 • 定义格式: • <类型> <数组名>[<常量表达式1>][<常量表达式2>]; • 例如,三个学生四门课程成绩数据如下: • 85 87 93 88 • 86 90 95 89 • 78 91 82 95 • 利用二维数组存放这些数据更能表现数据之间相互联系的特征。每一行数据表示该学生的各门课程的成绩,而每一列数据表示该门课程各学生的成绩。该数组定义为: • int matrix[3][4];
二维数组存储结构 • 逻辑结构: • 二维数组恰似一张表格(或矩阵)。数组元素中的第一个下标值表示该元素在表格中的行号,第二个下标为列号。M[3][3]具有如下逻辑结构: • M[0][0] M[0][1] M[0][2] • M[1][0] M[1][1] M[1][2] • M[2][0] M[2][1] M[2][2] • 存贮结构: • 二维数组在内存中按一维数组存放、占据一片连续的存贮单元;是“按行顺序”在内存中分配存贮单元。
二维数组初始化 • 1.按照二维数组元素的物理存储次序给所有或部分数组元素提供数据值 • int score[3][4]={ 85,87,93,88,86,90,95,89,78,91,82,95}; • //给数组stu_score每个元素都提供初值 • float matrix[2][3]={ 1.0,3.0}; • //仅为数组matrix的前2个元素提供初值
2.以行结构方式提供各数据值 • int score[3][4]={ {85,87,93,88}, {86,90,95,89}, • {78,91,82,95} };
4.2 字符型数组和字符串处理库函数 • 字符串用双引号括起来,例如,”abc”; • 用字符型数组存放字符串,存放时,在有效字符后自动加’\0’; • 称’\0’为空值,是字符串结束标志; • 有效字符的个数称为字符串长度。 • 例如,”abc”的长度为3,但占4个字节 • (’\0’占一位) 。
字符型数组的定义和初始化 • char weekday [7]={ "MONDAY"}; • char weekday [7]= "MONDAY"; • 字符串的输入与输出 • char name[20]; • cin>>name; • cin.get(name, n); • //第一个是字符数组变量,第二个指定向这个变量//中读入几个字符 • cout<<name;
例4-2 字符串的输入与输出 • 输入和输出 • Please input a name with blank(within 19 characters): • Cong Zhen • Please input the name again • Cong Zhen
例4-2 源程序 • #include <iostream.h> • int main() • { char name1[20], name2[20]; • cout<<"Please input a name with blank(within 19 characters): "<<endl; • cin.get(name1, 20); • cout<<"Please input the name again"<<endl; • cin>>name2; • cout<<"Using function get, the name storing in the variable is: "<<name1<<endl; • cout<<"Using operater <<, the name storing in the variable is: "<<name2<<endl; • return 0; • }
字符串处理库函数 • 需要添加#include <string.h> • stpcpy(): 字符串拷贝; • strcat(): 字符串连接; • strchr(): 在字符串中查找字符; • strcmp(): 字符串比较; • strlen(): 求字符串长度; • strlwr(): 将字符串中的大写字母转换为小写字母; • strrev(): 反转字符串; • strstr(): 在字符串中查找另一个字符串; • strupr(): 将字符串中的小写字母转换为大写字母;…
例4-3 • 编写一个用来计算字符串长度的函数mystrlen(),并用主函数验证 • 算法分析: • 1)设一个计数器变量len=0 • 2)从数组s[len]第一个元素开始进行处理 • 3)若当前的元素值s[len]非空(‘\0’),则len+1,继续执行3;否则,退出循环。 • 4)打印结果len
程序逻辑功能框图 len = 0 str[n] str[len]=‘\0’? 是 否 len=len+1 打印结果len
// Example 4-3:求字符串的长度 • #include <iostream.h> • //计算字符串的长度的函数 • int mystrlen(char string[]) • { • int len = 0; • while(string[len]!='\0') • len = len+1; • return len; • }
//测试计算字符串长度的主函数 • int main() • { char string[100]; • int len = 0; • cout<<"Please input a string (within 99 characters): "<<endl; • cin>>string; • cout<<"The length of the string is:"<<mystrlen(string)<<endl; • return 0; • } 输入 china 输出 The length of the string is:5
4.3 结构体类型 • 迄今为止,已介绍了基本类型(或称简单类型)的变量(如整型、实型、字符型变量等),也介绍了一种构造类型数据——数组,数组中的各元素是属于同一个类型的。 • 但是只有这些数据类型是不够的。有时需要将不同类型的数据组合成一个有机的整体,以便于引用。这些组合在一个整体中的数据是互相联系的。
例如,工人工资单:姓名、单位、编号..... • 例如,学生成绩单:学号、姓名、性别、各科成绩等 • 这些项都与某一学生相联系。 • 可以看到性别(sex)、年龄(age)、成绩(score)、地址(addr)是属于学号为10010和名为“Li Fun”的学生的。 • 如果将num、name、sex、age、score、addr分别定义为互相独立的简单变量,难以反映它们之间的内在联系。
4.3.1 结构体类型的定义 • 结构体作为一种数据构造类型,在C 语言程序中也许需要经历定义——声明——调用的过程。 • 结构体是由不同的数据类型的数据组成的。组成结构体的每个数据成为该结构体的成员项简称成员。 • 在程序使用结构体时,首先要对结构体进行描述,这称为结构体的定义。
struct 结构名 { 数据类型 成员名1; 数据类型 成员名2; …… 数据类型 成员名n; } ; struct student { char name[20]; unsigned long number; float math; float english; float physics; }; 4.3.1 结构体类型的定义
三种结构体变量的声明 • (1)先定义结构体类型,再定义结构体类型变量。 • 例如,日期类型可以定义为 • struct date • { int da_year; • char da_mon; • char da_day; • }; • struct date yesterday,today,tomorrow;
三种声明结构体变量的方式(2) • (2)定义类型的同时声明变量。例如, • struct date • { • int da_year; • char da_mon; • char da_day; • } yesterday, today, tomorrow; • 声明了3个日期类型的变量: yesterday、today和tomorrow。
三种声明结构体变量的方式(3) • (3)直接定义结构体类型变量。例如, • struct • { • int da_year; • char da_mon; • char da_day; • } yesterday, today, tomorrow; • 不出现结构体类型名。
程序设计举例 • 例4-5 编写一个程序,实现矩阵相乘运算 • 例4-6 编写一个用于对整型数组进行排序的程序,排序方法使用简单的交换排序法 • 例4-7 编写一个字符串处理程序,将一个字符串之中的所有小写字母转换为相应的大写字母 • 例4-8 使用数组编写一个统计学生课程平均分的程序 • 例4-9 使用结构体重新编写上题的程序
例4-5 实现矩阵相乘运算 • 算法说明: • 矩阵S(LxN)和矩阵T(NxM)相乘。 • S是L行、N列;T是N行、M列。 • 要求:S的列数和T的行数必须相同。
算法说明(续) 3 1 2 2 0 1 1 2 1 1 0 3 2 1 1 T = S = r11 r12 r13 1*3+0*2+3*1 1*1+0*0+3*2 1*2+0*1+3*1 2*3+1*2+1*12*1+1*0+1*2 2*2+1*1+1*1 SxT = r21 r22 r23 = R
矩阵乘法算法 • 用两重循环实现对Cij的求值: • for(i=0; i<l; i=i+1) • for(j=0; i<n; j=j+1) • 求Cij; • 其中“求Cij”又可以细化为: • Cij = 0; • for(k=0; k<m; k=k+1) • Cij = Cij+Aik×Bkj
// 4-5:计算两个矩阵的乘积 • #include <iostream.h> • int main() • {const int L=4; const int M=5;const int N=3; • double a[L*M]={1.0, 3.0, -2.0, 0.0, 4.0, • -2.0, -1.0, 5.0, -7.0, 2.0, • 0.0, 8.0, 4.0, 1.0, -5.0, • 3.0, -3.0, 2.0, -4.0, 1.0 }; • double b[M*N]={4.0, 5.0, -1.0, • 2.0, -2.0, 6.0, • 7.0, 8.0, 1.0, • 0.0, 3.0, -5.0, • 9.0, 8.0, -6.0 }; • double c[L*N]; int i, j, k;
// 4-5:计算两个矩阵的乘积(续) • for(i=0; i<L; i=i+1) • for(j=0; j<N; j=j+1) • { c[i*N+j] = 0; • for(k=0; k<M; k=k+1) • c[i*N+j] = c[i*N+j] +a[i*M+k]*b[k*N+j]; • } • cout << "The result is c=" << endl; • for(i=0; i<L; i=i+1) • { for(int j=0; j<N; j=j+1) • cout << c[i*N+j] << " "; • cout << endl; • } • return 0; • }
例4-6 冒泡排序 • 算法分析: • (1)两两比较相邻元素A(I)和A(I+1)(I=1,2,…N-1),如果A(I)>A(I+1),则交换它们的位置 A(I) A(I+1); • (2)对剩下的N-1个元素,再两两进行比较,按同样规则交换它们的位置,经过N-2次比较,将次最大值交换到A(N-1)的位置; • (3)如法炮制,经过N-1趟的“冒泡处理”,每趟进行N-i次的比较,全部数列有序。
// Example 4-6:冒泡排序 • #include <iostream.h> • int main() • { const int COUNT=16; • int list[COUNT]={503, 87, 512, 61, 908, 170, 897, 275, • 653, 426, 154, 509, 612, 677, 765, 703 }; • for(int i=0; i<COUNT; i=i+1) • for(int j=COUNT-1; j>i; j=j-1) • if(list[j-1]>list[j]) • {int tmp = list[j-1];list[j-1] = list[j];list[j] = tmp;} • cout << "The result is :" << endl; • for(int k=0;k<16;k++)cout << list[k] << " "; • cout<<endl; return 0; • }
例4-7将小写字母转换为大写字母 • #include <iostream.h> • int main() • { char str[]="This is a sample"; • cout<<"The original string is: "<<str<<endl; • int i = 0; • while(str[i]!=0) • { if(str[i]>='a' && str[i]<='z')str[i] = str[i]-'a'+'A'; • i = i+1; • } • cout<<"After transform: "<<str<<endl; • return 0; • }
例4-8 统计学生课程平均分的程序 • 定义二维数组student[6][5], • 其中,给数组student前4列元素读值,第1列为学号,第2列到第4列为4门课程的成绩。第5列为平均分,通过计算求得。
//4-8: 统计学生课程的平均分 • #include <iostream.h> • #define PERSON 6 • #define COURSE 3 • int main() • { int student[PERSON][COURSE+2]; • int i, j; • cout<<"Please input data of student :"<<endl;
for(i=0; i< PERSON; i=i+1) • { cin>>student[i][0];student[i][COURSE+1]=0; • for(j=1; j<= COURSE; j=j+1) • { cin>>student[i][j]; • student[i][COURSE+1]=student[i][COURSE+1]+student[i][j]; • } • student[i][COURSE+1]=student[i][COURSE+1]/ COURSE; • }
//4-8: 统计学生课程的平均分 • cout<<"学号 高数 英语 体育 平均分"<<endl; • cout<<"--------------------------------------"<<endl; • for(i=0; i< PERSON; i=i+1) • { for(j=0; j<= COURSE+1; j=j+1) • cout<<student[i][j]<<"\t"; • cout<<endl; • } • return 0; • }
例4-9 • 使用结构体重新编写上题的程序。 • 算法 定义一个结构体类型StudentType,其中包含学号、各门课程成绩和平均分等数据成员,其值分别通过输入和计算求得。
//Example 4-9: 统计学生课程的平均分 • #include <iostream.h> • #define PERSON 6 • #define COURSE 3 • struct StudentType • {char id[10]; //学号 • int score[COURSE]; //课程成绩 • int GPA; //平均分 • };
int main() • { StudentType xjtuStudent[PERSON]; • int i, j; • cout<<"Please input data of student :"<<endl; • for(i=0; i< PERSON; i=i+1) • { • cin>> xjtuStudent[i].id; • xjtuStudent[i].GPA=0;
for(j=0; j< COURSE; j=j+1) • {cin>> xjtuStudent[i]. score[j]; • xjtuStudent[i]. GPA = xjtuStudent[i]. GPA + xjtuStudent[i]. score[j]; • } • xjtuStudent[i]. GPA = xjtuStudent[i]. GPA / COURSE; • }
cout<<"学号 高数 英语 体育 平均分"<<endl; • cout<<"--------------------------------------"<<endl; • for(i=0; i< PERSON; i=i+1) • { cout<<xjtuStudent[i].id<<"\t"; • for(j=0; j< COURSE; j=j+1) • cout<< xjtuStudent[i].score[j]<<"\t"; • cout<< xjtuStudent[i].GPA<<endl; • } • return 0;}
上机练习题 • 1.使用数组求斐波那挈数列的第n项和前n之和。 • 3 .矩阵相加。 • 4.输入10个字符到一维字符数组s中,将字符串置逆。即s[0]与s[9]互换,s[1]与[8]互换,...,s[4]与s[5]互换,输出置逆后的数组s。 • 5.替换加密(恺撒加密法) 。 • 7.定义一个名为Circle的结构体(圆),其数据成员是圆的外接矩形的左上角和右下角两点的坐标,计算该圆的面积。
结 束 语 • 学好计算机的唯一途径是 • 你的编程能力与你在计算机上投入的时间成 上机练习 正比