C字符串字符串
内的多个替代可以说我有一个字符串: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"
最有效的方法是使用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。源代码可能是越野车,因为我没有真正尝试过。但是这个想法就在那里。这是我能想到的最有效的实现。
好的,我编辑过?使其分配新的空间。不确定你输入的含义:aa = 1,ab = 2,bb = 3。 – user105033 2009-09-29 22:57:51
我的意思是用1代替aa,用2代替ab,用3代替bb。你可以得到“13”或“a2b”。 – user172818 2009-09-29 22:59:30
+1用于解决重叠的字符串大小写 – Ashwin 2009-09-29 22:59:36
对于这个特定的情况,一个简单的while/for循环可以做到这一点。但它看起来像一个家庭作业问题,所以我不会为你明确写出它。如果需要更多的通用字符串操作,我会使用pcre。
使用PCRE的+1。 – user172818 2009-09-29 23:28:36
这绝不是世界上最优雅的解决方案,它也假定结尾字符串总是比原始字体小,哦,我对转换进行了硬编码,但希望它能指出您或多或少在正确的方向或者给你一个想法,从跳下:
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;
}
声明,我甚至没有对此进行测试,但它应该是在你想要的方向上至少半。
这是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;
}
这是没有内存限制:
#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;
}
您是否有兴趣在一个通用的解决方案,与DEST,其中src和dest中可以有不同的长度SRC替换所有出现的? – Ashwin 2009-09-29 21:48:40
是的,长度无关紧要。 – user105033 2009-09-29 21:51:55