在字符串中删除另一字符串

fcbqd85 2007-11-25 06:37:29
怎样写一个c语言函数,删除在字符串pstr1中出现的所有字符串pst2?(不能用字符串标准函数)不只有那位大哥大姐给点思路
...全文
1366 48 打赏 收藏 转发到动态 举报
写回复
用AI写文章
48 条回复
切换为时间正序
请发表友善的回复…
发表回复
heykite 2011-05-06
  • 打赏
  • 举报
回复
抱歉,上面的代码有问题,重新发下.


#include <stdio.h>

void get_input_str();
void squeeze(char s1[], char s2[]);

int main(int argc, char *argv[])
{
get_input_str();
}

void get_input_str()
{
char str1[30],str2[30];

printf("请输入str1字符串:\n");
scanf("%s",str1);
printf("请输入str2字符串:\n");
scanf("%s",str2);
squeeze(str1, str2);
}

void squeeze(char s1[], char s2[])
{
int i, j, k;

for (i = k = 0; s1[i] != '\0'; i++)
{
for (j = 0; s2[j] != '\0' && s2[j] != s1[i]; j++);
if(s2[j] == '\0')
s1[k++] = s1[i];
s1[k] = '\0';
}
printf("%s\n",s1);
}

heykite 2011-05-05
  • 打赏
  • 举报
回复


#include <stdio.h>

void get_input_str(); //接受输入.
void squeeze(char s1[], char s2[]);

int main(int argc, char *argv[])
{
get_input_str();
}

void get_input_str()
{
char str1[30],str2[30];

printf("请输入str1字符串:\n");
scanf("%s",str1);
printf("请输入str2字符串:\n");
scanf("%s",str2);
squeeze(str1, str2);
}

void squeeze(char s1[], char s2[])
{
int i, j, k;

for (i = 0; s1[i] != '\0'; i++)
{
for (j = 0; s2[j] != '\0'; j++)
{
if(s1[i] == s2[j])
{
for (k = i; s1[k] != '\0'; k++)
{
s1[k] = s1[k+1];
}
}
}
}
printf("%s",s1);
}

夹心饼干 2008-07-09
  • 打赏
  • 举报
回复
for(i=0; *(p+i)!='\0'; i++)
{
for(j=0; *(p+j)!='\0'; j++)


说明下 这里的p是p1

思路其实就是strcpy的反向加一个数组循环前移的过程
楼主可以自己看下相关的东西
夹心饼干 2008-07-09
  • 打赏
  • 举报
回复
void delstr(char *source,char *deststr)
{
char *p1 = source,*p2 = deststr;
int i,j,len = sizeof(deststr);
for(i=0; *(p+i)!='\0'; i++)
{
for(j=0; *(p+j)!='\0'; j++) //查找是否存在完全相同的字符串
{
if(*(p+i+j)==*(p2+j))
{
continue;
}else
{
break;
}
}
for(j=i; *(p+j)!='\0'; j++)
{
*(p1+j) = *(p1+j+len); // 依次使后面的元素前移,用J可以避免再次纪录I的值
}
}
}
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 w4225285 的回复:]
需要 学习中
[/Quote]
都不敢贴出来了o(∩_∩)o...
bear1985 2008-07-09
  • 打赏
  • 举报
回复
这个好像还可以
bear1985 2008-07-09
  • 打赏
  • 举报
回复
#include <stdio.h>

void delsub(char *str, char *sub)
{
char *psrc = str, *pdest = str, *psub, *p;

if((str == NULL) || (sub == NULL))
return;

while(*psrc)
{
p = psrc;
psub = sub;
while(*p && *p == *psub)
{
p++;
psub++;
}

if(*psub == 0)//找到一个子串
psrc = p;
else
*pdest++ = *psrc++;
}
*pdest = 0;

}

/*int main()
{
char str[] = "1234123ad12341234abc";
char sub[] = "1234";
cout<<"first str = "<<str<<endl;
cout<<"sub str = "<<sub<<endl;

delsub(str,sub);

cout<<"after del = "<<str<<endl;
return 0;
}*/
mu_yang 2007-11-30
  • 打赏
  • 举报
回复
值得看看
C_coding 2007-11-29
  • 打赏
  • 举报
回复
Hello loops, those compiling warnings and errors can be easily removed by placing pairs of parentheses arounding the third assignment expressions within conditional operator. Apart from this, your code are great, the logic behind works precisely.
fcbqd85 2007-11-29
  • 打赏
  • 举报
回复
很感谢各位的回复,
loops 2007-11-29
  • 打赏
  • 举报
回复
我是在vc8下编译的,没问题。刚才拿到linux下面去试试,果然有上面的错误,加了括号就没有问题了。

很奇怪,gcc下,:后面的赋值表达式必须加括号才行。难道是因为=的优先级比:小吗?

gcc和vc8都正确的版本。

/***********************************************************************
* Function : char *strrmv3(char *s1, char *s2);
* Author : loops
* Date : 2007.11.28
* Description: Remove sub string s2 from s1 without invoking any other functions.
* Maximum copy times: strlen(s1); Maximum scan times: strlen(s1)
* Assembly instructions: 49
* Comments : Compared to strrmv2, the overhead of strrmv3 comes from the calculation
: of (p-s2) along with every successful match.
***********************************************************************/
char* strrmv3( char *s1, char *s2)
{
char *w=s1, *r=s1, *p;//w: 写入位置,r: 读入位置 p: 用于处理s2
for( p=s2; *r; *w++=*r++ )
!(*p)&&(w-=(p-s2),p=s2), (*r!=*p)?(p=s2):(p+=1);
*p ? (*w='\0') : (*(w-=(p-s2))='\0');//如果*p=='\0',说明s1末尾匹配成功了。
return s1;
}

int main()
{
char str[]="abcabcdefgabcdefgabcdefgabcabcdefgabc";
printf("%s\n",strrmv3(str,"abc"));
return 0;
}

C_coding 2007-11-28
  • 打赏
  • 举报
回复
第三个版本的strrmv3,只用了5行,实现了功能
[...]
char* strrmv3( char *s1, char *s2)
{
char *w=s1, *r=s1, *p;//w: 写入位置,r: 读入位置 p: 用于处理s2
for( p=s2; *r; *w++=*r++ )
!(*p)&&(w-=(p-s2),p=s2), (*r!=*p)?p=s2:p+=1;
*p ? *w='\0' : *(w-=(p-s2))='\0';//如果*p=='\0',说明s1末尾匹配成功了。
return s1;
}
[...]



The code can't compile on gcc. The other two functions posted before this also can't compile.

main.c: In function `strrmv3':
main.c:7: warning: use of conditional expressions as lvalues is deprecated
main.c:7: error: invalid lvalue in assignment
main.c:8: warning: use of conditional expressions as lvalues is deprecated
main.c:8: warning: use of cast expressions as lvalues is deprecated
main.c:8: warning: use of compound expressions as lvalues is deprecated
main.c:8: error: invalid lvalue in assignment
main.c:7: warning: value computed is not used
loops 2007-11-28
  • 打赏
  • 举报
回复
另外个版本的strrmv2,由17楼下面的算法改进而来,汇编指令数53条,拷贝字符的次数:strlen(s1),代码长度:8行

/***********************************************************************
* Function : char *strrmv2(char *s1, const char *s2);
* Author : loops
* Date : 2007.11.28
* Description: Remove sub string s2 from s1 without invoking any other functions.
* Maximum copy times: strlen(s1); Maximum scanning characters: strlen(s1)
* Assembly instructions: 53
***********************************************************************/

char* strrmv2( char *s1, const char *s2)
{
size_t dstLen=0;
char *w=s1, *r=s1;//w: 写入位置,r: 读入位置
const char *p; //p: 用于处理s2
for( p=s2;*p; ++dstLen, ++p );//得到s2的长度
for( p=s2; *r; *w++=*r++ )
!(*p)&&(w-=dstLen,p=s2), (*r!=*p)?p=s2:p+=1;
*p ? *w='\0' : *(w-=dstLen)='\0';//如果*p=='\0',说明s1末尾匹配成功了。
return s1;
}


第三个版本的strrmv3,只用了5行,实现了功能

/***********************************************************************
* Function : char *strrmv3(char *s1, char *s2);
* Author : loops
* Date : 2007.11.28
* Description: Remove sub string s2 from s1 without invoking any other functions.
* Maximum copy times: strlen(s1); Maximum scanning characters: strlen(s1)
* Assembly instructions: 49
* Comments : Compared to strrmv2, the overhead of strrmv3 comes from the calculation
: of (p-s2) along with every successfully match.
***********************************************************************/
char* strrmv3( char *s1, char *s2)
{
char *w=s1, *r=s1, *p;//w: 写入位置,r: 读入位置 p: 用于处理s2
for( p=s2; *r; *w++=*r++ )
!(*p)&&(w-=(p-s2),p=s2), (*r!=*p)?p=s2:p+=1;
*p ? *w='\0' : *(w-=(p-s2))='\0';//如果*p=='\0',说明s1末尾匹配成功了。
return s1;
}

int main()
{
char str[]="abcabcdefgabcdefgabcdefgabcabcdefgabc";
printf("%s\n",strrmv(str,"abc"));
return 0;
}

loops 2007-11-28
  • 打赏
  • 举报
回复
不好意思,上面有个bug,修正一下。由下面的代码生成的汇编指令是71条(VC8 Release)

/***********************************************************************
* Function : char *strrmv(char *s1, const char *s2);
* Author : loops
* Date : 2007.11.28
* Description: Remove sub string s2 from s1 without invoking any other functions.
***********************************************************************/
char* strrmv( char *s1, const char *s2)
{
size_t dstLen=0;
char *w=s1, *r=s1;//w: 写入位置,r: 读入位置
const char *p; //p: 用于处理s2
for( p=s2;*p; ++dstLen, ++p );//得到s2的长度
for( p=s2; *w && *p; (*w++!=*p++) && (p=s2) );//寻找到s1中第一个匹配s2的位置
for( p=s2, r=w,w-=dstLen; *r; *w++=*r++ )
!(*p)&&(w-=dstLen,p=s2), (*r!=*p)?p=s2:p+=1;
*p ? *w='\0' : *(w-=dstLen)='\0';//如果*p=='\0',说明s1末尾匹配成功了。
return s1;
}
loops 2007-11-28
  • 打赏
  • 举报
回复
It has less lines of code than yours,
~~~~~~~~~~~
要论编译出来的汇编指令的条数的话,我的(指17楼下面的算法,一共57行汇编指令)还是比你的(33楼的算法,一共77行汇编指令)要少20个指令,呵呵。(VC8下release编译出来的结果)


如果想追求极致C的代码的短小的话,我可以改写成如下面的样子,只用了9行代码,而且其中3行还是用来定义局部变量的,变量数一共4个,跟你的一样。呵呵。
如下面所示的算法实现了 "字符拷贝次数是strlen(s1)-(s1开头到第一次出现abc为止的字符个数)"的目标。但是汇编指令数也上升成78个。

char* strrmv( char *s1, const char *s2)
{
size_t dstLen=0;
char *w=s1, *r=s1;//w: 写入位置,r: 读入位置
const char *p; //p: 用于处理s2
for( p=s2;*p; ++dstLen, ++p );//得到s2的长度
for( p=s2; *w && *p; (*w++!=*p++) && (p=s2) );//寻找到s1中第一个匹配s2的位置
for( p=s2, r=w,w-=dstLen; *r; *w++=*r++ )
!(*p)&&(w-=dstLen), (*r!=*p)?p=s2:p+=1;
*p ? *w='\0' : *(w-=dstLen)='\0';//如果*p=='\0',说明s1末尾匹配成功了。
return s1;
}
C_coding 2007-11-28
  • 打赏
  • 举报
回复
Updated


http://www.cyberspace.org/~jhl/miscc.c

/*******************************************************************************
* Function : char *strrmv(char *s1, const char *s2);
* Author : lovecreatesbeauty@gmail_Del.com [Remove _Del for email]
* Date : 2007.11.27
* Description: Remove sub string s2 from s1.
******************************************************************************/

char *strrmv(char *s1, const char *s2)
{
int i, j, w = 0, r = 0;

for (i = 0; s1[i]; i++){
for (j = 0; s2[j]; j++)
if (s1[i + j] != s2[j]) break;
if (!s2[j] && j){
if (r) for (; r != i; s1[w++] = s1[r++]) ;
else w = i;
r = i + j, i = r - 1;
}
if (r && !s1[i + 1])
for (; r <= i + 1; s1[w++] = s1[r++]) ;
}
return s1;
}
loops 2007-11-27
  • 打赏
  • 举报
回复
[code=C/C++}
for (p1 = s1; p1 = strstr(p1, s2); ){
p2 = p1 + strlen(s2);
for (p3 = p1; *p3++ = *p2++; )
;
}
[/code]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
很简洁,但是最坏情况下,字符拷贝的次数依旧比我的多。
比如abc1abc2abc3abc4 你的拷贝字符串的次数是14+10+6+2=32次,
但是某些情况下,拷贝字符的次数将少于strlen(s1)。


C_coding 2007-11-27
  • 打赏
  • 举报
回复
It has less lines of code than yours, and doesn't use a special variable for status indicating purpose like the `quit' in your code.

Both my new version and your code have this problem: if the string for search criteria contains only one null character, they fall into a forever loop. Is it acceptable :=)

I can fix it in my code with a check of string length of `s2', but it doesn't look graceful. I give up this modification at the end.
moonmonkey 2007-11-27
  • 打赏
  • 举报
回复
学习学习
C_coding 2007-11-27
  • 打赏
  • 举报
回复
> loops
> 发表于:2007-11-27 14:17:1828楼 得分:0
>
> 字符拷贝次数是 strlen(s1)-(s1开头到第一次出现abc为止的字符个数)


Hello loops, how is my new version below :)

This version doesn't call any library or user defined functions, and all have been done inside one single function.



http://www.cyberspace.org/~jhl/miscc.c

/*******************************************************************************
* Function : char *strrmv(char *s1, const char *s2);
* Author : lovecreatesbeauty@gmail_Del.com [Remove _Del for email]
* Date : 2007.11.27
* Description: Remove sub string s2 from s1.
******************************************************************************/

char *strrmv(char *s1, const char *s2)
{
int i, j, w = 0, r = 0;

for (i = 0; s1[i]; i++){
for (j = 0; s2[j]; j++)
if (s1[i + j] != s2[j])
break;
if (!s2[j]){
if (r) for (; r != i; s1[w++] = s1[r++]) ;
else w = i;
r = i + j, i = r - 1;
}
if (r && !s1[i + 1])
for (; r <= i + 1; s1[w++] = s1[r++]) ;
}
return s1;
}

加载更多回复(28)

69,368

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧