tips:本文只涉及串的基本操作
目录
串
字符串简称串,计算机上非数值处理的对象基本都是字符串数据。
1.定义
串(string)是由零个或多个字符组成的有限序列。一般记为S=‘a1a2…an’ (n>=0)。
其中,S是串名,单引号括起来的字符序列是串的值:ai可以是字母,数字或其他字符;串中字符的个数n称为串的长度。n=0时的串称为空串。
串中任意多个连续的字符组成的子序列称为该串的子串,相应地,包含子串的串称为主串。某个字符在串中的序号称为该字符在串中的位置。子串在主串中的位置以子串的第一个字符在主串中的位置来表示。当两个串的长度相等且每个对应位置的字符都相等时,称这两个串是相等的。
其中,由一个或多个空格组成的串称为空格串(空格串不是空串),其长度为串中空格字符的个数。
串的逻辑结构和线性表极为相似,区别仅在于串的数据对象为字符集。
2. 基本操作
//生成串
//判空
//求串长
//输出串
//复制串
//比较串
//拼接串
//求子串
//Index
//Index2
//插入串
//删除串
//清空
//替换串
3.代码实现
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 10
typedef int Status;
typedef int ElemType;
typedef char String[MAXSIZE + 1]; /* 0号单元存放串的长度 */
3.1 生成串
/* 生成一个其值等于chars的串T */
Status StrAssign(String T, char* chars) //形参以char*指针接收
{
int i;
if (strlen(chars) > MAXSIZE) //chars的长度即为"abcd"的长度4
{
return ERROR;
}
else
{
T[0] = strlen(chars);
//printf("%d\n", strlen(chars)); //4
for (i = 1; i <= T[0]; i++)
{
T[i] = *(chars + i - 1); //T[1]=*(chars+1-1) =‘a’
}
return OK;
}
}
3.2 判空
//判空
/* 若S为空串,则返回TRUE,否则返回FALSE */
Status StrEmpty(String S)
{
if (S[0] == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
3.3 求串长
//求串的长度
/* 返回串的元素个数 */
int StrLength(String S)
{
return S[0];
}
3.4 输出串
/* 输出串T */
void StrPrint(String T)
{
int i;
for (i = 1; i <= T[0]; i++)
{
printf("%c ", T[i]);
}
printf("\n");
}
3.5 复制串
//复制串
/* 将串S复制 赋值给串T */
Status StrCopy(String T, String S)
{
for (int i = 0; i <= S[0]; i++) //S[0]中存放着串S的长度
{
T[i] = S[i];
}
return OK;
}
3.6 比较串
//比较两个串的大小
/* 操作结果: 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
int StrCompare(String S, String T)
{
for (int i = 1; i <= S[0] && i <= T[0]; ++i)
{
if (S[i] != T[i])
{
return S[i] - T[i];
}
}
return S[0] - T[0];
}
3.7 拼接串
//拼接串
/* 用T返回S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE */
Status StrCat(String T, String s1, String s2)
{
int i = 0;
if (s1[0] + s2[0] <= MAXSIZE)
{ //未截断时
for (i = 1; i <= s1[0]; i++)
{ //将s1的值赋值给T
T[i] = s1[i];
}
for (i = 1; i <= s2[0]; i++)
{ //将s2的值赋值给T
T[s1[0] + i] = s2[i]; //从s1后面接上
}
T[0] = s1[0] + s2[0];
return TRUE;
}
else
{ // 发生截断时
for (i = 1; i <= s1[0]; i++)
{ //将s1的值赋值给T
T[i] = s1[i];
}
for (i = 1; i <= s2[0]; i++)
{ //将s2的值赋值给T
T[s1[0] + i] = s2[i]; //从s1后面接上
}
T[0] = MAXSIZE; //拼接后长度超出数组范围,发生截断
return FALSE;
}
}
3.8 求子串
//从主串S的第pos个字符开始,返回长度为len的子串Sub
Status SubString(String Sub, String S, int pos, int len)
{
//判断输入参数非法情况
if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1)
{
return ERROR;
}
for (int i = 1; i <= len; i++)
{
Sub[i] = S[pos + i - 1];
}
Sub[0] = len;
return OK;
}
3.9 Index
/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
/* 其中,T非空,1≤pos≤StrLength(S)。 */
int Index(String S, String T, int pos)
{
int i = pos; //主串当前位置下标值
int j = 1; //子串当前位置下标值
while (i <= S[0] && j <= T[0])
{
if (S[i] == T[j])
{ //主串当前位置字符 等于 子串当前位置字符时
++i;
++j;
}
else
{
i = i - j + 2; //i退回到上次匹配首位的下一位
j = 1; //j退回到子串T的首位
}
}
if (j > T[0])
{
return i - T[0]; //返回子串在第pos个字符之后的位置
}
else
{
return 0; //主串中不存在于子串相匹配的串
}
}
3.10 Index2
/* T为非空串。若主串S中第pos个字符之后存在与T相等的子串, */
/* 则返回第一个这样的子串在S中的位置,否则返回0 */
int Index2(String S, String T, int pos)
{
int n, m, i;
String sub;
if (pos > 0)
{
n = StrLength(S);
m = StrLength(T);
i = pos;
while (i <= n - m + 1) //限制子串的长度不能大于主串的长度
{
SubString(sub, S, i, m);
if (StrCompare(sub, T) != 0)
{
++i; //不相等,主串开始比较位置往后移动
}
else
{
return i; //相等
}
}
}
return 0;
}
3.11 插入串
/* 初始条件: 串S和T存在,1≤pos≤StrLength(S)+1 */
/* 操作结果: 在串S的第pos个字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE */
Status StrInsert(String S, int pos, String T)
{
int i;
if (pos<1 || pos >S[0] + 1)
{
return ERROR;
}
if (S[0] + T[0] <= MAXSIZE)
{
//完全插入
for (i = S[0]; i >= pos; i--)
{ //将串S从最后的元素开始,复制到对应位置
S[i + T[0]] = S[i];
}
for (i = pos; i < pos + T[0]; i++)
{ //将子串T的元素从pos处,
S[i] = T[i - pos + 1];
}
S[0] = S[0] + T[0];
return TRUE;
}
else
{
//部分插入
for (i = MAXSIZE; i >= pos; i--)
{
S[i] = S[i - T[0]]; //将主串从pos到MAXSIZE之间的元素,复制到对应的位置
}
for (i = pos; i < pos + T[0]; i++)
{
S[i] = T[i - pos + 1]; //再将子串的值赋值给主串对应的位置(子串的值会覆盖掉主串中的值)
}
S[0] = MAXSIZE;
return FALSE;
}
}
3.12 删除串
/* 初始条件: 串S存在,1≤pos≤StrLength(S)-len+1 */
/* 操作结果: 从串S中删除第pos个字符起长度为len的子串 */
Status StrDelete(String S, int pos, int len)
{
int i;
if (pos<1 || pos>S[0] - len + 1 || len < 0)
{
return ERROR;
}
for (i = pos + len; i <= S[0]; i++)
{
S[i - len] = S[i];
}
S[0] -= len;
return OK;
}
3.13 清空
/* 初始条件:串S存在。操作结果:将S清为空串 */
Status ClearString(String S)
{
S[0] = 0;/* 令串长为零 */
return OK;
}
3.14 替换串
/* 初始条件: 串S,T和V存在,T是非空串(此函数与串的存储结构无关) */
/* 操作结果: 用V替换主串S中出现的所有与T相等的不重叠的子串 */
Status Replace(String S, String T, String V)
{
int i = 1; /* 从串S的第一个字符起查找串T */
if (StrEmpty(T)) /* T是空串 */
{
return ERROR;
}
do
{
i = Index(S, T, i); /* 结果i为从上一个i之后找到的子串T的位置 */
if (i) /* 串S中存在串T */
{
StrDelete(S, i, StrLength(T)); /* 删除该串T */
StrInsert(S, i, V); /* 在原串T的位置插入串V */
i += StrLength(V); /* 在插入的串V后面继续查找串T */
}
} while (i);
return OK;
}
4.完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 10
typedef int Status;
typedef int ElemType;
typedef char String[MAXSIZE + 1]; /* 0号单元存放串的长度 */
/* 生成一个其值等于chars的串T */
Status StrAssign(String T, char* chars) //形参以char*指针接收
{
int i;
if (strlen(chars) > MAXSIZE) //chars的长度即为"abcd"的长度4
{
return ERROR;
}
else
{
T[0] = strlen(chars);
//printf("%d\n", strlen(chars)); //4
for (i = 1; i <= T[0]; i++)
{
T[i] = *(chars + i - 1); //T[1]=*(chars+1-1) =‘a’
}
return OK;
}
}
//判空
/* 若S为空串,则返回TRUE,否则返回FALSE */
Status StrEmpty(String S)
{
if (S[0] == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
//求串的长度
/* 返回串的元素个数 */
int StrLength(String S)
{
return S[0];
}
/* 输出串T */
void StrPrint(String T)
{
int i;
for (i = 1; i <= T[0]; i++)
{
printf("%c ", T[i]);
}
printf("\n");
}
//复制串
/* 将串S复制 赋值给串T */
Status StrCopy(String T, String S)
{
for (int i = 0; i <= S[0]; i++) //S[0]中存放着串S的长度
{
T[i] = S[i];
}
return OK;
}
//比较两个串的大小
/* 操作结果: 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
int StrCompare(String S, String T)
{
for (int i = 1; i <= S[0] && i <= T[0]; ++i)
{
if (S[i] != T[i])
{
return S[i] - T[i];
}
}
return S[0] - T[0];
}
//拼接串
/* 用T返回S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE */
Status StrCat(String T, String s1, String s2)
{
int i = 0;
if (s1[0] + s2[0] <= MAXSIZE)
{ //未截断时
for (i = 1; i <= s1[0]; i++)
{ //将s1的值赋值给T
T[i] = s1[i];
}
for (i = 1; i <= s2[0]; i++)
{ //将s2的值赋值给T
T[s1[0] + i] = s2[i]; //从s1后面接上
}
T[0] = s1[0] + s2[0];
return TRUE;
}
else
{ // 发生截断时
for (i = 1; i <= s1[0]; i++)
{ //将s1的值赋值给T
T[i] = s1[i];
}
for (i = 1; i <= s2[0]; i++)
{ //将s2的值赋值给T
T[s1[0] + i] = s2[i]; //从s1后面接上
}
T[0] = MAXSIZE; //拼接后长度超出数组范围,发生截断
return FALSE;
}
}
//从主串S的第pos个字符开始,返回长度为len的子串Sub
Status SubString(String Sub, String S, int pos, int len)
{
//判断输入参数非法情况
if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1)
{
return ERROR;
}
for (int i = 1; i <= len; i++)
{
Sub[i] = S[pos + i - 1];
}
Sub[0] = len;
return OK;
}
/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
/* 其中,T非空,1≤pos≤StrLength(S)。 */
int Index(String S, String T, int pos)
{
int i = pos; //主串当前位置下标值
int j = 1; //子串当前位置下标值
while (i <= S[0] && j <= T[0])
{
if (S[i] == T[j])
{ //主串当前位置字符 等于 子串当前位置字符时
++i;
++j;
}
else
{
i = i - j + 2; //i退回到上次匹配首位的下一位
j = 1; //j退回到子串T的首位
}
}
if (j > T[0])
{
return i - T[0]; //返回子串在第pos个字符之后的位置
}
else
{
return 0; //主串中不存在于子串相匹配的串
}
}
/* T为非空串。若主串S中第pos个字符之后存在与T相等的子串, */
/* 则返回第一个这样的子串在S中的位置,否则返回0 */
int Index2(String S, String T, int pos)
{
int n, m, i;
String sub;
if (pos > 0)
{
n = StrLength(S);
m = StrLength(T);
i = pos;
while (i <= n - m + 1) //限制子串的长度不能大于主串的长度
{
SubString(sub, S, i, m);
if (StrCompare(sub, T) != 0)
{
++i; //不相等,主串开始比较位置往后移动
}
else
{
return i; //相等
}
}
}
return 0;
}
/* 初始条件: 串S和T存在,1≤pos≤StrLength(S)+1 */
/* 操作结果: 在串S的第pos个字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE */
Status StrInsert(String S, int pos, String T)
{
int i;
if (pos<1 || pos >S[0] + 1)
{
return ERROR;
}
if (S[0] + T[0] <= MAXSIZE)
{
//完全插入
for (i = S[0]; i >= pos; i--)
{ //将串S从最后的元素开始,复制到对应位置
S[i + T[0]] = S[i];
}
for (i = pos; i < pos + T[0]; i++)
{ //将子串T的元素从pos处,
S[i] = T[i - pos + 1];
}
S[0] = S[0] + T[0];
return TRUE;
}
else
{
//部分插入
for (i = MAXSIZE; i >= pos; i--)
{
S[i] = S[i - T[0]]; //将主串从pos到MAXSIZE之间的元素,复制到对应的位置
}
for (i = pos; i < pos + T[0]; i++)
{
S[i] = T[i - pos + 1]; //再将子串的值赋值给主串对应的位置(子串的值会覆盖掉主串中的值)
}
S[0] = MAXSIZE;
return FALSE;
}
}
/* 初始条件: 串S存在,1≤pos≤StrLength(S)-len+1 */
/* 操作结果: 从串S中删除第pos个字符起长度为len的子串 */
Status StrDelete(String S, int pos, int len)
{
int i;
if (pos<1 || pos>S[0] - len + 1 || len < 0)
{
return ERROR;
}
for (i = pos + len; i <= S[0]; i++)
{
S[i - len] = S[i];
}
S[0] -= len;
return OK;
}
/* 初始条件:串S存在。操作结果:将S清为空串 */
Status ClearString(String S)
{
S[0] = 0;/* 令串长为零 */
return OK;
}
/* 初始条件: 串S,T和V存在,T是非空串(此函数与串的存储结构无关) */
/* 操作结果: 用V替换主串S中出现的所有与T相等的不重叠的子串 */
Status Replace(String S, String T, String V)
{
int i = 1; /* 从串S的第一个字符起查找串T */
if (StrEmpty(T)) /* T是空串 */
{
return ERROR;
}
do
{
i = Index(S, T, i); /* 结果i为从上一个i之后找到的子串T的位置 */
if (i) /* 串S中存在串T */
{
StrDelete(S, i, StrLength(T)); /* 删除该串T */
StrInsert(S, i, V); /* 在原串T的位置插入串V */
i += StrLength(V); /* 在插入的串V后面继续查找串T */
}
} while (i);
return OK;
}
void test01()
{
//生成串
String s1; //声明一个char类型的数组s1
StrAssign(s1, "abcd"); //将字符串作为参数来传递,实际上传递的是字符串的第一个字符的地址(地址传参)
//判空
Status i_empty = StrEmpty(s1);
printf("串s1是否为空(1为是/0为否):%d\n", i_empty); //串s1是否为空(1为是/0为否):0
//求串长
int i_length = StrLength(s1);
printf("串s1的长度为:%d\n", i_length); // 串s1的长度为:4
//遍历输出串
StrPrint(s1); //a b c d
printf("-----------------------------\n");
//复制串
String s2;
StrCopy(s2, s1);
//判空
i_empty = StrEmpty(s2);
printf("串s2是否为空(1为是/0为否):%d\n", i_empty); //串s2是否为空(1为是/0为否):0
//求串长
i_length = StrLength(s2);
printf("串s2的长度为:%d\n", i_length); // 串s2的长度为:4
//遍历输出串
StrPrint(s2); //a b c d
printf("-----------------------------\n");
//比较两个串大小
int i_compare = StrCompare(s1, s2);
printf("%d\n", i_compare); //0 (s1=s2)
printf("-----------------------------\n");
//拼接两个串
String s3;
StrCat(s3, s1, s2); //将s1和s2拼接后,赋值给s3
//判空
i_empty = StrEmpty(s3);
printf("串s3是否为空(1为是/0为否):%d\n", i_empty); //串s3是否为空(1为是/0为否):0
//求串长
i_length = StrLength(s3);
printf("串s3的长度为:%d\n", i_length); // 串s3的长度为:8
//遍历输出串
StrPrint(s3); //a b c d a b c d
printf("-----------------------------\n");
String sub;
SubString(sub, s3, 1, 5); //取s3中第1个字符之后长度为5的串,赋值给sub
//判空
i_empty = StrEmpty(sub);
printf("串sub是否为空(1为是/0为否):%d\n", i_empty); //串sub是否为空(1为是/0为否):0
//求串长
i_length = StrLength(sub);
printf("串sub的长度为:%d\n", i_length); // 串sub的长度为:8
//遍历输出串
StrPrint(sub); //a b c d a
printf("-----------------------------\n");
//子串在主串第pos个字符之后的位置
int pos = 1;
int i_index = Index(s3, sub, pos); //(主串,子串,第pos个位置)
printf("子串sub在主串s3中第%d个字符之后的位置是(0表示不存在):%d\n", pos, i_index);
//子串sub在主串s3中第1个字符之后的位置是(0表示不存在):1
int i_index2 = Index2(s3, sub, pos);
printf("子串sub在主串s3中第%d个字符之后的位置是(0表示不存在):%d\n", pos, i_index2);
//子串sub在主串s3中第1个字符之后的位置是(0表示不存在):1
printf("-----------------------------\n");
//#define MAXSIZE 10
//1.
String s4;
StrAssign(s4, "iii");
StrPrint(s4); //i i i
//2.
String s5;
StrAssign(s5, "abcdefgh");
StrPrint(s5); //a b c d e f g h
//3.在s5的第3个位置之前插入s4
StrInsert(s5, 3, s4);
StrPrint(s5); //a b i i i c d e f g
printf("-----------------------------\n");
StrPrint(s5); //a b i i i c d e f g
//从串S中删除第pos个字符起长度为len的子串
StrDelete(s5, 1, 9);
StrPrint(s5); //g
StrDelete(s5, 1, 1);
StrPrint(s5); //(空)
printf("-----------------------------\n");
//清空
StrPrint(s1); //a b c d
ClearString(s1);
StrPrint(s1); //
StrPrint(s2); //a b c d
ClearString(s2);
StrPrint(s2); //
StrPrint(s3); //a b c d a b c d
ClearString(s3);
StrPrint(s3); //
printf("-----------------------------\n");
//1.
StrAssign(s1, "abbcefgbb");
StrAssign(s2, "bb");
StrAssign(s3, "vv");
StrPrint(s1); //a b b c e f g b b
StrPrint(s2); //b b
StrPrint(s2); //b b
StrPrint(s3); //v v
//2.用s3替换主串s1中出现的所有与s2相等的不重叠的子串
// 用vv代替s1中的bb
Replace(s1, s2, s3);
StrPrint(s1); //a v v c e f g v v
}
int main()
{
test01();
return 0;
}