如何用C语言操作字符串,像高级语言一样灵活的操作,字符串的长度任意变呢?答案是肯定的,而且更灵活,效率更高!
下面实现strcpy与strcat函数的结合体
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MEM_ALINE 64//预留量,为了减少内存分配次数
//定义结构体,声明变量的时候必须要赋初值
//比如string str={0,0,0};
typedef struct{
size_t memlen;//内存长度
size_t strlen;//字符长度
char* str;//字符串,后面有'\0'
}string;
//本模块所有的函数在变量不用时,都需要释放内存
void str_free(string *src)
{
if(src->memlen){//如果已经申请过了内存
src->memlen=src->strlen=0;
free(src->str);
}
}
//构建字符串,sour字符串在定义string t1={0,0,0};必须要初始化成0
//因为第二次要用realloc函数分配内存了
//本函数支持strcpy_free(&t1,t1.str,3);也就是说把自边往后移3位
//函数名后面加_free表示提醒程序员不要忘了用str_free函数释放内存
void strcpy_free(string *dest,char *sour,size_t start)
{
char *src=sour;//定义新变量,用于自身复制到自身时
size_t len=strlen(src)+1;//新字符的长度
if(start>dest->strlen)start=dest->strlen;//如果传入的起始位置大于原来的长度
if(len==1){//如果src="",可以直接用desc->str[xx]=0;与dest->strlen=start;来代替
if(dest->strlen){//原来有内容
dest->str[start]=0;
dest->strlen=start;
}
}
else{
int isFree=0;//是否需要释放内存
if(dest->memlen==0){//如果第1次赋值
len+=start;//整长度加上起始位置
dest->strlen=len-1;//字符长度
dest->str=(char*)malloc(len);//分配内存
dest->memlen=len;//内存长度
strcpy(&dest->str[start],src);//复制字符串
}
else{
if(src>=dest->str && src<=dest->str+start){//内存地址有重叠,可能是自身复制到自身
src=(char*)malloc(len);//分配原来的长度
strcpy(src,sour);//先把原来的数据复制到临时变量中
isFree=1;//需要释放临时分配的内存
}
len+=start;//整长度加上起始位置
dest->strlen=len-1;//字符长度
if(dest->memlen<len){//内存扩容
len+=MEM_ALINE;//多分配预留量
dest->memlen=len;//内存长度
dest->str=(char*)realloc(dest->str,len);//扩容内存
}
strcpy(&dest->str[start],src);//复制字符串
}
if(len+(MEM_ALINE<<1)<=dest->memlen){//如果新内存空间,比原来小2倍预留量
dest->memlen=len+MEM_ALINE;//为了节省了内存空间,保留预留量后释放多余内存
dest->str=(char*)realloc(dest->str,dest->memlen);
}
if(isFree)free(src);//释放临时分配的内存
}
}
int main(int argc,char*argv[])
{
string t1={0,0,0};
//1.连接两个字符串
strcpy_free(&t1,"Hello! My Good ",0);
printf("%s\n",t1.str);
strcpy_free(&t1,"Friends.~~",t1.strlen);
printf("%s\n",t1.str);
strcpy_free(&t1,t1.str,7);
printf("%s\n",t1.str);
strcpy_free(&t1,"abcd",1);
printf("%s\n",t1.str);
str_free(&t1);//释放内存
}
程序运行的结果