描述各种信息的文字符号序列称为字符串,简称串。在计算机上的非数值处理一般都是字符串数据。
1. 串类型的定义
串(string)是由零个或多个字符构成的有限序列,通常记为:
s="a0a1⋯an,n≥0"
s
="
a
0
a
1
⋯
a
n
,
n
≥
0
"
其中,s是串名,用双引号圈起来的部分(不包含双引号)称为串值,每个 ai(0≤i≤n) a i ( 0 ≤ i ≤ n ) 为字符。长度为0的串称为空串。各个字符全是空格字符的串称为空格串。
串中任何连续字符组成的子序列称为此串的子串,包含子串的串相应的称为主串。串中某个字符在串中出现的位置称为该字符在串中的位置,子串中第0个字符在主串中的位置称为子串在主串中 的位置。
串之间大小关系的定义:
设有两个串:str1 和 str2
str1="a0a1⋯an−1",str2="b0b1⋯bm−1"
str1
="
a
0
a
1
⋯
a
n
−
1
"
,
str2
="
b
0
b
1
⋯
b
m
−
1
"
str1和str2之间的大小关系定义如下:
(1) 如果 m=n m = n 且 a−i=bi,i=1,2,⋯,n−1 a − i = b i , i = 1 , 2 , ⋯ , n − 1 则称str1 = str2;
(2) 如果下面两个条件中有一个满足条件,则称str1 < < <script type="math/tex" id="MathJax-Element-8"><</script> str2:
(a).m < < <script type="math/tex" id="MathJax-Element-9"><</script> n,且 ai=bi,i=0,1,2,⋯,m−1 a i = b i , i = 0 , 1 , 2 , ⋯ , m − 1
(b).存在某个 0≤k≤min(m,n) 0 ≤ k ≤ min ( m , n ) 使得 ai=bi,i=0,1,2,⋯,k−1,ak≤bk a i = b i , i = 0 , 1 , 2 , ⋯ , k − 1 , a k ≤ b k
(3)不满足条件(1)(2)时,则称 str1 ≥ ≥ str2。
2. 字符串的实现
在C++语言中,提供了两种字符串的实现。其中一种是比较原始的C风格的串这种串的类型为char*,字符串以字符‘\0’结束,这种形式的串在应用时容易出问题,当 char* = NULL时,许多字符串库函数将会崩溃。另外一种是C++已经包装好的string类。这里我们做一个类似于string类的一个String类。
//头文件
#pragma once
#pragma warning( disable : 4996)
#include <cstring>
#include <iostream>
// 串类
class String
{
protected:
// 串实现的数据成员:
char *strVal; // 串值
int length; // 串长
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
String(); // 构造函数
virtual ~String(); // 析构函数
String(const String ©); // 复制构造函数
String(const char *copy); // 从C风格串转换的构造函数
//String(LinkList<char> ©);// 从线性表转换的构造函数
int getLength() const; // 求串长度
bool isEmpty() const; // 判断串是否为空
String &operator =(const String ©);
// 赋值语句重载
const char *CStr() const;// 将串转换成C风格串
const char & operator [](int i) const;
// 重载下标运算符
};
//串相关操作
// 输出串
//void Write(const String &s);
// 将串addOn连接到addTo串的后面
void Concat(String &addTo, const String &addOn);
// 将串original复制到串copy
void Copy(String ©, const String &original);
// 将串original复制n个字符到串copy
void Copy(String ©, const String &original, int n);
// 查找模式串pattern第一次在目标串target中从第 pos个字符开始出现的位置
int Index(const String &target, const String &pattern,int pos = 0);
// 求串s的第pos个字符开始的长度为len的子串
String& SubString(const String &s, int pos, int len);
// 重载关系运算符==
bool operator ==(const String &first,const String &second);
// 重载关系运算符<
bool operator <(const String &first,const String &second);
// 重载关系运算符>
bool operator >(const String &first,const String &second);
// 重载关系运算符<=
bool operator <=(const String &first,const String &second);
// 重载关系运算符>=
bool operator >=(const String &first,const String &second);
// 重载关系运算符!=
bool operator !=(const String &first,const String &second);
void write(String &S);
//cpp文件
#include "String.h"
using namespace std;
String::String()
{
length = 0;
strVal = NULL;
}
String::String(const String ©)
{
if (© != this)
{
length = copy.length;
strVal = new char[length + 1]; // 分配存储空间
strcpy(strVal, copy.strVal);
}
}
String::~String()
{
delete[] strVal;
}
String::String(const char *inString)
// 操作结果:从C风格串转换构造新串——转换构造函数
{
length = strlen(inString); // 串长
strVal = new char[length + 1]; // 分配存储空间
strcpy(strVal, inString); // 复制串值
}
int String::getLength() const
{
return length;
}
bool String::isEmpty() const
{
return length == 0;
}
String & String::operator =(const String ©)
{
if (copy.isEmpty())
{
length = 0;
strVal = NULL;
}
else
{
length = copy.length;
strVal = new char[length + 1]; // 分配存储空间
strcpy(strVal, copy.strVal);
}
return *this;
}
const char *String::CStr() const
// 操作结果:将串转换成C风格串
{
return (const char *)strVal;// 串值类型转换
}
const char& String::operator [](int i) const
{
return strVal[i];
}
void Concat(String &addTo, const String &addOn)
{
const char* cFirst = addTo.CStr();//指向第一个串
const char* cSecond = addOn.CStr();//指向第二个串
char* copy = new char[addOn.getLength() + addTo.getLength() + 1];//分配空间
strcpy(copy, cFirst);
strcat(copy, cSecond);
addTo = copy;//注意这里
delete[] copy;
}
void Copy(String ©, const String &original)
{
copy = original;
}
void Copy(String ©, const String &original, int n)
{
char* temp = new char[n + 1];
for (int i = 0; i < n; i++ )
{
temp[i] = original[i];
}
temp[n] = '\0';
copy = temp;
delete[] temp;
}
int Index(const String &target, const String &pattern, int pos)
{
const char* cTarget = target.CStr();
const char* cPattern = pattern.CStr();
const char* ptr = strstr(cTarget + pos, cPattern);//strstr函数,strchr函数
if (ptr == NULL)
{
return -1;
}
else
{
return ptr - cTarget;
}
}
String& SubString(const String &s, int pos, int len)
{
char* temp = new char[len + 1];
temp[len] = '\0';
int count = 0;
for (int i = pos; i < pos + len; i++)
{
temp[count] = s[i];
count++;
}
String stemp(temp);
delete[] temp;
return stemp;
}
bool operator ==(const String &first, const String &second)
{
return strcmp(first.CStr(), second.CStr()) == 0;
}
bool operator <(const String &first, const String &second)
{
return strcmp(first.CStr(), second.CStr()) < 0;
}
bool operator >(const String &first, const String &second)
{
return strcmp(first.CStr(), second.CStr()) > 0;
}
bool operator <=(const String &first, const String &second)
{
return strcmp(first.CStr(), second.CStr()) <= 0;
}
bool operator >=(const String &first, const String &second)
{
return strcmp(first.CStr(), second.CStr()) >= 0;
}
bool operator !=(const String &first, const String &second)
{
return strcmp(first.CStr(), second.CStr()) != 0;
}
void write(String &S)
{
for (int i = 0; i < S.getLength(); i++)
{
cout << S[i]<<endl;
}
}
//测试文件
#include "String.hpp"
using namespace std;
int main(int argc, char* argv[])
{
char a[5] = "abcd";
char a2[3] = "cd";
String s(a);
write(s);
String s2(s);
write(s2);
String s3(a2);
Concat(s, s2);
write(s);
cout << Index(s, s3) << endl;
getchar();
return 0;
}
之后有时间将增加字符串匹配的常用算法