串
串的定義
概念
- 串是由零個或多個字符數組組成的有限序列。
- 串中字符的個數稱為串的長度,含有零個元素的叫空串。
- 串是限定了元素為字符的線性表
(注:串與一般的線性表操作有很大區別,線性表主要針對表內的某個元素,而串操作主要針對子串)
代碼
在C語言中,一個串可以如下定義,但僅以'\0'作為結束符時需要我們遍歷整個數組,時間復雜度為O(n),這並不是我們想要的最優結果,
其他方法會在下文“串的結構體定義”部分有詳細描述,這里僅舉個例子
char str[] = "as123";
對C語言來講,串主要由一個字符數組表示,上方字符串str中的字符有 'a' ,'s', '1','2','3','\0'
下對'\0'單獨介紹
‘\0’
'\0'是轉譯字符,意思是告訴編譯器,這不是字符0,而是空字符,是字符串的結束標志。
故字符數組str的長度為7,而串str的長度為6
串相關的術語
- 串中任意連續的字符組成的子序列稱為該串的子串
- 包含子串的串稱為主串
- 某個字符在串中的序號稱為這個字符的位置
- 有一個或多個空格組成的串稱為空格串
串的結構體定義
串的儲存結構主要分為定長順序儲存與變長分配儲存兩種
定長順序儲存
用額外一個變量來存放串的長度,這樣求串長時間復雜度就降為了O(1)
#define MAXSIZE 1024
//串的定長順序儲存結構
typedef struct _str
{
char str[MAXSIZE+1];
int length;
}Str;
變長分配儲存
//串的變長儲存結構
typedef struct _str_p
{
char *ch;
int length;
}Str_p;
串的操作
此處以變長儲存為例(定長順序儲存沒什么太值得好說的)
//先定義一個串的結構體
typedef struct _str_p
{
char *ch;
int length;
}Str_p;
//定義一個串
Str_p str;
串的初始化
bool initStr(Str_p &str)
{
str.length = 0;
str.ch = nullptr;
return true;
}
串的賦值
ISO C++11 does not allow conversion from string literal to 'char *'
注意:在C++11里,指針指向的內容如果不可修改,就建議把該指針確認為const指針類型,否則會有個warning
也就是說我們這里要用 const char* ch 而非 char* ch
//參數:串, 串的內容
bool inputString(Str_p &str, const char* ch)
{
if(str.ch) free(str.ch);
int len = 0;
const char *c = ch;
while(*c)
{
++len;
//因為內存連續,所以可以對c進行自增
++c;
}
//若賦值為空,即該串為空串
if(!len)
{
str.ch = nullptr;
str.length = 0;
return true;
}
else
{
//len+1是為了存放'\0'
str.ch = (char*)malloc(sizeof(char)*(len+1));
if(!str.ch) return false;
else
{
c = ch;
for(int i=0; i<len; i++,c++)
str.ch[i] = *c;
str.length = len;
return true;
}
}
}
獲取串的長度
int getStrLen(Str_p str)
{
return str.length;
}
串的比較
//串的比較
int strCompare(Str_p s1, Str_p s2)
{
for(int i=0; i<s1.length && i<s2.length; i++)
if(s1.ch[i]!=s2.ch[i])
return s1.ch[i] - s2.ch[i];
return s1.length - s2.length;
}
合並串
//參數: 合並后的字符串, 子串1, 子串2
bool conStr(Str_p &str, Str_p s1, Str_p s2)
{
initStr(str);
if(str.ch)
{
free(str.ch);
str.ch = nullptr;
}
str.ch =
(char*)malloc(sizeof(char*)*(s1.length+s2.length+1));
if(!str.ch) return false;
//將s1的字符保存到str
int i;
for(i=0; i<s1.length;i++)
str.ch[i] = s1.ch[i];
//同理
int j;
//此處取等號是為了把'\0'放進去
for(j=0; j<=s2.length; j++)
str.ch[i+j] = s2.ch[j];
str.length = s1.length + s2.length;
return true;
}
求子串
//參數: 子串, 父串, 起始位置, 切片長度
bool subStr(Str_p &substr,Str_p str, int pos, int len)
{
initStr(substr);
if(pos<0||
pos>str.length||
len<0||
len>str.length-pos)
return false;
if(substr.ch)
{
free(substr.ch);
substr.ch = nullptr;
}
//所求子串為空串
if(!len)
{
substr.ch = nullptr;
substr.length = 0;
return true;
}
else{
substr.ch =
(char*)malloc(sizeof(char)*(len+1));
int i = pos, j = 0;
while(i<pos+len)
{
substr.ch[j] = str.ch[i];
i++;
j++;
}
substr.ch[j] = '\0';
substr.length = len;
return true;
}
}
清空串
bool clearStr(Str_p &str)
{
if(str.ch)
{
free(str.ch);
str.ch = nullptr;
}
str.length = 0;
return true;
}