<script language=JavaScript> </script>今天是 <script language=JavaScript> </script> |
4.1串
串(又称字符串)是一种特殊的线性表,它的数据元素仅由一个字符组成。
计算机非数值处理的对象常常是字符串数据。它在文字编辑、词法扫描、符号处理等许多领域得到越来越广泛的应用。
本章将讨论串的有关概念,一些基本的串处理操作和几种不同的存储结构。
4.1.1串的基本概念
?1、串
串(String)是由零个或多个字符组成的有限序列,是数据元素为单个字符的特殊线性表。
一般记为 S="a1a2……an" (n≥0)
其中:
▲ S是串名
▲ 双引号括起的字符序列a1a2……an是串值,可以是字母、数字或其它字符;
▲ 双引号本身不属于串, 它只说明其中的字符序列是串,而不是常数或标识符。
- 串中所包含的字符个数称为该串的长度。
【例1】"345"是数字字符串,它不同于整常数345
【例2】" abcde "是长度为5的字符串,但在内存中占6个字节,最后一个字节存放’/0’。
【例3】’A’为字符, "A"为字符串。%c为字符格式, %s为字符串格式。
▲ 提示
对于串变量,C/C++中是用字符数组来保存字符串的。
char st[]="abc/'*123";
gets(st); scanf("%s",st);
strcpy(st,"data");
puts(st); printf("st=%s/n",st);
对于字符变量
char ch='A';
ch=’B’; ch=getchar();
scanf("%c",&ch);
printf("ch=%c/n",ch);
putchar(ch);
2、空串和空白串
▲? 空串(Empty String)长度为零的串,它不包含任何字符。
- 空白串(Blank String)仅由一个或多个空格组成的串。
【例1】""是空串,不包含任何字符。
【例2】"?? ?"是空白串,由多个空格组成。
▲ 注意:
空串和空白串的不同。
【例3】″″和″? ″分别表示长度为0的空白串和长度为2(包含两个空格)的空串。
3、子串和主串
▲ 子串?? 串s中任意个连续的字符组成的子序列称为串s的子串。
▲ 主串?? 包含某个子串的串。
【例1】串s="ABC123A123CD"
?????? s1="ABC"???? s3="123A"??? s4="ABCA"
?????? s2="ABC12"?? s5="ABCE"???
则:s1,s2,s3为串s的子串。
▲ 子串的位置? 通常将子串的第一个字符在对应的主串中的序号定义为子串在主串中的位置。
【例2】设A和B分别为
A="This is a string"
B="is"
则B是A的子串,B在A中出现了两次。首次出现时,B的第一个字符’i’在对应的主串中的序号是2(A[2]=’i’)。因此B在A中的位置是2。
▲ 串相等?? 两个串的长度相等且对应的字符都相等,则称两个串是相等的。
▲ 提示
C/C++中判断字符串是否相等,需要用到字符串比较函数strcmp(s1,s2)---比较s1和s2的大小
。
C语言中常用的串运算
注:用C处理字符串时,要调用标准库函数 #include<string.h>
(1) strcpy(t,s)---s的串值复制到t中。
? 执行:strcpy(t,"data");? 有:t="data"
(2) strlen(s)----求s的长度
?? strlen("data*123")=8?? strlen("")=0
(3) strcat(s1,s2)----s2的值接到s1的后面。
?? 设 s1="data/0" , s2="123/0"
?? 执行:strcat(s1,s2);
?? 有:? s1="data123/0" , s2="123/0“
(4) strcmp(s1,s2)---比较s1和s2的大小
?? 若s1<s2,返回负整数?? 如:"ABC"<"abc"
?? 若s1=s2,返回0如:??? 如:"abc"=="abc"
?? 若s1>s2,返回正整数?? 如:"ABCD">"ABC"
(5) strstr(s1,s2)----若s2是s1的子串,则指向s2在s1中第1
????? 次出现时的第1个字符的位置,即序号值;否则返回NULL。
? 设 s1="ABE123*DE123bcd"
???? s2="E123"
? 有 strstr(s1,s2)=3
???? s1="ABE123*DE123“
4.1.2串的基本运算
串的运算有很多,下面应用C语言中的相关函数介绍串的部分常用基本运算。
1、求串长
int strlen(char *s);//求串s的长度
【例1】printf("%d",strlen(s1)); //输出s1的串长12
2、串复制
char *strcpy(char *to,*from);//将from串复制到to串中,并返回to开始处指针
【例2】strcpy(s3,s1); //s3="dir/bin/appl",s1串不变
3、联接
char *strcat(char *to,char *from);//将from串复制到to串的末尾,
//并返回to串开始处的指针
【例3】strcat(s3,"/"); //s3="dir/bin/appl/"
strcat(s3,s2); //s3="dir/bin/appl/file.asm"
4、串比较
int strcmp(char *s1,char *s2);//比较s1和s2的大小,
//当s1<s2、s1>s2和s1=s2时,分别返回小于0、大于0和等于0的值
【例4】result=strcmp("baker","Baker"); //result>0
result=strcmp("12","12"); //result=0
result=strcmp("Joe","joseph") //result<0
5、字符定位
char *strchr(char *s,char c);//找c在字符串s中第一次出现的位置,
//若找到,则返回该位置,否则返回NULL
【例5】p=strchr(s2,'.'); //p指向"file"之后的位置
if(p) strcpy(p,".cpp"); //s2="file.cpp"
注意:
①上述操作是最基本的,其中后 4个操作还有变种形式:strncpy,strncath和strnchr。
②其它的串操作见C的<string.h>。在不同的高级语言中,对串运算的种类及符号都不尽相同
③其余的串操作一般可由这些基本操作组合而成
【例6】求子串的操作可如下实现:
void substr(char *sub,char *s,int pos,int len){
//s和sub是字符数组,用sub返回串s的第pos个字符起长度为len的子串
//其中0<=pos<=strlen(s)-1,且数组sub至少可容纳len+1个字符。
if (pos<0||pos>strlen(s)-1||len<0)
Error("parameter error!");
strncpy(sub,&s[pos],len);//从s[pos]起复制至多len个字符到sub
}//substr
4.1.3串的存储结构
串是特殊的线性表,组成串的数据元素是单个字符。故其存储结构与线性表的存储结构类似。
1 串的顺序存储
1 、顺序串
▲ 顺序串是用一组地址连续的存储单元来存储串中的字符序列。因此可用高级语言的字符数组来实现。
(1)直接使用定长的字符数组来定义
该种方法顺序串的具体描述:
#define MaxStrSize 100 //该值依赖于应用,由用户定义
char SeqString[MaxStrSize]; //SeqString是一个可容纳100个字符的顺序串
▲ 注意:
①串的大小在编译时刻就已确定,是静态的。
②直接使用定长的字符数组存放串内容外,一般使用一个不会出现在串中的特殊字符’/0’, 放在串值的末尾来表示串的结束。所以串空间最大值为MaxStrSize时,最多只能放MaxStrSize-1个字符。
【例1】设SeqString[12]=”abcdefghijk”;下面是C语言中存放该串的示意图,以字符'/0'表示串值的终结。
0?? 1?? 2?? 3??? 4?? 5?? 6?? 7??? 8?? 9?? 10?? 11
‘a’ | ‘b’ | ‘c’ | ‘d’ | ‘e’ | ‘f’ | ‘g’ | ‘h’ | ‘i’ | ‘j’ | ‘k’ | ‘/0’ |
用字符数组存放该串的示意图
(2)类似顺序表的定义
▲ 直接使用定长的字符数组存放串内容外,可用一个变量来保存串的长度。
该种方法顺序串的具体描述:?
#define MaxStrSize 100 //该值依赖于应用,由用户定义,,但应小于256,因为char占一个字节
typedef struct str {
char ch[MaxStrSize]; //依次存储在ch[0.. MaxStrSize-1]中
int len;
}SeqString;
SeqString? S;
【例2】设S.ch[12]=”abcdefgh”;下面是C语言中存放该串的示意图,以字符'/0'表示串值的终结。
S.ch[12]=”abcdefgh”;
S. len =8;
0?? 1?? 2?? 3??? 4?? 5?? 6?? 7?? 8??? 9 ??10?? 11
‘a’ | ‘b’ | ‘c’ | ‘d’ | ‘e’ | ‘f’ | ‘g’ | ‘h’ | ‘/0’ |
|
|
|
用顺序串存放该串的示意图
▲▲▲▲▲ 定长顺序存储出现的问题:
- 若字符串超过Maxstrlen 则自动截断(因为静态数组存不进去)。??
- ?
想存放超长字符串怎么办?——定长顺序存储结构(静态数组)有缺陷!
解决办法是改用动态分配的一维数组。我们下面将要介绍串的链式存储结构。
一、字符串输入输出函数
1.scanf和printf:用于输入和输出,输入字符串时遇到空格、tap、回车键即停止输入。
举例:
char s[10];
scanf("%s/n",s);
输入“my name is”则会输出“my”。
2.gets和puts:用于把字符串存入字符数组中;以及将字符输出并自动换行。
举例:
char s[10];
gets(s);
将把用户输入的字符串存入字符数组s中。这时输入“my name is”则就会输出“my name is”。
puts("happy")
可以直接输出字符串
以上函数的函数说明在头文件stdio.h中,写为:
#include"stdio.h"
二、字符串处理函数
1.字符串连接函数strcat
string catenate的缩写,用于把两个字符串连接在一起,组成一个字符串。
举例:
strcat(字符数组1,字符数组2)
把字符数组2中的字符串连接到字符数组1中的字符串后面,并删去原字符数组1后面的“/0”,结果存在字符数组1中。
char str1[30]={"study c"};
char str2[]={"language"};
printf("%s",strcat(str1,str2));
则输出:
strudy c language
注:字符数组1必须定义得足够大,否则不能装入连接后的字符串。
2.字符串拷贝函数strcpy
string copy的缩写,用于把一个字符串(或字符数组中的字符串)复制到一个字符串数组中去。
举例:
strcpy(字符数组1,字符数组2)
或strcpy(字符数组1,字符串常量2)
char str1[15],str2[]="c language";
strcpy(str1,str2);
或:
strcpy(str1,"c language");
3.字符串比较函数strcmp
string compare的缩写,用于按照字典顺序(按ascⅱ码值),对两个字符串自左向右逐个字符比较两个字符串的大小,直到遇到不同字符或“/0”为止。
举例:
strcmp(字符数组1(或字符串1),字符数组2(或字符串2))
比较规则如下:
字符串1=字符串2,返回值=0;
字符串1 >字符串2,返回值 >0;
字符串1 <字符串2,返回值 <0;
char str1[]="beijing";
char str2[]="beijing china";
strcmp(str1,str2);
或:
strcmp("beijing","beijing china");
后,由ascⅱ码可知“beijing”小于“beijing china”,所以返回值 <0。
注:不能用关系运算符进行比较,如:
if(str1==str2) printf("no");是不正确的,只能写成:
if(strcmp(str1,str2)==0) printf("no");
4.测试字符串长度函数strlen
string length的缩写,用于测试字符串的实际长度,其中不包括“/0”。
举例:
strlen(字符数组(或字符串))
例如执行下面的语句
char str[15]={"language"};
strlen(str);
后,返回值是8。不是9,也不是15。
5.字符串大小写转换函数strupr和strlwr
a.strupr是string uppercase的缩写,用于小写转成大写。
举例:
strupr(字符数组(或字符串))
char str[]="language";
printf("%s/n",strupr(str));
b.strlwr是string lowercase的缩写,用于大写转成小写。
举例:
strlwr(字符数组(或字符串))
char str[]="language";
printf("%s/n",strlwr(str));
上面介绍的函数的函数说明包含在头文件string.h中,写为:
#include "string.h"