天天看点

字符串替换C语言数据结构(长度不定)

字符串替换C语言数据结构(长度不定)
字符串替换C语言数据结构(长度不定)
字符串替换C语言数据结构(长度不定)
字符串替换C语言数据结构(长度不定)
字符串替换C语言数据结构(长度不定)

我不说这个程序为什么字符串替换还要写这么多代码

总之在输入过程中遇到的 问题我能想到的都解决了

程序的健壮性还是有的 。

字符串替换C语言数据结构(长度不定)

我个人觉得gainchar函数是这个小程序健壮性的重要体现 末尾还有个英语单词匹配的代码

//查昊昊
# include <stdio.h>    
# include <stdlib.h>    
# define N 1500   //如果想录入x个字节那么就把N的数值改成x   
# define MAX 14000  //当新字符串的个数已经不在 [MIN,MAX]时 此时不再复制字符串  
# define MIN 2    
int gainint(int *p,int a,int b);//返回数字*p    
int gainchar(char *a,int min,int max);//返回字符串长度    
int BF(char a[],char b[],int *c);//字符串匹配 BF算法 a为主串,b为被检验的串  
void shifang(int *p,char *q);//释放int char指针    
int main(){    
    int domain[2][3]={{MIN,0,0},{N,N,N}},length[5]={0,-1,-1,0,-1},i,j,k,n;//domain为各个字符串范围,length[0-4]分别储存0主字符串长度,1被替换的字符串长度,2替换的字符串长度,3匹配的个数,4新字符串长度    
    char wen[3][23]={"请输入一段字符串","字符串中要替换的字符串","将要替换的字符替换为"};//显示的界面    
    char *p[4]={NULL,NULL,NULL,NULL};//p[i]将用于指向各字符串    
    char spead[2][3]={"原","新"};    
    int *biao,choice;                 //biao[]数组储存字符匹配的下标    
    p[0]=(char *)calloc(N+1,sizeof(char));    
    do{    
        for(i=0;i<3;i++)    //有三次输入,就是输入wen[][]数组里的问题的选择    
        {    
            if(length[i]<domain[0][i]||length[i]>domain[1][i])//当字符串长度不满足条件时重新输入    
            {    
                printf("%s:[字节(%d--%d)]\n",wen[i],domain[0][i],domain[1][i]);//提示输入范围    
                length[i]=gainchar(p[i],domain[0][i],domain[1][i]);    
            }    
            if(!i)//输入原字符串ok时动态申请内存    
            {    
                p[1]=(char *)calloc(length[0]+1,sizeof(char));//因为字符数组的最后一位系统总是标识'\0',所以要多申请一个内存    
                p[2]=(char *)calloc(length[0]+1,sizeof(char));    
                domain[1][1]=domain[1][2]=length[0];//将后来的字符串输入范围改变    
            }    
            if(i==1)    
            {    
                if(!length[1])   //如果用户输入的是'\n'则将第一位变为\n长度变为1    
                {    
                    length[1]=1;    
                    printf("你输入的为回车符:\n");    
                    p[1][0]='\n';    
                }    
                biao=(int *)calloc(length[0]/length[1],sizeof(int));//输入旧的字符串完毕时申请biao内存,存储匹配下标    
                length[3]=BF(p[0],p[1],biao);//p[0]为主串,p[1]为被检验的串,biao[]存匹配的下标,length[3]存匹配的个数    
                if(!length[3])    //如果没有匹配的就重新输入旧字符串    
                {    
                    printf("字符串中没有此字符串,请重新输入");    
                    i=0;length[1]=-1;   //因为要执行i++,所以i=0    
                }    
            }    
            if(!length[2])         //如果length[2]即替换的字符串长度为0    
            {    
                printf("删除要替换的字符串请按0,用回车符代替请按1:\n");   // 如果想删除选中的字符串替换时直接回车有选择 
                p[2][1-gainint(&length[2],0,1)]='\n';  
            }    
            if(i==2&&length[1]==length[2]&&BF(p[1],p[2],biao))//原字符串与旧字符串 相同时重新输入p[2]    
            {    
                printf("替换的字符串与被替换的字符串相同,");    
                length[2]=-1;i=1;    
            }    
        }    
        length[4]=length[0]+(length[2]-length[1])*length[3];//计算新字符串长度    
        if(length[4]>=MIN&&length[4]<=MAX)    
            p[3]=(char *)calloc(length[4]+1,sizeof(char));//申请新字符串的内存    
        system("cls");    //清除屏幕     
        printf("替换的下标:\n");    
        for(i=0;i<length[3];i++)//每15个一行打印输出    
            printf("%-3d%c",biao[i]+1,(i+1)%15?' ':'\n');  
        printf("\n原字符串:\n%s\n新字符串:\n",p[0]);    
        for(i=j=n=0;i<length[0];i++,n++)//一边打印新字符串,一边复制字符串到p[3]里    
            if(i==biao[j])   //当i到达匹配的下标    
            {    
                printf("%s",p[2]);  //输出p[2]    
                if(length[4]>=MIN&&length[4]<=MAX)    //如果新字符串满足长度∈[MIN,MAX] 则复制
                    for(k=0;k<length[2];k++)    
                        p[3][n+k]=p[2][k];  //将p[2]存到p[3]里    
                    n+=length[2]-1;   //增加长度    
                    i+=length[1]-1;   //增加长度    
                    j++;   //匹配一个后biao[j]变为biao[j+1]    
            }    
            else    
            {    
                printf("%c",p[0][i]);   //如果没到下标就输出原字符串的字符    
                if(length[4]>=MIN&&length[4]<=MAX)    
                    p[3][n]=p[0][i];         //将不匹配的复制到p[3]中    
            }    
            printf("\n原字符串长度:%-3d新字符串长度:%-3d 替换的个数:%-3d",length[0],length[4],length[3]);   
            do{    
                printf("\n0:重新输入字符串并替换\n1:在原字符基础上重新替换\n2:对替换后的字符串执行新一轮替换\n3:释放指针+安全退出  输入你的选择(0--3):\n");     
                if(!gainint(&choice,0,3))   
                {  
                    length[0]=0;    //重新开始要让length[0]改为0   
                    domain[1][0]=N;  
                }  
                else if(choice==2)    
                {                              //当用户选择新字符串时让p[0]指向新字符串    
                    p[0]=length[4]<MIN?p[0]:p[3];//当新字符串个数为2个以下时提示用户并重新选择    
                    if(length[4]<MIN||length[4]>MAX)    
                        printf("新字符串字节已经不在[%d,%d]范围内!\n",MIN,MAX);    
                    else    
                    {    
                        shifang(NULL,p[0]); //就释放p[0]    
                        length[0]=length[4];//将length[0]改为新字符串的长度    
                        domain[1][0]=length[0]>N?length[0]:N;//如果新的字符串高于250则将范围改为新字符串的长度    
                    }    
                }    
            }while((length[4]>MAX||length[4]<MIN)&&choice==2);//当新字符个数为<2并且用户输入了第二个选择    
            printf("%s",choice==1||choice==2?spead[choice-1]:"\0");  //输出"新"或"旧"    
            length[1]=length[2]=-1;  //将其初始化    
            shifang(biao,p[2]);  //释放申请的内存    
            shifang(NULL,p[1]);  //释放申请的内存    
        shifang(NULL,choice<2?p[3]:NULL);  //如果用户输入的选择是前两个,则p[3]就没用了,也要释放    
    }while(choice<3);    
    shifang(NULL,p[0]);
	return 0;  
}   
int gainint(int *p,int a,int b)//输入int *p直至满足[a,b]输入结束,返回*p    
{     
    do{    
        *p=a-1;  
        scanf("%d",p);    
        while(getchar()!='\n');    
        if(*p>b||*p<a)    
            printf("输入有误,请重新输入(%d--%d):\n",a,b);    
    }while(*p>b||*p<a);    
    return *p;    
}    
int gainchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度  
{  
    int B,C;//B保存A的长度 C记录缓冲区的字符串  
    do{  
        B=-1;  C=0; //每次用户输入错误而循环时 都要初始化  
        fgets(A,max+1,stdin);//从键盘录入字符  
        while(A[++B]);  //求A的字符串长度  
        if(A[B-1]!='\n') while(getchar()!='\n') C++;    //如果缓冲区里读入的不是\n则记录字符串数量  
        else  A[--B]='\0'; //☆  去掉\n 并且字符串长度-1  
        if(C||B&&B<min) //如果缓冲区有字符串或者长度不够 则提示错误   但如果用户只输入回车而且min!=0则不提示错误 但还要输入当前字符串    
        printf("您输入的字符串长度:%d字节\n请重新输入!\n注:只输入(%d--%d)个字节!\n",B+C,min,max);  
    }while(C||B<min);  
    return B;//返回B 即:A字符串的长度  
}   
int BF(char a[],char b[],int *c)//BF算法 一般o(strlen(A)+strlen(B))  最坏o(strlen(A)*strlen(B))  
{                       
    int i=0,j=0,k=0;   
    do{  
        if (b[j]&&a[i++]==b[j]) // 继续比较后继字  
            ++j;  
        else  
        {  
            b[j]?(i-=j):(c[k++]=i-j);  
            j=0;      //无论b字符串是否结束因为(b[j]&&a[i++]==b[j])已经不满足 所以j要回到初位置  
        }  
    }while(a[i-1]);  
    return k;  
}   
void shifang(int *p,char *q)    
{    
    if(!p)  free(p);    
    if(!q)  free(q);    
    p=NULL; q=NULL;    
}
           

也可以把gainchar改成这个 一样的

int gainchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度    
{    
    int B,C;  
 do{    
        A[max]=B=C=0;
		while((A[B++]=getchar())!='\n'&&B<max);
        if(A[B-1]!='\n')
			while(getchar()!='\n'&&++C);    
	else A[--B]=0; 
	if(C||B&&B<min)
	   printf("您录入的字符串长度:%d字节\n只录入(%d--%d)个字节!\n",B+C,min,max);    
    }while(C||B<min);    
    return B;  
} 
           

三个经常用的字符串匹配函数

int BF(char a[],char b[])//BF算法 a为主串,b为被检验的串`返回b在a中的第一个下标 若无返回0  
{                       
int i=0,j=0;   
 while (a[i]&&b[j])  
 if (a[i++]==b[j]) ++j;   // 继续比较后继字  
else  {  
    i-=j;         
    j=0;  
    }  
return b[j]?0:i-j+1;  
} 
2:字符串全匹配://a主串 b次串  C[0]存储匹配的个数 c[1],c[2]……存储匹配的数组下标
void BF(char a[],char b[],int *c){                     
	int i=0,j=0,k=0; 
    do{
		if (b[j]&&a[i++]==b[j]) 
			++j;
		else
		{
			b[j]?(i-=j):(c[++k]=i-j); 
			j=0;     		
        }
	}while(a[i-1]);
		c[0]=k;
}   
对上面稍微一改://返回b在a中的个数
int BF(char a[],char b[]){                     
	int i=0,j=0,k=0; 
    do{
		if (b[j]&&a[i++]==b[j]) 
			++j;
		else
		{
			b[j]?(i-=j):k++; 
			j=0;     		
        }
	}while(a[i-1]);
		return k;
} 
           

还有就是 原字符串为英语句子 子字符串是一个单词 查找出原字符串中有多少个完整的单词 这个完整是指的 子字符串在原字符串中为一个完整的单词 : 代码C:

# include <stdio.h>
# define N 101
# define At(t)  (t<'a'||t>'z')&&(t<'A'||t>'Z')&&t!='-'
int CMP(char a,char b){//可以通过改变这个来改变是否忽略大小写
   return  a==b||b==a+32||a==b+32;
}
void BF(char a[],char b[],int c[]){//匹配 a中b单词完整的个数  c[0]存储匹配的个数 c[1],c[2]……存储匹配的单词的 下标 使用方法和群里的 字符串匹配下标相同
    int i=0,j=0,k=0;
    do{
        if (b[j]&&CMP(a[i++],b[j]))++j;//若a[i]与b[j]相等或是大小写关系 继续比较
        else{
           if(!b[j])
           {//如果b字符串到头了 此时需要检查 b在a字符串是否为完整的单词
            if((i!=j)&&At(a[i-j-1])||(i==j))//i==j时 b在a字符串的串首  如果不在串首,则i!=j 此时应检查a[i-j-1]
            if(!a[i]||a[i]&&At(a[i]))//如果b在a字符串的串尾 则a[i]==0  如果不在末尾 则检验 a[i]
            c[++k]=i-j;//存储当前匹配的单词位置
           }
           else i-=j;
            j=0;
        }
    }while(a[i-1]);
        c[0]=k;
}
int main(){
   char A[N]={"HOMEWORK:I am doing My-homework.your homework!Homework?oh"},B[N]={"Homework"};
   int C[N],i;
   BF(A,B,C);
   puts(A);
   puts(B);
   printf("B字符串在A中个共 %d个 <忽略大小写>\n匹配的数组下标:\n",C[0]);
   if(C[0])
   for(i=1;i<=C[0];i++)
     printf("%d ",C[i]);
    printf("\n");
   return 0;
}
           

继续阅读