假设我有一个字符串:
"(aaa and bbb or (aaa or aaa or bbb))"
**为简单起见,这将始终是字符串的格式,始终是3 a后跟空格或')'或3b后跟空格或')'。
用'1'代替'aaa'的每一个出现的最佳方法是什么,并且'结束字符串中'bbb'与'0'的每次出现应该是这样的:
"(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 :(得分:4)
最有效的方法是使用POSIX的正则表达式族。一些实现将为模式构建适当的自动机。另一种方法是重复使用KMP或Boyer-Moore搜索,但是你必须多次扫描字符串,效率较低。另外,给出这样的输入你想得到什么结果:aa = 1,ab = 2,bb = 3 on string“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。源代码可能有问题,因为我还没有真正尝试过。但这个想法就在那里。这是我能想到的最有效的实现。
答案 1 :(得分:1)
对于这种特定情况,一个简单的while / for循环可以解决问题。但它看起来像是一个家庭作业问题,所以我不会为你明确写出来。如果需要更通用的字符串操作,我会使用pcre。
答案 2 :(得分: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;
}
答案 3 :(得分: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;
}
免责声明,我甚至没有对此进行测试,但它至少应该朝着你想要的方向发展。
答案 4 :(得分: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;
}
答案 5 :(得分:-3)
您可以使用std::find和std::replace函数为每次替换尝试循环。 您将找到有关std :: string here的更多信息。