定长字符串

本文深入探讨了定长字符串的概念,包括其特点、优缺点以及在实际编程中的应用场景。通过示例代码展示了如何在C++中定义和操作定长字符串。

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

//SString.h

//字符串的定长顺序存储方式,字符串将位于栈上,其本身为以'\0'结尾的一串字符数组

#ifndef _SSTRING_H_
#define _SSTRING_H_

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>

#define STRINGLENGTH	20

typedef unsigned char UCHAR;
typedef UCHAR SString[STRINGLENGTH + 1];	//定义数组类型


void InitString(SString ss);	
void StrAssign(SString ss, const char *string);	
void StrCpy(SString des, const SString src);
int  StrLen(const SString s);
void Show(const SString s);
bool StrEmpty(const SString ss);
int  StrCmp(const SString s1, const SString s2);
void StrConcat(SString T, const SString s1, const SString s2);			//将串s1 s2连接成一个串T
void SubString(const SString s, SString sub, int pos, int len);			//在主串s的pos处取长度len个字符作为子串
int  StrIndex(const SString s, const SString sub, int pos);				//查找子串sub在主串s中的下标,从主串s的pos位置开始查找,未找到返回-1
void StrReplace(SString s, const SString sub, const SString T);			//将主串s中的全部不重复子串sub全部替换为T
void StrInsert(SString s1, const SString s2, int pos);					//将串s2插入串s1的位置pos处
void StrDelete(SString s1, int pos, int len);							//在串s1的位置pos处删除长度为len的字符串
void StringClear(SString s);

#endif //_SSTRING_H_



//SString.c

#include "SString.h"

void InitString(SString ss)
{
	ss[0] = '\0';
}

void StrAssign(SString ss, const char *string)
{
	int i = 0, j = strlen(string);
	if( STRINGLENGTH < j )					//数组容量比string所指字符数少,截断赋值
	{
		for (i = 0; i < STRINGLENGTH; i++)
		{
			ss[i] = string[i];
		}
		ss[STRINGLENGTH] = '\0';			//结束符
	}
	else									//正常赋值
	{
		for(i = 0; i < j; i++)
		{
			ss[i] = string[i];
		}
		ss[j] = '\0';						//结束符
	}
}

void StrCpy(SString des, const SString src)
{
	int len = StrLen(src), i = 0;
	for(i = 0; i < len; i++)	//将src中的有效字符全部复制到des中
	{
		des[i] = src[i];
	}
	des[len] = '\0';
}

int  StrLen(const SString s)
{
	int len = 0;
	const UCHAR *p = s;
	while('\0' != *p++)
		len++;

	return len;
}

void Show(const SString s)
{
	printf("%s\n", s);
}

bool StrEmpty(const SString ss)
{
	return '\0' == *ss;
}
//比较两个数组内部的字符串的ASCII码大小,如果s1大于s2返回正数,等于返回0,否则返回负数 ,当某个短串比较完毕后其与长串所有字符一致,则更长着大
int  StrCmp(const SString s1, const SString s2)
{
	const UCHAR *p = s1, *q = s2;
	while(('\0' != *p) && ('\0' != *q) && (*p == *q))	//如果在while内使用前置或后置++则应注意短路法则
	{
		p++;
		q++;
	}
	return *p - *q;
}
//数组的容量有限,不一定能装下s1与s2中全部有效字符,需判断
void StrConcat(SString T, const SString s1, const SString s2)			//将串s1 s2连接成一个串T
{
	int len_t = StrLen(T), len_s1 =  StrLen(s1), len_s2 =  StrLen(s2);
	int i = 0, j = 0;

	//无论如何都能装下S1
	for (i = 0; i < len_s1; i++)
	{
		T[i] = s1[i];
	}

	if( STRINGLENGTH >= len_s1 + len_s2 )	//至少刚好能装下s1与s2
	{
		for(j = 0; j < len_s2; j++)
		{
			T[i + j] = s2[j];
		}
		T[i +j] = '\0';
	}
	else if( STRINGLENGTH > len_s1 )		//能装下全部s1与部分s2
	{
		for(j = 0; j < STRINGLENGTH - len_s1; j++)
		{
			T[i + j] = s2[j];
		}
		T[STRINGLENGTH] = '\0';
	}
	else									//只能装下s1
	{
		T[i] = '\0';
	}
}

void SubString(const SString s, SString sub, int pos, int len)			//在主串s的pos处取长度len个字符作为子串
{
	if( pos < 0 || pos >= StrLen(s) || len <= 0 || len > StrLen(s) - pos )
		return ;

	int i = 0;
	for(i = 0; i < len; i++)
	{
		sub[i] = s[pos + i];
	}
	sub[i] = '\0';
}

int StrIndex(const SString s, const SString sub, int pos)				//查找子串sub在主串s中的下标,从主串s的pos位置开始查找,未找到返回-1
{
	int i = pos, j = 0;

	while( '\0' != s[i] && '\0' != sub[j])								//如果sub遍历完成,说明存在s中存在sub,如果s遍历完成,说明其中不存在sub
	{
		if( s[i] == sub[j] )
		{
			i++;
			j++;
		}
		else					//一旦发现不匹配,重新比较s的以前一次比较的开始字符之后1字符为开头的数个字符与串sub全部字符
		{
			i = i - j + 1;		//回溯, 回退到前一次比较开始字符的下一字符
			j = 0;				
		}
	}
	if( '\0' == sub[j] )		//sub遍历完成,即sub中所有字符均连续存在于s中,返回sub在s中的位置	
	{
		return i - j;
	}
	else						//未找到连续的匹配字符,返回-1表示不存在
		return -1;
}

void StrReplace(SString s, const SString sub, const SString T)			//将主串s中的全部不重复子串sub全部替换为T
{
	int index = 0, len = StrLen(sub);
	while(-1 != (index = StrIndex(s, sub, index))) 
	{
		StrDelete(s, index, len);										//删除字符串s中index开始处的长为len的字符串
		StrInsert(s, T, index);											//将字符串插入index位置
	}
}

//如果s2插入后s1与s2的整体长度大于数组长度,则使s2实际插入长度为 数组长度 - s1 长度
void StrInsert(SString s1, const SString s2, int pos)					//将串s2插入串s1的位置pos处
{
	if( pos < 0 || pos > StrLen(s1) || STRINGLENGTH == StrLen(s1) )	 //当数组只能装s1时,无需插入
		return ;

	int i =  StrLen(s1) - pos;										//串s1从pos位置开始的字符都往后移动,i为字符长度
	int len = 0;
	int j = 0;
	if( STRINGLENGTH >= StrLen(s1) + StrLen(s2) )					//数组能完全容纳串s1与s2
	{		
		len = StrLen(s2);											//待插入长度为整个s2长度
	}
	else															//( STRINGLENGTH > StrLen(s1) ) 能插入部分s2
	{
		len = STRINGLENGTH - StrLen(s1);							//待插入长度为数组余下容量
	}

	for (j = i; j >= 0; j--)
	{
		s1[pos + len + j] = s1[pos + j];							//以从后往前的顺序将pos之后那段字符移动到pos+len往后的位置
	}
	s1[pos + len + i] = '\0';

	for (j = 0; j < len; j++)
	{
		s1[pos + j] = s2[j];										//插入
	}
}

void StrDelete(SString s1, int pos, int len)							//在串s1的位置pos处删除长度为len的字符串
{
	if( pos < 0 || pos >= StrLen(s1) || len <= 0 || len > StrLen(s1) - pos )
		return ;
	int i = StrLen(s1) - pos - len;								//待删字符串之后的有效字符长度		
	int j = 0;	
	for(j = 0; j < i; j++)										//移动待删字符串之后的字符到指定位置完成删除操作
	{
		s1[pos + j] = s1[pos + len + j];						
	}
	s1[pos + j] = '\0';											//更新结束符
}

void StringClear(SString s)
{
	s[0] = '\0';
}





//main.c

#include "SString.h"

void main()
{
	SString ss;
	InitString(ss);
	const char * p = "123456789";
	StrAssign(ss, p);
	printf("串长度为%d\n", StrLen(ss));
	Show(ss);

	SString t;
	InitString(t);
	StrCpy(t, ss);
	Show(t);

	if( StrEmpty(t) )
		printf("串为空\n");
	else
		printf("串不为空\n");
	StrAssign(t, "00000");
	int i = StrCmp(t, ss) ;

	if( i > 0 )
		printf("t大于ss\n");
	else if( i < 0 )
		printf("t小于ss\n");
	else
		printf("等于\n");

	SString T;
	InitString(T);
	StrConcat(T, t, ss);
	Show(T);

	SString x;
	InitString(x);
	SubString(T, x, 0, 18);
	Show(x);

	StrInsert(ss, t, 1);
	Show(ss);
	StrDelete(ss, 1, 5);
	Show(ss);


	StrAssign(ss, "122312235456456");
	SString r;
	InitString(r);
	StrAssign(r, "456");
	int j = StrIndex(ss, r, 0);
	printf("%d\n", j);

	StrReplace(ss, r, t);
	Show(ss);

	system("pause");
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值