2009-09-29 173 views
1

内的多个替代可以说我有一个字符串:C字符串字符串

"(aaa and bbb or (aaa or aaa or bbb))" 

**为了简单起见,这将永远是字符串的格式,总是3 A的后面有一个空格或“ )'或3b的后面跟一个空格或')'。

这将是与“1”和everyoccurrence的“BBB”与“0” C.取代“AAA”的每一次出现结束字符串应该像最好的办法:

"(1 and 0 or (1 or 1 or 0))" 

编辑让我更具体:

char* blah = (char *) malloc (8); 
sprintf(blah, "%s", "aaa bbb"); 

blah = replace(blah); 

我怎么能写替代,使其分配空间和存储新的字符串

"1 0" 
+0

您是否有兴趣在一个通用的解决方案,与DEST,其中src和dest中可以有不同的长度SRC替换所有出现的? – Ashwin 2009-09-29 21:48:40

+0

是的,长度无关紧要。 – user105033 2009-09-29 21:51:55

回答

4

最有效的方法是使用POSIX的正则表达式系列。一些实现将为这些模式构建适当的自动机。另一种方法是反复使用KMP或Boyer-Moore搜索,但必须多次扫描字符串,效率较低。另外,你想要什么结果给出这样的输入:aa = 1,ab = 2,bb = 3在字符串“aabb”上?

顺便说一下,当你实现这个功能时,更简洁的解决方案是分配一个新的动态C字符串,而不是在替换时修改原始字符串。您可以实施就地更换,但这会更复杂。

regex_t r; regmatch_t match[2]; int last = 0; 
regcomp(&r, "(aaa|bbb)", REG_EXTENDED); 
insert(hashtable, "aaa", "0"); insert(hashtable, "bbb", "1"); 
while (regexec(&r, oristr, 1, match, 0) != REG_NOMATCH) { 
    char *val; 
    strncat(newstr, oristr + last, match->rm_so); 
    lookup(hashtable, oristr + match->rm_so, match->rm_eo - match->rm_so, &val); 
    last = match->rm_eo; 
    strncat(newstr, val); 
} 
strcat(newstr, oristr + last); 
oristr = realloc(oristr, strlen(newstr)); 
strcpy(oristr, newstr); free(newstr); regfree(&r); 

在实际实现中,应该动态改变newstr的大小。你应该记录newstr的结束,而不是使用strcat/strlen。源代码可能是越野车,因为我没有真正尝试过。但是这个想法就在那里。这是我能想到的最有效的实现。

+0

好的,我编辑过?使其分配新的空间。不确定你输入的含义:aa = 1,ab = 2,bb = 3。 – user105033 2009-09-29 22:57:51

+0

我的意思是用1代替aa,用2代替ab,用3代替bb。你可以得到“13”或“a2b”。 – user172818 2009-09-29 22:59:30

+1

+1用于解决重叠的字符串大小写 – Ashwin 2009-09-29 22:59:36

1

对于这个特定的情况,一个简单的while/for循环可以做到这一点。但它看起来像一个家庭作业问题,所以我不会为你明确写出它。如果需要更多的通用字符串操作,我会使用pcre。

+0

使用PCRE的+1。 – user172818 2009-09-29 23:28:36

-3

您可以使用函数std::findstd::replace为每个替换尝试循环。 你会发现更多关于std :: string here的信息。

+0

这是一个C问题,而不是C++。 – GManNickG 2009-09-29 22:01:01

+0

Oki,我读得快... – 2009-09-29 22:45:58

+0

没关系,我们都这么做。 – GManNickG 2009-09-29 22:50:20

0

这绝不是世界上最优雅的解决方案,它也假定结尾字符串总是比原始字体小,哦,我对转换进行了硬编码,但希望它能指出您或多或少在正确的方向或者给你一个想法,从跳下:

char* replace(char *string) { 
    char *aaa = NULL; 
    char *bbb = NULL; 
    char *buffer = malloc(strlen(string)); 
    int length = 0; 
    aaa = strstr(string, "aaa"); 
    bbb = strstr(string, "bbb"); 
    while (aaa || bbb) { 
     if (aaa && (bbb || aaa < bbb)) { 
      char startToHere = aaa - string; 
      strncpy(buffer, string, startToHere); 
      string += startToHere; 
      length += startToHere; 
      buffer[length] = '1'; 
     } 
     else if (bbb) { 
      char startToHere = aaa - string; 
      strncpy(buffer, string, startToHere); 
      string += startToHere; 
      length += startTohere; 
      buffer[length] = '0'; 
     } 
     aaa = strstr(string, "aaa"); 
     bbb = strstr(string, "bbb"); 
    } 
    buffer[length] = '\0'; 
    string = realloc(string, length); 
    strcpy(string, buffer); 
    free(buffer); 

    return string; 
} 

声明,我甚至没有对此进行测试,但它应该是在你想要的方向上至少半。

0

这是FSM的工作!

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

/* 
//  | 0   | 1    | 2    | 3    | 4    | 
// ----+------------+---------------+----------------+---------------+----------------+ 
// 'a' | 1   | 2    | ('1') 0  | ('b') 1  | ('bb') 1  | 
// 'b' | 3   | ('a') 3  | ('aa') 3  | 4    | ('0') 0  | 
// NUL | (NUL) halt | ('a'NUL) halt | ('aa'NUL) halt | ('b'NUL) halt | ('bb'NUL) halt | 
// (*) | (*) 0  | ('a'*) 0  | ('aa'*) 0  | ('b'*) 0  | ('bb'*) 0  | 
*/ 

void chg_data(char *src) { 
    char *dst, ch; 
    int state = 0; 
    dst = src; 
    for (;;) { 
    ch = *src++; 
    if (ch == 'a' && state == 0) {state=1;} 
    else if (ch == 'a' && state == 1) {state=2;} 
    else if (ch == 'a' && state == 2) {state=0; *dst++='1';} 
    else if (ch == 'a' && state == 3) {state=1; *dst++='b';} 
    else if (ch == 'a' && state == 4) {state=1; *dst++='b'; *dst++='b';} 
    else if (ch == 'b' && state == 0) {state=3;} 
    else if (ch == 'b' && state == 1) {state=3; *dst++='a';} 
    else if (ch == 'b' && state == 2) {state=3; *dst++='a'; *dst++='a';} 
    else if (ch == 'b' && state == 3) {state=4;} 
    else if (ch == 'b' && state == 4) {state=0; *dst++='0';} 
    else if (ch == '\0' && state == 0) {*dst++='\0'; break;} 
    else if (ch == '\0' && state == 1) {*dst++='a'; *dst++='\0'; break;} 
    else if (ch == '\0' && state == 2) {*dst++='a'; *dst++='a'; *dst++='\0'; break;} 
    else if (ch == '\0' && state == 3) {*dst++='b'; *dst++='\0'; break;} 
    else if (ch == '\0' && state == 4) {*dst++='b'; *dst++='b'; *dst++='\0'; break;} 
    else if (state == 0) {state=0; *dst++=ch;} 
    else if (state == 1) {state=0; *dst++='a'; *dst++=ch;} 
    else if (state == 2) {state=0; *dst++='a'; *dst++='a'; *dst++=ch;} 
    else if (state == 3) {state=0; *dst++='b'; *dst++=ch;} 
    else if (state == 4) {state=0; *dst++='b'; *dst++='b'; *dst++=ch;} 
    else assert(0 && "this didn't happen!"); 
    } 
} 

int main(void) { 
    char data[] = "(aaa and bbb or (aaa or aaa or bbb))"; 
    printf("Before: %s\n", data); 
    chg_data(data); 
    printf(" After: %s\n", data); 
    return 0; 
} 
1

这是没有内存限制:

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

/* --------------------------------------------------------------------------- 
    Name  : replace - Search & replace a substring by another one. 
    Creation : Thierry Husson, Sept 2010 
    Parameters : 
     str : Big string where we search 
     oldstr : Substring we are looking for 
     newstr : Substring we want to replace with 
     count : Optional pointer to int (input/output value). NULL to ignore. 
       Input: Maximum replacements to be done. NULL or < 1 to do all. 
       Output: Number of replacements done or -1 if not enough memory. 
    Returns : Pointer to the new string or NULL if error. 
    Notes  : 
    - Case sensitive - Otherwise, replace functions "strstr" by "strcasestr" 
    - Always allocate memory for the result. 
--------------------------------------------------------------------------- */ 
char* replace(const char *str, const char *oldstr, const char *newstr, int *count) 
{ 
    const char *tmp = str; 
    char *result; 
    int found = 0; 
    int length, reslen; 
    int oldlen = strlen(oldstr); 
    int newlen = strlen(newstr); 
    int limit = (count != NULL && *count > 0) ? *count : -1; 

    tmp = str; 
    while ((tmp = strstr(tmp, oldstr)) != NULL && found != limit) 
     found++, tmp += oldlen; 

    length = strlen(str) + found * (newlen - oldlen); 
    if ((result = (char *)malloc(length+1)) == NULL) { 
     fprintf(stderr, "Not enough memory\n"); 
     found = -1; 
    } else { 
     tmp = str; 
     limit = found; /* Countdown */ 
     reslen = 0; /* length of current result */ 
     /* Replace each old string found with new string */ 
     while ((limit-- > 0) && (tmp = strstr(tmp, oldstr)) != NULL) { 
     length = (tmp - str); /* Number of chars to keep intouched */ 
     strncpy(result + reslen, str, length); /* Original part keeped */ 
     strcpy(result + (reslen += length), newstr); /* Insert new string */ 
     reslen += newlen; 
     tmp += oldlen; 
     str = tmp; 
     } 
     strcpy(result + reslen, str); /* Copies last part and ending nul char */ 
    } 
    if (count != NULL) *count = found; 
    return result; 
} 


/* --------------------------------------------------------------------------- 
    Samples 
--------------------------------------------------------------------------- */ 
int main(void) 
{ 
    char *str, *str2; 
    int rpl; 

    /* ---------------------------------------------------------------------- */ 
    /* Simple sample */ 
    rpl = 0; /* Illimited replacements */ 
    str = replace("Hello World!", "World", "Canada", &rpl); 
    printf("Replacements: %d\tResult: [%s]\n\n", rpl, str); 
    /* Replacements: 1  Result: [Hello Canada!] */ 
    free(str); 

    /* ---------------------------------------------------------------------- */ 
    /* Sample with dynamic memory to clean */ 
    rpl = 0; /* Illimited replacements */ 
    str = strdup("abcdef"); 
    if ((str2 = replace(str, "cd", "1234", &rpl)) != NULL) { 
     free(str); 
     str = str2; 
    } 
    printf("Replacements: %d\tResult: [%s]\n\n", rpl, str); 
    /* Replacements: 1  Result: [ab1234ef] */ 
    free(str); 

    /* ---------------------------------------------------------------------- */ 
    /* Illimited replacements - Case sensitive & Smaller result */ 
    str = replace("XXXHello XXXX world XX salut xxx monde!XXX", "XXX", "-",NULL); 
    printf("Result: [%s]\n\n", str); 
    /* Result: [-Hello -X world XX salut xxx monde!-] */ 
    free(str); 

    /* ---------------------------------------------------------------------- */ 
    rpl = 3; /* Limited replacements */ 
    str = replace("AAAAAA", "A", "*", &rpl); 
    printf("Replacements: %d\tResult: [%s]\n\n", rpl, str); 
    /* Replacements: 3  Result: [***AAA] */ 
    free(str); 

    return 0; 
}