一个能够自动扩容的顺序结构的串 ArrString (GCC编译)。

 /**
* @brief C语言 串 顺序结构 实现
* @author wid
* @date 2013-11-01
*
* @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h> #define TRUE 1
#define FALSE 0
#define NPOS -1 typedef struct
{
char *str;
int len;
int size;
}ArrString; //串结构 //字符串方法声明
ArrString *CreateString( const char *szStr ); ///创建一个初始值为 szStr 的串
void DestroyString( ArrString *pStr ); ///销毁串 pStr
void ClearString( ArrString *pStr ); ///置空串 pStr
int IsEmpty( const ArrString *const pStr ); ///是否为空串
int StrLength( const ArrString *const pStr ); ///获取串长度
int StrCopy( ArrString *pDest, const ArrString *const pSrc ); ///将串 pSrc 复制到 pDest
int StrCat( ArrString *pDest, ArrString *pSrc ); ///将串 pSrc 连接到 pDest 后
int SubStr( ArrString *pStr, ArrString *pSub, int nPos, int nLen ); ///取子串
int IndexStr( const ArrString *const pStr, const ArrString *const pSub, int nPos ); ///子串在串pStr中第一次出现的位置
int InsertStr( ArrString *pDest, const ArrString *const pSrc, int nPos ); ///将 pSrc 插入到 pDest 的 nPos 处
int EraseStr( ArrString *pStr, int nStart, int nEnd ); ///擦除 nStart 至 nEnd 间的子串
int ReplaceStr( ArrString *pStr, ArrString *pFind, ArrString *pReplace ); ///串替换
int StrCompare( const ArrString *const pStr_a, const ArrString *const pStr_b ); ///串比较
char *ToCString( const ArrString *const pStr ); ///转换为C风格字符串 //字符串方法实现 /**
* @brief 创建一个初始值为 szStr 的串
*
* @param szStr 指向一条以 `\0` 结束的字符串
*
* @return 返回指向新建的串的指针
*/
ArrString *CreateString( const char *szStr )
{
int nSrcLen = strlen( szStr ); ArrString *pStr = (ArrString *)malloc( sizeof(ArrString) );
pStr->str = (char *)malloc( nSrcLen + );
strcpy( pStr->str, szStr );
pStr->len = nSrcLen;
pStr->size = nSrcLen + ; return pStr;
} /**
* @brief 销毁串 pStr
*
* @param pStr 指向待销毁的串
*/
void DestroyString( ArrString *pStr )
{
free( pStr->str );
free( pStr );
} /**
* @brief 置空串 pStr
*
* @param 指向待置空的串
*/
void ClearString( ArrString *pStr )
{
pStr->str[] = '\0';
pStr->len = ;
} /**
* @brief 检测是否为空串
*
* @param pStr 指向待检测的串
*
* @return 若串为空, 则返回TRUE, 否则返回 FALSE
*/
int IsEmpty( const ArrString *const pStr )
{
return pStr->len == ? TRUE : FALSE;
} /**
* @brief 获取串长度
*
* @param pStr 指向待获取长度的串
*
* @return 返回串当前长度
*/
int StrLength( const ArrString *const pStr )
{
return pStr->len;
} /**
* @brief 将字符串 pSrc 复制到 pDest
*/
int StrCopy( ArrString *pDest, const ArrString *const pSrc )
{
int nSrcLen = strlen(pSrc->str); ///是否需要扩容
if( nSrcLen + > pDest->size )
{ //需要扩容
pDest->str = (char *)realloc( pDest->str, pSrc->size );
pDest->size = pSrc->size;
} char *dest = pDest->str;
char *src = pSrc->str; ///复制串
while( *dest++ = *src++ ); pDest->len = pSrc->len; return pDest->len;
} /**
* @brief 串连接, 将串 pSrc 连接到 pDest 后
*
* @param pDest 指向目标串
* @param pSrc 指向源串
*
* @return 返回连接后目标串的长度
*
* @note 执行串连接后 pSrc 串将被销毁
*/
int StrCat( ArrString *pDest, ArrString *pSrc )
{
///检测是否需要扩容
if( pDest->size - (pDest->len + pSrc->len) < )
{ //需要扩容
pDest->str = (char *)realloc( pDest->str, pDest->len + pSrc->len + );
pDest->size = pDest->len + pSrc->len + ;
} char *dest = &pDest->str[pDest->len];
char *src = pSrc->str; ///连接串
while( *dest++ = *src++ );
pDest->len += pSrc->len; ///销毁 pSrc
free( pSrc->str );
free( pSrc );
pSrc = NULL; return pDest->len;
} /**
* @brief 取子串
*
* @param pStr 指向源串
* @param pSub 获取得到的子串
* @param nPos 截取起始位置
* @param nLen 截取的长度
*
* @return 成功得到子串返回 TRUE, 否则返回 FALSE
*
* @note 位置由 0 计起
*/
int SubStr( ArrString *pStr, ArrString *pSub, int nPos, int nLen )
{
///子串不存在
if( nPos < || nPos + nLen > pStr->len || nPos > pStr->len - )
{
pSub->len = ;
pSub->str[] = '\0'; return FALSE;
} ///目标子串是否需要扩容
if( pSub->size - nLen < )
{ //扩容
pSub->str = realloc( pSub->str, nLen + );
pSub->size = nLen + ;
} int i = ;
for( i = ; i < nLen; ++i )
{
pSub->str[i] = pStr->str[nPos + i];
}
pSub->str[i] = '\0';
pSub->len = nLen; return TRUE;
} /**
* @brief 获取子串在目标串中第一次出现的位置
*
* @param pStr 指向目标串
* @param pSub 指向待检测的子串
* @param nPos 检测的起始位置
*
* @return 返回子串在目标串中第一次出现的位置
*
* @note 位置由 0 计起
*/
int IndexStr( const ArrString *const pStr, const ArrString *const pSub, int nPos )
{
if( nPos < || nPos > pStr->len - )
return NPOS; char *dest = &pStr->str[nPos];
char *sub = pSub->str;
int nSame = ;
int nCount = ; ///传统匹配
while( *dest )
{
++nCount; if( *sub == *dest )
{
++nSame;
++dest;
++sub;
if( nSame == pSub->len )
return nPos + nCount - pSub->len;
}
else
{
sub = pSub->str;
if( nSame == )
++dest;
else
--nCount; nSame = ;
}
} return NPOS;
} /**
* @brief 将 pSrc 插入到 pDest 的 nPos 处
*
* @param pDest 目标串
* @param pSrc 源串
* @param nPos 插入的位置
*
* @return 若成功插入, 则返回插入后目标串的长度, 否则返回 -1
*
* @note 位置由 0 计起
*/
int InsertStr( ArrString *pDest, const ArrString *const pSrc, int nPos )
{
///插入位置是否合法
if( nPos < || nPos > pDest->len - )
return -; ///是否需要扩容
if( (pDest->size - pDest->len - pSrc->len) < )
{ //需要扩容
pDest->str = (char *)realloc( pDest->str, pDest->size + pSrc->len );
pDest->size += pSrc->len;
} ///从插入位置向后移动腾出空间
int i = pDest->len + pSrc->len - ;
pDest->str[i + ] = '\0';
for( i; i > nPos; --i )
{
pDest->str[i] = pDest->str[i - pSrc->len];
} ///将待插入的串插入
for( i = ; i < pSrc->len; ++i )
{
pDest->str[nPos + i] = pSrc->str[i];
} pDest->len += pSrc->len; return pDest->len;
} /**
* @brief 擦除串 pStr 中位置 nStat 至 nEnd 间的子串
*
* @param pStr 指向待擦除子串的串
* @param nStart 起始位置
* @param nEnd 结束位置
*
* @return 成功则返回擦除后串的长度, 否则返回 -1
*
* @note 位置由 0 计起, 擦除范围为 [nStart, nEnd)
*/
int EraseStr( ArrString *pStr, int nStart, int nEnd )
{
if( nStart > nEnd || \
nStart < ||
nStart > pStr->len || \
nEnd < || \
nEnd > pStr->len \
) return -; int i = nStart, nLen = nEnd - nStart; ///执行擦除
for( i; i < pStr->len - nLen; ++i )
{
pStr->str[i] = pStr->str[i + nLen];
} ///重置 `\0` 位置
pStr->str[ pStr->len - nLen ] = '\0'; ///重置长度
pStr->len -= nLen; return pStr->len;
} /**
* @brief 将串中的一部分子串用另一串替换
*
* @param pStr 指向被替换的串
* @param pFind 待替换的串
* @param pReplace 替换的内容
*
* @return 返回替换的次数
*/
int ReplaceStr( ArrString *pStr, ArrString *pFind, ArrString *pReplace )
{
int nStart = , nEnd = , nCount = ; while( TRUE )
{
nStart = IndexStr( pStr, pFind, nEnd );
if( nStart != NPOS )
{
EraseStr( pStr, nStart, nStart + pFind->len + );
InsertStr( pStr, pReplace, nStart );
nEnd = nStart + pReplace->len + ;
++nCount; }
else break;
} return nCount;
} /**
* @brief 比较串 pStr_a 与 pStr_b 的大小
*
* @param pStr_a 目标串一
* @param pStr_b 目标串二
*
* @return 若串一大于串二则返回正数, 相等返回 0, 小于串二则返回负数
*/
int StrCompare( const ArrString *const pStr_a, const ArrString *const pStr_b )
{
char *sa = pStr_a->str;
char *sb = pStr_b->str; while( *sa && *sb )
{
if( *sa != *sb )
return *sa - *sb; ++sa;
++sb;
} if( pStr_a->len == pStr_b->len )
return ; return pStr_a->len > pStr_b->len ? : -;
} /**
* @brief 将串转换为C风格字符串
*
* @param 指向待转换的串
*
* @return 返回指向转换后C风格串的指针
*/
char *ToCString( const ArrString *const pStr )
{
return pStr->str;
} //测试 int main()
{
///测试 CreateString
ArrString *s1 = CreateString( "Hello, " );
ArrString *s2 = CreateString( "world!" ); ///测试 IsEmpty、 StrLength
if( IsEmpty( s1 ) != TRUE )
printf( "s1 length = %d, IsEmpty = %d\n\n", StrLength(s1), IsEmpty( s1 ) ); ///测试 ClearString
ClearString( s1 );
printf( "ClearString s1...\n" );
printf( "s1 length = %d, IsEmpty = %d\n\n", StrLength(s1), IsEmpty( s1 ) ); ///测试 StrCopy、ToCString
StrCopy( s1, s2 );
printf( "测试StrCopy(s1, s2), s1=%s\n\n", ToCString(s1) ); ///测试 StrCat
StrCat( s1, s2 );
printf( "测试StrCat( s1, s2 ), s1=%s\n\n", ToCString(s1) ); ///测试 SubString
ArrString *s3 = CreateString( "Hello, world!" );
ArrString *sub = CreateString( "" );
SubStr( s3, sub, , );
printf( "测试 SubStr, 源串:\"%s\", 自位置3起, 长度为6, 子串为:\"%s\"\n\n", ToCString(s3), ToCString(sub) ); ///测试 IndexStr
int nPos = IndexStr( s3, sub, );
printf( "测试 IndexStr, 源串\"%s\", 子串:\"%s\", 子串在源串的位置:%d\n\n", ToCString(s3), ToCString(sub), nPos ); ///测试 InsertStr
ArrString *src = CreateString( "AAA" );
InsertStr( s3, src, );
printf( "测试 InsertStr, 在串s3位置2处插入串\"%s\": %s\n\n", ToCString(src), ToCString(s3) ); ///测试 ReplaceStr
ArrString *plc = CreateString( "#####" );
int n = ReplaceStr( s3, src, plc );
printf( "将串s3中\"AAA\"替换为\"#####\": %s, 共替换了%d次\n\n", ToCString(s3), n ); ///测试 EraseStr
EraseStr( s3, , );
printf( "擦除串s3中位置2至7的内容:%s\n\n", ToCString(s3) ); ///测试 StrCompare
printf( "\n测试 StrCompare:\n" );
ArrString *s4 = CreateString( "Hello!" );
ArrString *s5 = CreateString( "Hi~" );
n = StrCompare( s4, s5 );
if( n > )
printf( "%s > %s\n", ToCString(s4), ToCString(s5) );
if( n < )
printf( "%s < %s\n", ToCString(s4), ToCString(s5) );
if( n == )
printf( "%s == %s\n", ToCString(s4), ToCString(s5) ); ///销毁串
DestroyString( s1 );
DestroyString( s3 );
DestroyString( s4 );
DestroyString( s5 );
DestroyString( sub );
DestroyString( plc );
DestroyString( src ); return ;
}

运行测试:

若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。                                                                                                                                                                                                                                                                                                                                                       

C语言 串 顺序结构 实现的更多相关文章

  1. C语言 队列 顺序结构 实现

    一个能够自动扩容的顺序结构的队列 ArrQueue (GCC编译). /** * @brief C语言顺序结构队列的实现 * @author wid * @date 2013-10-30 * * @n ...

  2. C语言 栈 顺序结构 实现

    一个能够自动扩容的顺序结构的栈 ArrStack 实例 (GCC编译). /** * @brief C语言实现的顺序结构类型的栈 * @author wid * @date 2013-10-29 * ...

  3. C语言之顺序结构

    该章内容:这章我们学习三大结构之一:顺序结构,它是程序从上往下顺序执行,是程序运行最简单的方式.printf和scanf函数使用和特例是必考知识.本章是考试的重点章节. 学习方法:从简单的顺序结构题目 ...

  4. (七)C语言之顺序结构

  5. Java 流程控制语句 之 顺序结构

    在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说,程序的流程对运行结果 有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过控制语句的执行顺序来实 ...

  6. C语言第二次作业-----顺序结构

    一:改错题 (1)输出指定信息: 将给定源代码输入编译器: 执行编译命令,发现编译器报错,错误信息如下: 经检查,发现源程序将"stdio.h"误拼为"stido.h&q ...

  7. C语言程序设计第二次作业--顺序结构

    C语言程序设计第二次作业--顺序结构 1.输出带框文字:在屏幕上输出以下3行信息. ************* Welcome ************* 源程序 #include <stido ...

  8. C语言第二次作业——顺序结构

    一.改错题 1.输出带框文字:在屏幕上输出以下3行信息. (1)源程序 对程序进行编译,发现错误信息1 错误原因:stdio拼写错误 改正方法:将stdio正确拼写 对程序进行编译,发现错误信息2 错 ...

  9. C语言程序设计第二次作业—————顺序结构改

    1.输出带框文字:在屏幕上输出以下3行信息. ************* Welcome ************* 源程序 #include <stido.h> int mian() { ...

随机推荐

  1. codeforces 361 A - Mike and Cellphone

    原题: Description While swimming at the beach, Mike has accidentally dropped his cellphone into the wa ...

  2. c#中获取数组的行列个数的方法

    GetUpperBound可以获取数组的最高下标.GetLowerBound可以获取数组的最低下标.这样就可以实现对数组的遍历//定义二维数组string[,] myStrArr2=new strin ...

  3. 写一个ajax程序就是如此简单

    写一个ajax程序就是如此简单 ajax介绍: 1:AJAX全称为Asynchronous JavaScript and XML(异步JavaScript和XML),指一种创建交互式网页应用的网页开发 ...

  4. 使用JNDI或JDBC连接数据库

    一. JNDI 1. tomcat环境 找到X:\xxx\......\apache-tomcat-6.0.39\conf\server.xml,在<Host>节点中配置如下: <H ...

  5. java实现smtp邮件发送

    一.准备工作 首先你需要已一个发送邮箱,一般的邮箱都有SMTP.POP3服务,比如QQ邮箱,登陆QQ邮箱开启SMTP服务,开启是服务器会提示你设置独立密码,这个密码是跟邮箱正常登陆的密码不同的,这个是 ...

  6. css小tip

    1. <input>标签的默认样式 当在页面中添加一个input标签,当点击输入框时会有一个外边框包裹着,可以使用 : input { outline: none} 去除点击时产生的外边框 ...

  7. swift 定制自己的Button样式

    swift的UIButton类中有些公开方法可以重写,所以,如果想写出自己的UIButton,只要继承UIButton类,并重写相应的方法即可. 系统的UIButton可以添加图片,也可以添加标题,但 ...

  8. sd_cms置顶新闻,背景颜色突击显示

    维护之前的一个客户网站,使用的是sd_cms系统,因为好久没有维护了,看到这网站的时候,真不敢相信,自己也曾做出过这样的网站. 客户要求置顶新闻始终在最上面,有背景颜色突击显示. 找到对应的代码,修改 ...

  9. PHP 四种基本排序算法的代码实现

    前提:分别用冒泡排序法,快速排序法,选择排序法,插入排序法将下面数组中的值按照从小到大的顺序进行排序. $arr(1,43,54,62,21,66,32,78,36,76,39); 1. 冒泡排序 思 ...

  10. poj1166学习中

    #include <iostream> #include <string.h> #include <cstdio> #include <cmath> u ...