//编译环境VS2013
strStr.h
#define _CRT_SECURE_NO_WARNINGS
//字符串封装,需要库函数
//不需要库函数,我现在完成的就是自己实现库函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct CString
{
char *p;<span style="white-space:pre"> </span>//保存字符串首地址
int realLength;<span style="white-space:pre"> </span>//实际长度
};
typedef struct CString myString; //全局变量
//主要实现的功能概述如下:
//字符串,初始化,打印,
//查找,查找字符,查找字符串
//尾部增加,(字符,字符串)
//删除(字符,字符串),
//任意位置增加(字符,字符串)
//修改字符串,(字符,字符串替换)
void initStr(myString *string); <span style="white-space:pre"> </span>//原封不动初始化
void initWithLength(myString *string, int length);<span style="white-space:pre"> </span>//开辟长度,内存清零
void initWithString(myString *string, char *copyString);//初始化,并拷贝字符串
void printStr(myString *string); //打印
void backAddChar(myString *string, char *ch);<span style="white-space:pre"> </span> //尾部插入字符
void backAddString(myString *string, char *str);<span style="white-space:pre"> </span>//尾部掺入字符串
void run(myString *string);
//以下两个查找函数 ,仅仅是找到了第一个匹配的字符,还要完成所有匹配的字符
//完成这个工作仅仅需要续断循环查找即可
char *findFirstChar(myString *string, char ch);<span style="white-space:pre"> </span>//返回第一个匹配的字符
char *findFirstString(myString *string, char str);
int deleteFirstChar(myString *string, char ch);
int deleteFirstString(myString *string, char *str);
void addChar(myString *string, char *ch, char *pos);<span style="white-space:pre"> </span> //任意位置增加字符
void addString(myString *string, char *str, char *pos);<span style="white-space:pre"> </span>//任意位置增加字符串
void changeFirstChar(myString *string, const char oldChar, const newChar);
void changeFirstString(myString *string, char * const oldString, char *const newString);
//strStr.c 主要函数文件
#include"strStr.h"
int myStrLen(char *p) //strlen()
{
if (p == NULL)
{
return -1; //失败
}
int length = 0;
while (*p != '\0')
{
length++;
p++;
}
return length;
}
//完全可以替代strcpy函数。
char *myStrcpy(char *dest, const char *source) //限制拷贝的时候修改内容
{
if (dest == NULL || source == NULL)
{
return NULL;
}
char *destback = dest;
while (*source != '\0')
{
*dest = *source; //赋值
source++;
dest++;//指针不断向前
}
*dest = '\0';
return destback;
}
char *myStrcat(char *dest, const char *source)
{
if (dest == NULL || source == NULL)
{
return NULL;
}
else
{
char *destbak = dest; //保留dest的地址
while (*dest != '\0')
{
dest++;//指针移动,直到\0
}
while (*source != '\0')
{
*dest = *source;
dest++;
source++;
}
*dest = '\0';
return destbak;
}
}
char *myStrchr(const char *dest, const char ch) //找寻一个字符
{
if (dest == NULL)
{
return NULL;
}
while (*dest != '\0')
{
if (*dest == ch)
{
return dest;//找到ch,返回地址
}
dest++;
}
return NULL; //找到最后都没有找到
}
char *myStrstr(const char * const dest, const char * const findStr)
{
if (dest == NULL || findStr == NULL)
{
return NULL;
}
char *destbak = dest;//备份dest
char *p = NULL; //保存找到的地址
while (*destbak != '\0')
{
int flag = 1;//假设相等
char *findStrbak = findStr; //备份findStr;
char *nowdestbak = destbak;
while (*findStrbak != '\0')
{
if (*nowdestbak != '\0')//判断被查找字符串是否结束
{
//有一个不相等,就不相等
if (*findStrbak != *nowdestbak)
{
flag = 0;//不相等
}
nowdestbak++;
findStrbak++;
}
else
{
flag = 0; //设置标识
break;
}
}
if (flag == 1)//找到了
{
p = destbak;//找到位置首地址
return p; //返回找到的字符串的地址。
}
destbak++;
}
return NULL; //遍历完成之后没有任何效果则返回空。
}
void initStr(myString *string) //原封不动初始化
{
string->p = NULL;
string->realLength = 0;
}
void initWithLength(myString *string, int length)//开辟长度,内存清零
{
//string->p = (char *)malloc(sizeof(char)*length);//分配内存不清零
string->p = (char *)calloc(length, sizeof(char));//分配内存并清零
string->realLength = length;
}
void initWithString(myString *string, char *copyString)//初始化,并拷贝字符串
{
int length = strlen(copyString);//获取字符串长度
string->p = (char *)calloc(length + 1, sizeof(char));
myStrcpy(string->p, copyString);//拷贝字符串
//这里不需要考虑末尾字符串为\0的问题,因为一开始就全清零了
string->realLength = length + 1; //设置字符串长度
}
void backAddChar(myString *string, char *ch) //尾部插入字符
{
//strlen()函数不会计算\0.
if (strlen(string->p) + 1 == string->realLength)//意味着满了
{
//重新分配内存
string->p = realloc(string->p, string->realLength + 1);
string->realLength += 1;
string->p[string->realLength - 2] = ch;
string->p[string->realLength - 1] = '\0';
//末尾加0 结束
}
else
{
int nowLength = myStrLen(string->p);
string->p[nowLength] = ch;
string->p[nowLength + 1] = '\0';
}
}
void backAddString(myString *string, char *str)//尾部掺入字符串
{
int nowmyStringLength = myStrLen(string->p);//获取当前长度
int addStringLength = myStrLen(str);//要增加的长度
//如果 当前长度+要增加的长度+'\0'的长度 大于 原来字符串额实际长度
if (nowmyStringLength + addStringLength + 1 > string->realLength)
{
//判断是否越界
int needAddLength = nowmyStringLength + addStringLength + 1 - (string->realLength);
//需要增加的程度等于将要加入的字符串程长度+1
string->p = (char *)realloc(string->p, string->realLength + needAddLength);
myStrcat(string->p, str);
string->realLength += needAddLength; //改变字符串实际长度
}
else
{
myStrcat(string->p, str);
}
}
void printStr(myString *string) //打印
{
printf("\n string=%s", string->p);
}
void run(myString *string)
{
system(string->p);
}
char *findFirstChar(myString *string, char ch)
{
char *p = myStrchr(string->p, ch);
return p;
}
char *findFirstString(myString *string, char *str)
{
char *pres = myStrstr(string->p, str);
return pres;
}
int deleteFirstChar(myString *string, const char ch)
{
char *p = myStrchr(string->p, ch);//查找
if (p == NULL)
{
return 0;
}
else
{
char *pnext = p + 1;
while (*pnext != '\0')
{
*p = *pnext;
p++;
pnext++;//删除的元素后面的每一个元素都前移一位
}
*p = '\0';
return 1;
//一开始我有一个问题就是,当pnext='\0'.也就是整个dest中
//只有一个字符,且这个字符刚好是要删除的字符,那么while (*pnext != '\0')
//
}
}
int deleteFirstString(myString *string, char * const str)
{
char *pres = myStrstr(string->p, str);
if (pres == NULL)
{
return 0;//删除失败
}
else
{
int length = myStrLen(str); //求字符串长度
char *pnext = pres + length; //下一个字符串
while (*pnext != '\0')
{
*pres = *pnext; //将从pres到pres+length长度之间的字符串删除
pres++;
pnext++;
}
*pres = '\0';
return 1; //删除成功
}
}
void addChar(myString *string, char *ch, char *pos) //任意位置增加字符
{
if (pos == NULL || string == NULL)
{
return;
}
if (myStrLen(string->p) + 1 == string->realLength)//意味着满了
{
//空间满了之后需要重新申请内存
string->p = (char *)realloc(string->p, string->realLength + 1);
//申请了内存之后,字符的实际长度就加1
string->realLength += 1;
//实际长度增加了之后开始移动,把要插入的位置腾出来
int nowLength = myStrLen(string->p);//求出当前总长度
int moveLength = myStrLen(pos);//要移动的长度,从插入位置pos一直到结尾
for (int i = nowLength; i > nowLength - moveLength; i--)
{
string->p[i] = string->p[i - 1];//后移一位
}
//移动完成之后,插入位置腾出来了,现在插入字符
string->p[nowLength - moveLength] = ch;//插入
//插入之后将字符处啊末尾加上'\0'
string->p[nowLength + 1] = '\0';
}
else //没有满的情况,也就是不用申请内存
{
int nowLength = myStrLen(string->p);//求出当前总长度
int moveLength = myStrLen(pos);//要移动的长度,从插入位置pos一直到结尾
for (int i = nowLength; i > nowLength - moveLength; i--)
{
string->p[i] = string->p[i - 1];//后移一位
}
//移动完成之后,插入位置腾出来了,现在插入字符
string->p[nowLength - moveLength] = ch;//插入
//插入之后将字符处啊末尾加上'\0'
string->p[nowLength + 1] = '\0';
}
}
void addString(myString *string, char *str, char *pos)//任意位置增加字符串
{
if (pos == NULL || string == NULL)
{
return;
}
int nowmyStringLength = myStrLen(string->p);//获取当前长度
int addStringLength = myStrLen(str);//要增加的长度
//如果 当前长度+要增加的长度+'\0'的长度 大于 原来字符串额实际长度
if (nowmyStringLength + addStringLength + 1 > string->realLength)
{
//判断是否越界
int needAddLength = nowmyStringLength + addStringLength + 1 - (string->realLength);
//需要增加的程度等于将要加入的字符串程长度+1
string->p = (char *)realloc(string->p, string->realLength + needAddLength);
string->realLength += needAddLength; //改变字符串实际长度
//先移动,再拷贝,这与在尾部家字符串是不同的
int nowLength = myStrLen(string->p);//求出当前总长度
int moveLength = myStrLen(pos);//要移动的长度,从插入位置pos一直到结尾
int insertLength = myStrLen(str);//求出要插入的字符串的长度
for (int i = nowLength; i >= nowLength - moveLength; i--)
{
string->p[i+insertLength] = string->p[i];//后移一位
}
//移动完成之后,插入位置腾出来了,现在插入字符
//由于插入的是字符串所以还需要一个循环
for (int j = 0; j < insertLength; j++)
{
string->p[nowLength - moveLength + j] = str[j];//插入
}
}
else//字符串没有满,也就是存储的字符串的长度小于实际长度
{
//先移动,再拷贝,这与在尾部家字符串是不同的
int nowLength = myStrLen(string->p);//求出当前总长度
int moveLength = myStrLen(pos);//要移动的长度,从插入位置pos一直到结尾
int insertLength = myStrLen(str);//求出要插入的字符串的长度
for (int i = nowLength; i > nowLength - moveLength; i--)
{
string->p[i + insertLength] = string->p[i];//后移一位
}
//移动完成之后,插入位置腾出来了,现在插入字符
//由于插入的是字符串所以还需要一个循环
for (int j = 0; j < insertLength; j++)
{
string->p[nowLength - moveLength + j] = str[j];//插入
}
}
}
void changeFirstChar(myString *string, const char oldChar, const newChar)
{
char *pstr = string->p;
while (*pstr != '\0')
{
if (*pstr == oldChar)
{
*pstr = newChar;
return; //如果要查询所有的oldChar则不需要return。
}
pstr++;
}
}
void changeFirstString(myString *string, char * const oldString, char *const newString)
{
char *pfind = findFirstString(string, oldString); //找到要修改的字符串
if (pfind != NULL)
{
deleteFirstString(string, oldString); //删除
addString(string, newString, pfind);//插入。
}
}
//main.c 测试文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "strStr.h"
void main()
{
myString string1;
//字符串初始化
initWithString(&string1, "notepad");
//backAddString(&string1, "pad");
printStr(&string1);
//查找第一个匹配的字符测试
/*char *strp = findFirstChar(&string1, 'a');
*strp = 'A';
printf("%c\n", *strp);*/
//查找第一个匹配的字符串
//char *strp = findFirstString(&string1, "ad");
//printf("%c\n", *strp);
//查找第一个匹配的字符串,找不到的情况返回空。
/*char *strp = findFirstString(&string1, "addd");
if (strp != NULL)
{
*strp = 'X';
}*/
//printStr(&string1);
删除字符测试
//deleteFirstChar(&string1, 'n');
//printStr(&string1);
删除字符串测试
//int num = deleteFirstString(&string1, "padf");
//printStr(&string1);
//if (num == 0)
//{
// printf("\n删除失败\n");
//}
//else
//{
// printf("删除成功\n");
//}
任意位置插入字符测试
首先找到要插入的位置
//char *p = findFirstChar(&string1, 't');
//if (p != NULL)
//{
// addChar(&string1, 'w', p);
//}
//printStr(&string1);
任意位置插入字符串测试
//backAddString(&string1, "notepad");
//printStr(&string1);
//char *p = findFirstChar(&string1, 't');
printf("%s", p);
//if (p != NULL)
//{
// //printf("test\n");
// addString(&string1, "12345", p);
// //printf("%s\n", string1);
//}
addString(&string1, "1345", p);
//printStr(&string1);
替换字符 测试
//changeFirstChar(&string1, 'p', 'A');
//printStr(&string1);
//替换字符串测试
//backAddString(&string1, "notepad");
//changeFirstString(&string1, "pad", "I Love C++!!");
//printStr(&string1);
//循环改变oldString
backAddString(&string1, "notepadnotepadnotepadnotepad");
printStr(&string1);
while(findFirstString(&string1, "notepad"))
{
changeFirstString(&string1, "notepad", "123456789");
}
printStr(&string1);
//run(&string1); //执行指令
system("pause");
}