2011-10-04 322 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; 
}