//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';
}
#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");
}