读书人

怎么去掉一个字符串中的数字?需要考虑

发布时间: 2013-09-28 10:01:20 作者: rapoo

如何去掉一个字符串中的数字?需要考虑空间和效率。
如题,有个字符串"abc123def456",如何去掉其中的数字,变成"abcdef"。
需要考虑空间和效率问题,例如字符串长度很长的情况下,另外申请数组空间上就不合适。
怎样才能高效的去掉其中的数字呢?
[解决办法]
遍历,是数字就去掉呗.如果有规律就另想办法.
[解决办法]
STL里面的replace
不到符合不
[解决办法]
从后向前,遍历字符,遇到数字就删除
[解决办法]


#include<stdio.h>
#include<stdlib.h>

#define IsNumber(a) \
(('0' <= (a)) && ((a) <= '9'))

char *delete_num(char *src)
{
char *slow;
char *fast;

if (NULL == src)
return NULL;

//找到第一个数字字符处
fast = src;
while (*fast && !IsNumber(*fast))
fast++;

slow = fast;
while (IsNumber(*fast) ? *fast++ : *slow++ = *fast++)
;

return src;
}

int main()
{
char src[] = "abcdef1g2h3i45gk6lm7n8";

printf("%s\n", delete_num(src));

system("pause");
return 0;
}

[解决办法]
在C中的话,就简单了:

char a[100] = { 0 };
sscanf( "abc123def456", "%[^0123456789]", a );
[解决办法]
分段移位
当碰到数字串时,记录下起始位置和结束位置
继续parser,找到其后面的第一个不含自符的字串的结束位置,然后进行移动,后面依次循环就行了
如aaabbb123cccddd345ggg567gghh
第一次移位
aaabbbcccddd
[解决办法]
ddd345ggg567gghh
第二次移位
aaabbbcccdddggg
[解决办法]
345ggg567gghh
...
"
[解决办法]
"表示上次的结束位置
[解决办法]
void DelDigit(char * pStr)
{
char * pTempStr;

pTempStr = pStr;
while (*pStr != NULL)
{
if ((*pStr > '9')
[解决办法]
(*pStr < '0'))
{
*pTempStr = *pStr;
pTempStr++;
}
pStr++;
}
*pTempStr = '\0';
}
没验证过,大概是这个思路,呵呵。
[解决办法]
遍历,记录第一个是数字的机制,继续遍历到第一个不是数字的地址,然后缩进,然后recursive
[解决办法]
鱼和熊掌不可兼得! 如果在不另外开辟空间的情况下, 只有原地移动字符串了! 如:

root@~ #cat delnum.c
#include <stdio.h>

int main (void) {

char str[]="sdfsdfasdf234sfsar234324234sadfq234asf23q4";
void delnum (char s[]);
printf ("%s\n",str);
delnum(str);
printf ("%s\n",str);
return 0;

}

void delnum (char s[]) {
int i,j;
for(i=0;s[i]!='\0';i++) {
if(s[i]>='0'&&s[i]<='9') {
for(j=i;s[j]!='\0';j++) {
s[j]=s[j+1];


}
i--;
}
}
}
root@~ #./delnum
sdfsdfasdf234sfsar234324234sadfq234asf23q4
sdfsdfasdfsfsarsadfqasfq
root@~ #


[解决办法]
如果有许多连续的数字这个就不好。。可以记录下数字的其实和终止的位置会比较好。。。
引用:
鱼和熊掌不可兼得! 如果在不另外开辟空间的情况下, 只有原地移动字符串了! 如:


C/C++ code
root@~ #cat delnum.c
#include <stdio.h>

int main (void) {

char str[]="sdfsdfasdf234sfsar234324234sadfq234asf23q4";
voi……

[解决办法]

//我的程序,记录位置和数字的长度
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[256]="sdds344sdhs3334dhffd2";
printf("%s\n",str);
int i=0;
int length=strlen(str);
while(str[i]!='\0')
{
//第一个位置满足
if(str[i]>='0'&&str[i]<='9')
{
int sum=1;
//记录位置和长度
while(str[i]!='\0'&&(str[i+1]>='0'&&str[i+1]<='9'))
{
i++;
sum++;
}
//不满足的时候移位
for(int j=i+1;str[j]!='\0';j++)
{
str[j-sum]=str[j];
}
//注意将最后移位设为\0
str[length-sum-1]='\0';
}
i++;
}
printf("%s\n",str);
}

[解决办法]
程序测试后有点问题,请勿采纳[
Quote=引用:]
C/C++ code
//程序测试后有点问题,请勿采纳[

//我的程序,记录位置和数字的长度
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[256]="sdds344sdhs3334dhffd2";
printf("%s\n",str);
int i=0;
int length=strlen(st……
[/Quote]
[解决办法]
还是另外申请一个数组比较好,易懂且好操作
[解决办法]
#include <stdio.h>
#include <stdlib.h>

char* function(char *str)
{
char *write,*read;

write=read=str;

while(*read!=0)
{
if( !('0'<=*read && *read<='9') )
{
*write++=*read;
}

++read;
}

*write=NULL;

return str;
}

int main()
{
char buffer[100];

while( scanf("%s",buffer)!=EOF )
{
printf("%s\n",function(buffer));
}

return 0;
}

[解决办法]
一个思路,如果连续出现数字,则做一次性移动
char *deldigit(const char s[],int len)
18 {
19 char *temp =(char *)s;
20 char *digBegin;
21 int i ,digNum,digFlag,length = len;
22 digNum =0;
23 digFlag = 0;
24 for(i = 0; *(temp + i + digNum) != '\0';i++)
25 {
26 if(isdigit(*(temp + i + digNum)) != 0)//是数字
27 {
28 digFlag = 1;
29 digNum ++;
30 i --;
31 }
32 else
33 {
34 if(digFlag == 1)//前面有digNum个数字
35 {
36 memmove(temp+i,temp+i+digNum,length-i);
37 length -= digNum;
38 digNum = 0;


39 }
40 digFlag = 0;
41 }
42 }
43 if(digFlag == 1)//处理数字在最后的情况
44 {
45 memmove(temp+i,temp+i+digNum,length-i);
46 }
47 *(temp + length)='\0';
[解决办法]

引用:
从后向前,遍历字符,遇到数字就删除


四楼的办法还可以,但是。。。
[解决办法]
楼主用16楼的办法吧……
stl里面的remove算法就是那样搞的……
[解决办法]
分成小段~然后双指针从前往后遍历
[解决办法]
#16的方法好帅。我和#20的想法接近,不过一对比#16的,太寒酸了啊。


char * ParseUnknowStr_cstrp (char * In_cstrp, char * EndOfIn_cstrp)
{
if ((NULL==In_cstrp)
[解决办法]
(NULL==EndOfIn_cstrp))
{
return NULL;
}
char * CurrentPtr_cstrp= In_cstrp;
EndOfIn_cstrp[0]= 0;
while (CurrentPtr_cstrp<EndOfIn_cstrp)
{
while (0==CurrentPtr_cstrp[0])
{
++CurrentPtr_cstrp;
}
if (CurrentPtr_cstrp<EndOfIn_cstrp)
{
int temp_i= strlen ( CurrentPtr_cstrp);
strcat ( In_cstrp, CurrentPtr_cstrp);
CurrentPtr_cstrp= CurrentPtr_cstrp+ temp_i;
}
}
return In_cstrp;
}

char * KickNumbersOut_cstrp (char * In_cstrp)
{
if ((NULL==In_cstrp)
[解决办法]
(0==In_cstrp[0]))
{
return NULL;
}
int LenOfIn= strlen ( In_cstrp);
char * End_cstrp= In_cstrp+ LenOfIn;//这儿是指向结尾的0
while (0<=LenOfIn)
{
if (('0'<=In_cstrp[LenOfIn])&&(In_cstrp[LenOfIn]<='9'))
{
In_cstrp[LenOfIn]= 0;
}
--LenOfIn;
}
return ParseUnknowStr_cstrp ( In_cstrp, End_cstrp);
}

[解决办法]
//*****************************************************************
这是我编的程序,我认为要效率的话,又不开辟空间,那可以直接数字,然后覆盖掉原数组中的内容
#include < stdio.h >
#include < string.h >

void main()
{
char str[] = "abc123def45666werfwp645werew" ;
int i , j = 0 ;
int length = strlen(str) ; //先判断字符串的长度

for( i = 0 ; i < length ; i++ )
if( ! ( str[i] >= '0' && str[i] <= '9' ) )
str[j++] = str[ i ]; //删除数字

str[j] = 0 ; //记得在字符串尾加'\0'


for( j = 0 ; j < strlen(str) ; j++ )

putchar(str[j]);
putchar('\n');
}

[解决办法]
引用:
楼主用16楼的办法吧……
stl里面的remove算法就是那样搞的……

STL的remove算法是:先找到第一个满足要删除的字符处,用以避免前面数据的多余的拷贝操作,然后才调用remove_copy
[解决办法]
16楼很大呀
[解决办法]
引用:
引用:
楼主用16楼的办法吧……
stl里面的remove算法就是那样搞的……

STL的remove算法是:先找到第一个满足要删除的字符处,用以避免前面数据的多余的拷贝操作,然后才调用remove_copy


//比如下面这种情况,将字符'1'之前的字符重新写到原地址处时没有直接跳过效率高,
//所以在copy之前先将指针定位到'1'处然后再copy效率比较高点。
char a[] = "abcdefghigklmnabcdefghigklmnabcdefghigklmnabcdefghigklmn1234567890";

如果不考虑前面多余的copy操作的话,可以这样:

#include<stdio.h>
#include<stdlib.h>

char *delete_num(char *src)
{
char *slow = src, *fast = src;

while (('0' <= *fast && *fast < '9') ? *fast++ : (*slow++ = *fast++));

return src;
}

int main()
{
char src[] = "abcdef1g2h3i45gk6lm7n8";

printf("%s\n", delete_num(src));


system("pause");
return 0;
}


[解决办法]
我觉得另辟空间比较划算
[解决办法]
如果不用内存复制,条件可以改为
if((byte)((byte)*read - '0') > 9)

[解决办法]
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s="abc123def456";
string del("0123456789");
string::size_type pos=0;
while((pos=s.find_first_of(del,pos))!=string::npos)
{
s.erase(pos,pos);
}
cout<<s<<endl;
return 0;
}

[解决办法]

#include <stdio.h>
#include <stdlib.h>

#define IsNumber(a) (('0' <= (a)) && ((a) <= '9'))

char *delete_num(char *src)
{
char *slow;
char *fast;

if(NULL == src)
return NULL;

fast = src;
while(*fast && !IsNumber(*fast))
fast++;
slow = fast;
while(*fast != '\0') {
if(IsNumber(*fast)) {
*fast++;
}
else {
*slow++ = *fast++;


}
}
*slow = '\0';
return src;
}

int main(void)
{
char src[] = "abcdeflg35454k6lm7n8";
printf("%s\n",delete_num(src));
return 0;
}



编译通过
[解决办法]
#include <stdio.h>
#include <stdlib.h>

char* remove_number(char *str);

int main()
{
char buffer[100];
while (scanf("%s", buffer) != EOF) {
printf("%s\n", remove_number(buffer));
}
return 0;
}

// 删除C风格字符串中的数字
char* remove_number(char *str)
{
char *write, *read;
write = read = str; // 三个指针指向原来的字符串
while (*read != 0) { // 当指针指向的字符不是字符串结尾

if (!('0' <= *read && *read <= '9')) { // 如果是数字
*write++ = *read; // 后一个字符填充前一个字符,这里还没有完全理解
}
++read;
}
*write = NULL; // 封闭字符串
return str; // 返回字符串指针
}

[解决办法]
30 楼的有点问题,完成的结果有问题。还是16楼的 代码清晰点

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;

char* remove_number(char *str);

int main()
{
char buffer[100]="abc123def456_abc123def456_abc123def456";
string s=(buffer);
string del("0123456789");
string::size_type pos=0;
while((pos=s.find_first_of(del,pos))!=string::npos) {
s.erase(pos,pos);
}

printf("%s\n", remove_number(buffer));
cout<<s<<endl;

return 0;
}

// 删除C风格字符串中的数字
char* remove_number(char *str)
{
char *write, *read;
write = read = str; // 三个指针指向原来的字符串
while (*read != 0) { // 当指针指向的字符不是字符串结尾

if (!('0' <= *read && *read <= '9')) { // 如果是数字
*write++ = *read; // 后一个字符填充前一个字符,这里还没有完全理解
}
++read;
}
*write = NULL; // 封闭字符串
return str; // 返回字符串指针
}





[解决办法]
#include<iostream.h>
#include<string.h>
main()
{
char s[50];
int i,j;
while(1)
{
cout<<"input a string:";
cin>>s;
i=strlen(s);j=0;
while(j<i)
{
if(s[j]>='0'&&s[j]<='9')
{
strcpy(&s[j],&s[j+1]);
i=strlen(s);
}
else j++;
}
cout<<s<<endl;

}

}
[解决办法]
用链表方便删除
[解决办法]
引用:
在C中的话,就简单了:

char a[100] = { 0 };


sscanf( "abc123def456", "%[^0123456789]", a );


%[^...]没有那么智能啊亲
[解决办法]

#include <stdio.h>
#define SIZE 10000
int main(){
char s[SIZE];
int i, j;
while(gets(s)){
for(i = j = 0; s[i]; i++){
if(s[i] >= '0' && s[i] <= '9'){//是数字
;
}else{
s[j++] = s[i];//j是指遍历到当前位置i时出现的字母个数
}
}
s[j] = 0;
printf("%s\n",s);
}
return 0;
}

[解决办法]
不开辟空间的话,只能在原数组下移动了。
可以用两个指针来做,第一个指针指到要移到的位置,第二个指针指到要移动的字符,遇到数字就只移动后一个指针而不copy到前一个位置。这样每个字符最多移动一次。
而且在第一个数字出现后,后面的字符也是至少要移动一次的。
我想不到更好的办法了……

读书人网 >C语言

热点推荐