数据结构五: 串

描述各种信息的文字符号序列称为字符串,简称串。在计算机上的非数值处理一般都是字符串数据。

1. 串类型的定义

串(string)是由零个或多个字符构成的有限序列,通常记为:

s =" a 0 a 1 a n , n 0 "

其中,s是串名,用双引号圈起来的部分(不包含双引号)称为串值,每个 a i ( 0 i n ) 为字符。长度为0的串称为空串。各个字符全是空格字符的串称为空格串。
串中任何连续字符组成的子序列称为此串的子串,包含子串的串相应的称为主串。串中某个字符在串中出现的位置称为该字符在串中的位置,子串中第0个字符在主串中的位置称为子串在主串中 的位置。
串之间大小关系的定义:
设有两个串:str1 和 str2
str1 =" a 0 a 1 a n 1 " , str2 =" b 0 b 1 b m 1 "

str1和str2之间的大小关系定义如下:
(1) 如果 m = n a i = b i , i = 1 , 2 , , n 1 则称str1 = str2;
(2) 如果下面两个条件中有一个满足条件,则称str1 < str2:
   (a).m < n,且 a i = b i , i = 0 , 1 , 2 , , m 1
   (b).存在某个 0 k min ( m , n ) 使得 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 &copy); // 复制构造函数
    String(const char *copy);   // 从C风格串转换的构造函数
    //String(LinkList<char> &copy);// 从线性表转换的构造函数

    int getLength() const;  // 求串长度
    bool isEmpty() const;   // 判断串是否为空

    String &operator =(const String &copy);
    // 赋值语句重载
    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 &copy, const String &original);

// 将串original复制n个字符到串copy 
void Copy(String &copy, 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 &copy)
{
    if (&copy != 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 &copy)
{
    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 &copy, const String &original)
{
    copy = original;
}

void Copy(String &copy, 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;
}

之后有时间将增加字符串匹配的常用算法

猜你喜欢

转载自blog.csdn.net/wuye999/article/details/79509974