2011-10-04 272 views
-3

给定一个字符串(作为函数的参数),在给定字符组合后,如果退出(它只是修改字符串),我需要删除零序列。例如,如果字符组合为x+,则字符串20.301x+000005必须转换为20.301x+5从C字符串中删除字符

我尝试这样做:

void convertStr(char *analysisBuffer) 
{ 
    char *exp; 

    if((exp = strstr(analysisBuffer,"x+"))!=NULL||(exp = strstr(analysisBuffer,"X+"))!= NULL) 
    { 
     exp += 2; 
     char * zeroIt = exp; 
     while(*zeroIt == '0') 
      ++zeroIt; 
     unsigned int x = exp - analysisBuffer; 
     analysisBuffer[x] = '\0'; 
     strcat(analysisBuffer,zeroIt); 
    } 
} 

谁能告诉我如何正确地执行呢?

+0

您是指'analysisBuffer [X] = '\ 0';'代替'analysisBuffer [0] = '\ 0';'? – tdk001

+0

重申您的要求:删除给定序列后发生的所有“0”。是否有必要修改字符串或允许复制? – pmr

+0

只修改字符串 – Yakov

回答

3

这是为表达 的多次出现的作品,并降低一个版本字符串的大小,以便内存不被占用零结束符。这可能会更慢,并且完全没有必要 但是,您可以感受到做一些奇特的事情。

声明:我很久没有写过任何纯C了。

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

char* strip_zero(char* str, const char* startseq) { 
    // while there is an occurence of the substring 
    size_t ssize = strlen(startseq); 
    size_t oldlen = strlen(str) + 1; // account for terminator 
    size_t rems = 0; 
    char* begin = str; 

    while((begin = strstr(begin, startseq))) { 
    // move to the end of the sequence 
    begin += ssize; 
    char* walk = begin; 
    // walk until we reach nonzero 
    while(*walk == '0') { ++walk; ++rems; } 
    // move the string forward 
    memmove(begin, walk, strlen(walk) + 1); 
    } 

    // realloc the string 
    return (char*)realloc(str, oldlen - rems); 
} 

int main(void) 
{ 
    // make a copy so we can modify 
    const char* a = "x+20.301x+00000x+0005x+"; 
    char* foo = (char*)malloc(strlen(a) + 1); 
    strcpy(foo, a); 
    printf("%s \n", foo); 
    foo = strip_zero(foo, "x+"); 
    printf("%s \n", foo); 
    free(foo); 
    return 0; 
} 
+0

+1这就是为什么我喜欢C,因为“做某些事情的真棒感觉”;) – BlackBear

+0

如果字符串必须在适当的位置进行修改,这并不能解决问题,我相信带重叠字符串的strcpy可能会有未定义的结果。 –

+0

@Jim谢谢,我错过了文档中的“可能不”部分。我会解决这个问题。但是我不明白你评论的第二部分。修改是就地。如果内存应该维护,你只需要跳过'realloc',一切都会好起来的。 – pmr

1

喜欢的东西

char * write = str; 
char * read = str; 
while(*read){ 
    while(*read && *read == '0'){ read++; } 
    *write++ = *read++; 
} 
*write = '\0'; 

? (这是未经测试)

2

下面是一个更完整的例子,你想要什么。我试图改进几项:

  • 使用strcasestr函数进行不区分大小写的测试。 (为此,我们需要#define _GNU_SOURCE
  • 使用strcat(与您一样)将字符串的尾部附加到头部。
  • 注意将字符串定义为char test[] = "..."而不是char *test = "...",因为后者将会出现段错误。
  • 有一个'如果'来看看我们是否必须跳过一个或多个'0'。
  • 您可以使用像rindex()这样的函数来排除while循环,该函数给出字符串中字符最右侧的索引。

#define _GNU_SOURCE 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

    void 
convertStr(char *analysisBuffer) 
{ 
    char *exp = strcasestr(analysisBuffer, "x+"); 

    if (exp) { 
     exp += 2; 
     if (*exp == '0') { 
      while (*exp == '0') { 
       *exp = '\0'; 
       exp++; 
      } 
      strcat(analysisBuffer, exp); 
     } 
    } 
} 

    int 
main(int argc, char *argv[]) 
{ 
    char test[] = "20.301X+0005"; 

    printf("before: %s\n", test); 
    convertStr(test); 
    printf("after : %s\n", test); 

    return EXIT_SUCCESS; 
} 
+0

我的C是生锈的,但不修改字符串文字UB?当然,为了观察这是函数调用者的义务,但这是你的代码所做的。 – pmr

+0

是的,如果它是一个字符串文字,但我在这里定义一个可修改的字符串数组。为了充分回答你的问题,请看下面的计算器讨论:http:// stackoverflow。com/questions/164194/why-does-simple-c-code-receive-segmentation-fault – Johan

+0

忘了说我实际编译并运行这段代码,所以我知道它的工作原理。我甚至尝试了一些不同的输入,并使用gdb来查看是否遇到奇怪的事情。 – Johan

1

相反的:

unsigned int x = exp - analysisBuffer; 
    analysisBuffer[x] = '\0'; 
    strcat(analysisBuffer,zeroIt); 

你可能只是做:

memmove(exp, zeroIt, strlen(zeroIt) + 1); 
1
size_t strip0(char *buff); 
size_t strip0(char *buff) 
{ 
size_t src,dst; 

for (src=dst=0; buff[dst] = buff[src++] ;dst++) { 
    if ((buff[dst] == 'x' || buff[dst] == 'X') && buff[src] == '+') { 
     buff[++dst] = buff[src++] ; 
     while (buff[src] == '0') src++; 
     } 
    } 
return dst; 
} 

#include <stdio.h> 

int main(int arc, char **argv) 
{ 
char data[] = "100x+003 aap 200x+300 100X+003 noot 200X+300 mies 1234xX+000000000zzz"; 

printf("Org: %s\n", data); 
strip0(data); 
printf("New: %s\n", data); 

return 0; 
}