- myString.c,常用函数的实现
- 头文件定义请参考:https://www.cnblogs.com/kxwslmsps/p/16949213.html
-
#include"myString.h" /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:初始化字符数组 \n * @retval ERROR(0):pstr不存在,不可操作 * @retval OK(1):初始化成功成功 */ status xxx_init(myString* pstr) { if (pstr == NULL) { return ERROR; } pstr->pch = NULL; pstr->capacity = 0; pstr->size = 0; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:判空 \n * @retval ERROR(0):字符串不存在,不可操作 * @retval FALSE(0):字符串非空 * @retval TRUE(1):字符串为空 */ status xxx_empty(myString* pstr) { if (pstr == NULL) { return ERROR; } return pstr->size == 0 ? TRUE : FALSE; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:求堆上字符串字符长度,不包括结束标志杠0 \n * @return 返回字长串长度 * @retval -1:字符串不存在,不可求长度 * @retval 非负整数:字符串长度 */ int xxx_strlen(myString* pstr) { if (pstr == NULL) { return -1; } return pstr->size; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:清空堆上字符串 \n * @retval ERROR(0):字符串不存在,不可操作 * @retval OK(1):清空成功,串空间及串容量不变,只是串长度变为0 */ status xxx_clear(myString* pstr) { if (pstr == NULL) { return ERROR; } pstr->size = 0; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:清空 \n * @retval ERROR(0):字符串不存在,不可操作 * @retval OK(1):清空成功 */ status xxx_destroy(myString* pstr) { if (pstr == NULL) { return ERROR; } if (pstr->pch != NULL) { free(pstr->pch); pstr->pch = NULL; } pstr->capacity = 0; pstr->size = 0; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:打印字符数组 \n */ void xxx_output(myString* pstr) { if (pstr == NULL || pstr->pch == NULL) { return; } int i = 0; printf("capacity=%d,size=%d,mystr=", pstr->capacity, pstr->size); while (i < pstr->size) { printf("%c", pstr->pch[i]); ++i; } if (pstr->pch == NULL) { printf("已被销毁\n"); } else if (pstr->size == 0) { printf("已被清空\n"); } else { printf("\n"); } } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:将字符串src字符赋值给堆上字符串pstr \n * @param[in] pstr:目的字符串 * @param[in] src:源字符串。当src为空时,pstr将被置空 * @retval ERROR(0):字符串不存在,不可操作 * @retval OVERFLOW(-2):赋值失败,pstr无法容纳src,且开辟新空间失败 * @retval OK(1):赋值成功。当源串为空时,目的串被置空,但目的串堆上空间不变 */ status xxx_assign(myString* pstr, const char* src) { if (pstr == NULL || src == NULL) { return ERROR; } // 若src为空串,将pstr置空 int size = strlen(src); if (size == 0) { pstr->size = 0; return OK; } // 若目的串的空间不足以容纳源串所有字符,则新开辟空间 if (pstr->capacity < size) { char* pch = (char*)realloc(pstr->pch, sizeof(char) * size); if (pch == NULL) { return OVERFLOW; } // 更新pstr信息 pstr->pch = pch; pstr->capacity = size; } // 将源串字符拷贝到目的串 int i = 0; while (i < size) { pstr->pch[i] = src[i]; ++i; } pstr->size = size; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:拷贝堆上字符串\n * @param[in] pstr1:目地字符串 * @param[in] pstr2:源字符串。当pstr2为空串时,结果是将pstr1置空 * @retval ERROR(0):字符串不存在,不可操作 * @retval OVERFLOW(-2):拷贝失败:pstr1无法容纳pstr2,且开辟新空间失败 * @retval OK(1):拷贝成功 */ status xxx_copy(myString* pstr1, const myString* pstr2) { if (pstr1 == NULL || pstr2 == NULL) { return ERROR; } // 源串为空时,目的串置空 if (pstr2->size == 0) { pstr1->size = 0; return OK; } // 若目的串的空间不足以容纳源串所有字符,则新开辟空间 if (pstr1->capacity < pstr2->size) { char* pch = (char*)realloc(pstr1->pch, sizeof(char) * pstr2->size); if (pch == NULL) { return OVERFLOW; } // 更新pstr信息 pstr1->pch = pch; pstr1->capacity = pstr2->size; } // 拷贝源串字符串到新建空间 int i = 0; while (i < pstr2->size) { pstr1->pch[i] = pstr2->pch[i]; ++i; } pstr1->size = pstr2->size; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:比较2个堆字符串大小 \n * @parm[in] pstr1:待比较字符串 * @parm[in] pstr2:待比较字符串 * @retval 1:pstr1>pstr2 * @retval -1:pstr2<pstr2 * @retval 0:pstr1==pstr2 */ int xxx_compare(const myString* pstr1, const myString* pstr2) { assert(pstr1 != NULL && pstr2 != NULL); int s1 = pstr1->size; int s2 = pstr2->size; // i作遍历指针,min记录2串较短者长度 int i = 0; int min = s1 <s2 ? s1 : s2; // 逐个比较2串字符,若相等且未比较完前min个字符,继续比较后继字符 // 若不相等,或已比较完前min个字符,则跳出循环 while (i < min && pstr1->pch[i] == pstr2->pch[i]) { ++i; } // 说明前min个字符比较完且前min个字符相等,只须比较2串长度即可 if (i == min) { return s1 == s2 ? 0 : (s1 > s2 ? 1 : -1); } // 否则i<min则说明pstr1->[i]!=pstr2->pch[i]必成立,只需比较当前字符大小即可 return pstr1->pch[i] > pstr1->pch[i] ? 1 : -1; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:拼接2个字符数组后将结果存放于pstr \n * @param[in] pstr1:待拼接字符串1 * @param[in] pstr2:待拼接字符串2 * @param[out] pstr:存放拼接结果 * @retval ERROR(0):字符串不存在,不可操作 * @retval OVERFLOW(-2):拼接失败:结果串空间不足,且开辟新空间失败 * @retval OK(1):拼接成功:包括2源串均为空时,结果串被置空 */ status xxx_concat(myString* pstr, const myString* pstr1, const myString* pstr2) { if (pstr == NULL || pstr1 == NULL || pstr2 == NULL) { return ERROR; } // 2源串都为空时,结果串置空 if (pstr1->size == 0 && pstr2->size == 0) { pstr->size = 0; return OK; } int s1 = pstr1->size; // pstr1长度 int s2 = pstr2->size; // pstr2长度 // 开辟堆上新空间,用来存放2串的字符 if (pstr->capacity < s1 + s2) { char* pch = (char*)realloc(pstr->pch, sizeof(char) * (s1 + s2)); if (pch == NULL) { return OVERFLOW; } // 更新pstr信息 pstr->pch = pch; pstr->capacity = s1 + s2; } // 拷贝pstr1到目的串[0,s1-1]空间上 int i = 0; while (i < s1) { pstr->pch[i] = pstr1->pch[i]; ++i; } // 拷贝pstr2到目的串[s1,s1+s2-1]空间上 int j = 0; while (j < s2) { pstr->pch[i+j] = pstr2->pch[j]; ++j; } pstr->size = s1 + s2; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:从母串上截取n个连续字符存放于子串 \n * @param[in] pstr:母串 * @param[out] psub:子串:截取母串连续n个字符后存放于子串 * @param[in] index:截取字符的开始下标,取值为[0,pstr->size-1] * @param[in] n:n范围[0,size-index],当n>size-index时,n取size-index * @retval ERROR(0):字符串不存在,不可操作 * @retval FALSE(0):操作失败:母串为空,且要求在空串截取若干个字符导致失败 * @retval ERR_PARA(-1):index或n参数不符合要求 * @retval OVERFLOW(-2):开辟空间失败,内存溢出,操作失败 * @retval OK(1):操作成功,包括在母串首字符位置截取0个字符,视为操作成功 */ status xxx_subStr(myString* pstr, myString* psub, int index, int n) { if (pstr == NULL || psub == NULL) { return ERROR; } if (pstr ->size == 0) { // 母串为空,但在空串上截取0个字符,视为求子串成功 if (index == 0 && n == 0) { return OK; } return FALSE; } int size = pstr->size; // 母串长度 // 下标index不符合,或截取字符个数n不符合 if (index<0 || index>size - 1 || n<0) { return ERR_PARA; } // 当待截取个数>可截取个数时,则只截取要截取个数 if (n > size - index) { n = size - index; } // 若psub空间不足以容纳n个字符,则新开n个字符空间 if (psub->capacity < n) { char* pch = (char*)realloc(psub->pch, sizeof(char) * n); if (pch == NULL) { return OVERFLOW; } // 更新pstr信息 psub->pch = pch; psub->capacity = n; } // 从母串index处开始拷贝n个字符到psub int i = 0; while (i < n) { psub->pch[i] = pstr->pch[index + i]; ++i; } psub->size = n; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:在串1插入串2 \n * @param[in] pstr1:串1为被插串 * @param[in] pstr2:串2为待插串 * @param[in] index:串2插入在串1下标index处,index范围[0,pstr->size-1] * @param[in] n:截取的字符数n,取值为[0,pstr->size] * @retval ERROR(0):字符串不存在,不可操作 * @retval ERR_PARA(-1):插入失败:插入下标index不合理 * @retval OVERFLOW(-2):插入失败:串1空间不足,且开辟新空间失败 * @retval OK(1):插入成功:包括在串1插入空串,亦视为插入成功 */ status xxx_insert(myString* pstr1, myString* pstr2, int index) { if (pstr1 == NULL || pstr2 == NULL) { return ERROR; } // 若待插字串为空,不做操作,视为插入成功 if (pstr2->size == 0) { return OK; } if (index<0 || index> pstr1->size) // 插入位置不合理 { return ERR_PARA; } int s1 = pstr1->size; int s2 = pstr2->size; if (pstr1->capacity < s1+s2 ) { char* pch = (char*)realloc(pstr1->pch, sizeof(char) * (s1 + s2)); if (pch == NULL) { return OVERFLOW; } pstr1->pch = pch; pstr1->capacity = pstr1->size + pstr2->size; } // 将串1[index,s1]区域内字符全部依次往后挪s2个位置 int i = s1 - 1; while (i >= index) { pstr1->pch[i + s2] = pstr1->pch[i]; --i; } // 将串的pstr2->size个元素依次拷贝到串1区域[index,index+s2]中 int j = 0; while (j < pstr2->size) { pstr1->pch[index + j] = pstr2->pch[j]; ++j; } pstr1->size += pstr2->size; return OK; } /**********************************************************************/ /**********************************************************************/ /** * @brief 功能:删除字符数组给定下标处连续n个元素 \n * @param[in] pstr:待删串 * @param[in] index:在index处开始删除,index取值[0,size-1] * @param[in] n:待删字符个数,n取值[0,size-index] * @retval ERROR(0):字符串不存在,不可操作 * @retval ERR_PARA(-1):pstr为空,或index,n参数不合理,操作失败 * @retval OK(1):操作成功 */ status xxx_remove(myString* pstr, int index, int n) { if (pstr == NULL) { return ERROR; } int size = pstr->size; // index不在[0,size]范围内,或n<1,无须删除。且包含了pstr为空的情况 if (index<0 || index>size - 1 || n < 0) { return ERR_PARA; } // x=size-index表示在index处及之后有x个字符可删除,而n为待删字符个数 // if(待删除字符个数>=可删除字符个数),则将x个字符全删除即可 // 故 while(n>x) 即 while(n>size-index),即while(index<size-n) // 此为需要移动后继字符覆盖前边字符的前提条件,否则直接令pstr[index]='\0' // 设下标j=index;则要求j<size-n int j = index; while (j<size-n) { pstr->pch[j] = pstr->pch[j + n]; ++j; } // 若待删字符数n>可删字符数size-index,则将index及之后字符全删,剩 index个 // 否则只删n个字符,剩(size-n)个 pstr->size = n > size - index ? index : size - n; return OK; }