首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

怎么去掉一个字符串中的数字?需要考虑空间和效率

2013-09-28 
如何去掉一个字符串中的数字?需要考虑空间和效率。如题,有个字符串abc123def456,如何去掉其中的数字,变成

如何去掉一个字符串中的数字?需要考虑空间和效率。
如题,有个字符串"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到前一个位置。这样每个字符最多移动一次。
而且在第一个数字出现后,后面的字符也是至少要移动一次的。
我想不到更好的办法了……

热点排行