数据结构之串(一)

本文详细介绍了C语言中字符串(串)的一系列基本操作,包括生成、判空、求串长、输出、复制、比较、拼接、求子串、索引查找、插入、删除、清空和替换等,并提供了相应的代码实现。这些操作涵盖了字符串处理的核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}

END

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值