260 likes | 419 Views
第四章. 数组(二). 上讲主要内容. 一维数组 ◆ 概念的引入 ◆ 一维数组的定义、引用及初始化 程序举例 二维数组. 本章(二)主要内容. 字符数组 ◆ 概念的引入 ◆ 字符数组的定义、引用及初始化 ◆ 程序举例 用于字符串处理的函数. 字符数组 — 问题的提出. 一个简单的字符型变量只能存放一个字符。对于字符串数据, c 语言中是用字符数组来存放的。. 字符串 是 C 语言的一种数据类型。它由若干个字符组成,以 字符串结束标记 ‘’ ,( ASCII 码值为 0 的字符) 作为其最后一个字符 。.
E N D
第四章 数组(二)
上讲主要内容 • 一维数组 ◆ 概念的引入 ◆ 一维数组的定义、引用及初始化 程序举例 • 二维数组
本章(二)主要内容 • 字符数组 ◆ 概念的引入 ◆ 字符数组的定义、引用及初始化 ◆ 程序举例 • 用于字符串处理的函数
字符数组—问题的提出 一个简单的字符型变量只能存放一个字符。对于字符串数据,c语言中是用字符数组来存放的。 字符串是C语言的一种数据类型。它由若干个字符组成,以字符串结束标记‘\0’,(ASCII码值为0的字符)作为其最后一个字符。 在程序中,一个字符串在字面上是以一对双引号括起来的若干个字符,也称字符串常量。如“HELLO!"。 问题:从键盘上输入一字符串,统计该字符串的长度。
字符数组—问题分析 如何存储字符串 如何求字符串长度 要完成从键盘上输入一字符串,并统计该字符串的长度。需要解决: 一个字符串可视为一组类型相同(字符型)的有顺序的数据。因此,可以定义字符型数组来存放字符串。字符数组的每个元素都可以作为一个字符型变量存放字符串中对应字符。 字符串长度是指字符串中除字符串结束标记’\0’外的所有字符的个数。例如字符串“ABCde”长度为5,其中空格也是有效字符。
字符数组—程序 程序 char a[80]; 定义了一个名为a类型为字符型,大小(长度)为80的数组,因此字符数组a能存放长度不超过79的字符串。因为必须留一个元素存放字符串结束标志‘\0’。 程序运行结果为: Input a string: Welcome to China! Length of“ Welcome to China!”=17 #define "string.h" main() {char a[80]; int n=0,i=0; /*为长度计数器n和数组下标i赋初值0*/ printf("\nInput a string:"); gets(a); /*从键盘接收一字符串并存入字符数组a中*/ while(a[i++]!='\0') n++; printf("Length of \“%s\"=%d\n",a,n); } 循环语句来完成求字符串长度 while(a[i++]!=‘\0’) n++; 从字符数组的第1个元素(下标为0)起,逐个判断,若当前字符不为结束标记‘\0’,则长度计数器n加1,直到当前字符为‘\0’结束。上述语句可改写为: while(a[i]! =‘\0’) {i++;n++;}; 从键盘上输入字符串是通过函数调用语句gets(a)来完成的。功能是从键盘上输入一个字符串到指定的字符数组中。
字符数组—概念及定义 用来存放字符数据的数组是字符数组。字符数组中的每个元素都可以看为一字符型变量,可存放一个字符。以其ASCII码的形式存放。 字符串是C语言中的字符型数据。它由若干个字符组成,其最后一个字符是字符串结束标志‘\0’。在C语言中,字符串是借助于一维数组来存放的。 字符数组的定义 字符数组的定义与一、二维数组的相同。例如: char s[80]; char s[5][40];
字符数组—初始化 H e l l o ! \0 e ! H l l o H e l l o ! \0 \0 \0 \0 1.逐个字符赋给数组中各个元素,即把所赋初值依次放在一对花括号中。例如: char srt1[6]={‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’}; char str2[7]={‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’, ‘\0’}; 2.直接引用字符串常量给字符数组赋初值。例如: char str2[7]={“Hello!”}; char str2[7]= “Hello!; 系统会自动在最后加入‘\0’,所以不必人为加入。由于定义了str2数组占有7个连续内存单元,因此有足够空间存放字符串。若是定义成: char str2[6]=“Hello!”; 6个存储单元不够用,结束符‘\0’将占用下一个不属于str2的存储单元。 3.赋初值的字符个数少于数组元素。此时,系统将会自动在其后的元素假如‘\0’。例如: char str1[10]={‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’}; char str2[10]=“Hello!”;
字符数组—引用 1.逐个引用字符数组中一个元素,得到一个字符。 不论字符数组中存放的是单个字符序列,还是字符串,都可以通过使用数组名及其下标来实现逐个引用字符数组单个字符。输入输出一个字符可利用格式输入函数中格式说明“%c”来完成。 例 6 逐个输出字符数组中单个字符。 main() { char c[6]={‘H’,’e’,’l’,’l’,’o’,’!’,’\0’}; int i; for (i=0; i<6; i++) printf(“%c”,c[i])/*逐个引用字符数组c中的一个元素c[i]*/ printf(“\n”); }
字符数组—引用 2.当字符数组存放字符串时,可以一次引用整个字符数组。 字符数组的名字是一个地址常量,它代表字符数组的首地址。当字符数组中存放的是字符串时,可把字符数组当为字符串来处理。此时,允许使用数组名一次引用整个数组。可以在调用字符串处理函数时,使用数组名字作实参,也可以使用字符数组名来进行输入输出。但是,不可使用赋值语句给字符数组整体赋一字符串。例如: char str[10]; str=“Hello C!”; 以上赋值语句是不允许的。因为数组s是一地址常量,不能被重新赋值。
字符数组—引用 2.当字符数组存放字符串时,可以一次引用整个字符数组。 (1)可以在sanf()及printf()函数中使用格式说明%s来实现字符串的整体输入和输出。例如: char str[10]; scanf(“%s”,str); printf("%s",str); 这里str是数组名,输入字符依次存入以数组首地址为起点的存储单元。并自动在末尾加‘\0’。用%s格式符输入字符串时,是以空格符,TAB符,及回车符来结束一个串的输入的。若输入字符串长度超过字符数组所能容纳的字符数时,系统不报错,相当于下标超界。 执行输出语句时,将从这一地址开始,依次输出存储单元中的字符,知道遇到一个‘\0’结束输出。‘\0’不在输出之列。输出结束后不自动换行。
字符数组—引用 (2)调用gets( )和puts( )函数实现字符串整体输入输出。例如: char str[10]; gets(str); 其中str接受从键盘读入字符串(包括空格符),直到读入一个换行符为止,系统自动把换行符用‘\0’代替。例如执行上述语句时,若从第一列输入: Helloc!<CR> (此处代表空格,<CR>代表Enter键) 将读入9个字符(包括空格和换行符),系统自动用‘\0’代替最后换行符。用puts( )函数实现字符串整体输出,例如: puts(str); 其中str为数组名,执行上述语句时,从数组str首地址开始,依次输出存储单元中字符,遇到第一个‘\0’结束输入,并自动输出一个换行。
字符数组—引用 例 7 引用数组名输入输出字符串。 main() { char str[80]; printf(“请输入一字符串:”); gets(str); printf(“\n输入的字符串是:”); puts(str); } 程序运行结果: 请输入一字符串:Happy 输入的字符串是:Happy
字符数组—程序举例 例 8编写一程序,实现两个字符串s1和s2的比较,并根据比较的情况输出下列结果: 负数s1<s2 r = 0 s1==s2 正数s1>s2 分析:字符串进行比较的方法是:从两字符串(数组)的初始位置(i=0)开始,将它们对应位置(相同下标)的字符的ASCII码值进行比较,只有当前字符相等(s1[i]=s2[i])而且不是两字符串“同时”到尾(s1[i]!=0),才继续去比较下一个(i值增1)字符。 有两种情况会结束比较: 第一种是出现不相等字符,第二种是两字符相等,但遇到了串结束符‘\0’,因此,不管哪种情况,可由当前两个字符相减而得到最后结果。当s1[i]和s2[i]不相等,若s1[i]大于s2[i],相减结果大于0表示s1串大于s2串,若s1[i]小于s2[i],相减结果小于0表示s1串小于s2串。若两串相等,同时遇到结果标志,相减的值必然等于0。
程序 Input No.1 string:ABCDMFG Input No.2 string:ABCDEFHJK The result is:7 main() {char s1[81],s2[81]; int i=0,r; printf("\nInput No.1 string: "); gets(s1); /* 从键盘输入第一个字符串入s1 */ printf("\nInput No.2 string: "); gets(s2); /* 从键盘输入第二个字符串入s2 */ while(s1[i]==s2[i]&&s1[i]!='\0') /* 两数组对应元素进行比较 */ i++; /* 出现不相等字符或遇到了串结束符‘\0’时结束比较 */ r=s1[i]-s2[i]; /* 不等字符相减得到差值 */ printf("The result is:%d\n",r);}
字符数组—程序举例 程序 例 9 从键盘上输入一个字符串,并复制到另一个字符数组后显示出来。 main() { char str1[20],str2[20]; int j=0; printf(”Input a string:”); scanf(“%s”,str1); while(str1[j]!=‘\0’) {str2[j]=str1[j];j++;} str2[j]=‘\0’; printf(“%s”,str2); } 提示:复制字符串就是将str1串中的字符逐个放到数组str2的对应数组元素中(包括‘\0’)。
字符串处理函数 C语言中没有提供对字符串进行整体操作的运算符,但提供了很多有关字符串操作的库函数。例如,不能由运算符实现的字符串赋值、合并和比较运算,都可以通过调用库函数来实现。下面介绍4种常用的字符串处理函数。在使用这些函数时,必须在程序前面用命令行指定包含标准头文件“string.h”。
字符串处理函数 1、求字符串长度函数strlen。函数的调用形式如下: strlen(s) 此函数计算出以S为其地址的字符串的长度,作为函数值返回。这一长度不包括串尾的结束标志‘\0’ 编一程序,求字符串的长度。 main() { int j=0; char str1[]={“string.”}; while(str1[j]!=‘\0’) j++; printf(“the lenth of str1=%d”, j); } #include “string.h” printf(“the lenth of str1=%d”, strlen(str1));
字符串处理函数 2、字符串复制(拷贝)函数strcpy。调用形式如下: strcpy(s1,s2) 此函数用来把s2所指字符串(源)的内容复制到s1所指存储空间(目的)中,函数返回s1的值,即目的串的首地址。注意:为保证复制的合法性,s1必须指向一个足够容纳s2串的存储空间。 字符串拷贝时连同‘\0’一起拷贝。 Strcpy函数的应用: char str1[6],str2[]={“China”}; strcpy(str1,str2); 或strcpy(str1, “China”); 两个字符串拷贝不能使用: str1=str2
字符串处理函数 3、字符串连接函数strcat。strcat函数的调用形式如下: strcat(s1,s2); 该函数将s2所指字符串的内容连接到s1所指的字符串后面,并自动覆盖s1串末尾的‘\0’;函数返回s1地址值。s1所指字符串应有足够空间容纳两串合并后的内容 。 Strcat函数的应用: char str1[20]={“This is a “}; char str2[]={“string.”}; printf(“%s”, strcat(str1,str2)); … 运行结果:This is a string.
字符串处理函数 4、字符串比较函数strcmp。函数的调用形式如下: strcmp(s1,s2) 该函数用来比较s1和s2所指字符串的大小。若串s1>串s2,函数值大于0;若串s1==串s2,函数值等于0;若串s1<串s2,函数值小于0(负数)。 字符串的比较方法是:依次对s1和s2所指字符串对应位置上的字符两两进行比较,当出现第一对不相同的字符时,即由这两个字符决定所在串的大小(字符大小的依据是其ASCII码值)。 两个字符串比较不能使用: if(str1==str2)… • char str1[]=“Chinese”,str2[]=“China”; • r=Strcmp(str1,str2); • r=Strcmp(str1, “string”); • r=Strcmp(“string”, “strong”); • if(strcmp(str1,str2)==0)… 作业:把教科书例4.13改写为使用字符串比较函数来作。
小结(1) 数组是一种整体定义、个别使用的数据结构。数组的整 体特征,在定义一个数组的语句中已经得到了最完整的说明。作为使用的个体,数组中的每个元素都有如下特征: 每个数组元素相当于一个同类性简单变量,但又不是孤立的一个简单变量。它是属于一个整体中的一员,这从数组元素的表示方法中可体现出。数组元素引用的方法是: 数组名[下标] 数组名是整体特征,而下标是个体表现。这种使用下标对数组元素进行引用的方法称“下标法”。应该说明一点的是,对数组元素的引用方法除下标法外,还有所谓“指针法”,这将在后续章节中介绍。
小结(2) . 数组名是地址常量 当程序中定义了一个数组后,系统将会为数组在内存分配一连续内存空间,数组元素按顺序号由小到大依次对应各存储单元,元素a[0]的地址就是数组的首地址。C语言用数组名来表示这一地址,这是一个地址常量。因此,数组名不能出现在赋值语句中赋值号的左端。 一般而言,C语言中只能逐个引用数组元素,而不能使用数组名一次引用整个数组(字符数组除外)。
小结(3) 数组下标越界问题 当定义了一数组后,数组的大小(长度)即数组元素的个数就确定了。由于C语言中下标的起始值由0开始,因此下标的最大值只能是数组长度减1。所谓数组下标越界的问题是指数组元素引用时,下标小于0或小表大于等于数组长度。 C编译系统在程序运行过程中并不自动检验数组元素的下标是否越界。因此数组两端都可能因为越界而破坏其它存储单元中的数据,甚至破坏了程序代码,出现预料不到的结果。因此,在编写程序时保证数组下标不越界是很重要的。
小结(4) 数组元素的顺序处理 由于一维数组元素引用时需一个下标,因此一维数组元素的顺序处理总是和单重循环联系在一起的。此时,循环变量就作为数组元小结素的下标变量来使用。循环变量的初值为0而终值就是数组元素的下标上限。 二维数组元素引用需要两个下标,因此二维数组元素的顺序处理总是和两重循环联系在一起。根据程序中具体情况,外层和内层的两个循环变量分别对应数组元素的行(列)下标变量。一般而言,两个循环变量的初值为下标下限,而终值都为行(列)的下标上限 。 对于存放字符串的字符数组,如果要依次处理各元素,有两种方法:如果已知字符串的长度,可以使用次数性循环语句,循环变量的初值是数组元素下标的下限,用字符串长度来控制循环结束;如果不知道字符串的长度,用循环语句来处理字符串时,控制循环结束的条件是当前字符是‘\0’
本章课后作业 • 复习教材第四章4.3-4.6内容 • 预习教材第五章内容 • 上机实习内容: 《C实验指导与习题》第四章 实验八 数组 • 完成《C实验指导与习题》第四章的全部习题