什么是replaceC中的string的函数?

给定一个(char *)string,我想查找所有出现的子string,并用替代stringreplace它。 我没有看到任何简单的函数在<string.h>中实现

优化器应该消除大部分局部variables。 tmp指针在那里确保strcpy不必走string来findnull。 tmp指向每次调用后结果的结尾。 (请参阅Shlemiel画家的algorithm为什么strcpy可能很烦人。)

编辑:没有注意到“第一次发现所有的事件”:

// You must free the result if result is non-NULL. char *str_replace(char *orig, char *rep, char *with) { char *result; // the return string char *ins; // the next insert point char *tmp; // varies int len_rep; // length of rep (the string to remove) int len_with; // length of with (the string to replace rep with) int len_front; // distance between rep and end of last rep int count; // number of replacements // sanity checks and initialization if (!orig || !rep) return NULL; len_rep = strlen(rep); if (len_rep == 0) return NULL; // empty rep causes infinite loop during count if (!with) with = ""; len_with = strlen(with); // count the number of replacements needed ins = orig; for (count = 0; tmp = strstr(ins, rep); ++count) { ins = tmp + len_rep; } tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); if (!result) return NULL; // first time through the loop, all the variable are set correctly // from here on, // tmp points to the end of the result string // ins points to the next occurrence of rep in orig // orig points to the remainder of orig after "end of rep" while (count--) { ins = strstr(orig, rep); len_front = ins - orig; tmp = strncpy(tmp, orig, len_front) + len_front; tmp = strcpy(tmp, with) + len_with; orig += len_front + len_rep; // move to next "end of rep" } strcpy(tmp, orig); return result; } 

这在标准的C库中没有提供,因为只有char *,如果replacestring比被replace的string长,则不能增加分配给string的内存。

你可以更容易地使用std :: string来做到这一点,但即使在那里,没有一个函数会为你做。

没有一个。

你需要使用类似strstr和strcat或strcpy的东西来滚动你自己的东西。

由于C中的string不能dynamic增长,所以replace通常不起作用。 因此,您需要为有足够空间replace的新string分配空间,然后将原始部分和replace部分复制到新string中。 要复制你要使用strncpy的部分。

你可以使用strstr来build立你自己的replace函数来查找子string和strncpy将其复制到一个新的缓冲区。

除非你想要replace_with与你想要replace长度相同,那么最好使用一个新的缓冲区来复制新的string。

这是一些示例代码。

 #include <string.h> #include <stdlib.h> char * replace( char const * const original, char const * const pattern, char const * const replacement ) { size_t const replen = strlen(replacement); size_t const patlen = strlen(pattern); size_t const orilen = strlen(original); size_t patcnt = 0; const char * oriptr; const char * patloc; // find how many times the pattern occurs in the original string for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) { patcnt++; } { // allocate memory for the new string size_t const retlen = orilen + patcnt * (replen - patlen); char * const returned = (char *) malloc( sizeof(char) * (retlen + 1) ); if (returned != NULL) { // copy the original string, // replacing all the instances of the pattern char * retptr = returned; for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) { size_t const skplen = patloc - oriptr; // copy the section until the occurence of the pattern strncpy(retptr, oriptr, skplen); retptr += skplen; // copy the replacement strncpy(retptr, replacement, replen); retptr += replen; } // copy the rest of the string. strcpy(retptr, oriptr); } return returned; } } #include <stdio.h> int main(int argc, char * argv[]) { if (argc != 4) { fprintf(stderr,"usage: %s <original text> <pattern> <replacement>\n", argv[0]); exit(-1); } else { char * const newstr = replace(argv[1], argv[2], argv[3]); if (newstr) { printf("%s\n", newstr); free(newstr); } else { fprintf(stderr,"allocation error\n"); exit(-2); } } return 0; } 
 // Here is the code for unicode strings! int mystrstr(wchar_t *txt1,wchar_t *txt2) { wchar_t *posstr=wcsstr(txt1,txt2); if(posstr!=NULL) { return (posstr-txt1); }else { return -1; } } // assume: supplied buff is enough to hold generated text void StringReplace(wchar_t *buff,wchar_t *txt1,wchar_t *txt2) { wchar_t *tmp; wchar_t *nextStr; int pos; tmp=wcsdup(buff); pos=mystrstr(tmp,txt1); if(pos!=-1) { buff[0]=0; wcsncpy(buff,tmp,pos); buff[pos]=0; wcscat(buff,txt2); nextStr=tmp+pos+wcslen(txt1); while(wcslen(nextStr)!=0) { pos=mystrstr(nextStr,txt1); if(pos==-1) { wcscat(buff,nextStr); break; } wcsncat(buff,nextStr,pos); wcscat(buff,txt2); nextStr=nextStr+pos+wcslen(txt1); } } free(tmp); } 

creativeandcritical.net上的repl_str()函数快速可靠。 该页面还包含一个宽string变体repl_wcs() ,它可以与Unicodestring(包括以UTF-8编码的string)一起使用,通过帮助函数 – 演示代码从页面链接。 迟来的全面披露:我是那个页面的作者和它的function。

我发现大部分build议的function很难理解 – 所以我想出了这个:

 static char *dull_replace(const char *in, const char *pattern, const char *by) { size_t outsize = strlen(in) + 1; // TODO maybe avoid reallocing by counting the non-overlapping occurences of pattern char *res = malloc(outsize); // use this to iterate over the output size_t resoffset = 0; char *needle; while (needle = strstr(in, pattern)) { // copy everything up to the pattern memcpy(res + resoffset, in, needle - in); resoffset += needle - in; // skip the pattern in the input-string in = needle + strlen(pattern); // adjust space for replacement outsize = outsize - strlen(pattern) + strlen(by); res = realloc(res, outsize); // copy the pattern memcpy(res + resoffset, by, strlen(by)); resoffset += strlen(by); } // copy the remaining input strcpy(res + resoffset, in); return res; } 

输出必须是免费的

随时添加改进:-)

这是我根据这些要求创build的:

  1. 无论是长还是短,都要replace模式。

  2. 不使用任何malloc(显式或隐式)来内在地避免内存泄漏。

  3. replace任意数量的模式。

  4. 容忍具有等于searchstring的子string的replacestring。

  5. 不需要检查线arrays是否足够容纳replace。 例如,除非调用者知道该行的大小足以保存新string,否则这不起作用。

 /* returns number of strings replaced. */ int replacestr(char *line, const char *search, const char *replace) { int count; char *sp; // start of pattern //printf("replacestr(%s, %s, %s)\n", line, search, replace); if ((sp = strstr(line, search)) == NULL) { return(0); } count = 1; int sLen = strlen(search); int rLen = strlen(replace); if (sLen > rLen) { // move from right to left char *src = sp + sLen; char *dst = sp + rLen; while((*dst = *src) != '\0') { dst++; src++; } } else if (sLen < rLen) { // move from left to right int tLen = strlen(sp) - sLen; char *stop = sp + rLen; char *src = sp + sLen + tLen; char *dst = sp + rLen + tLen; while(dst >= stop) { *dst = *src; dst--; src--; } } memcpy(sp, replace, rLen); count += replacestr(sp + rLen, search, replace); return(count); } 

任何改善这个代码的build议都被欢迎。 只要发表评论,我会testing它。

修复fann95的响应,使用就地修改string,并假设line指向的缓冲区足够大,以容纳结果string。

 static void replacestr(char *line, const char *search, const char *replace) { char *sp; if ((sp = strstr(line, search)) == NULL) { return; } int search_len = strlen(search); int replace_len = strlen(replace); int tail_len = strlen(sp+search_len); memmove(sp+replace_len,sp+search_len,tail_len+1); memcpy(sp, replace, replace_len); } 
 char *replace(char *instring,char *old,char *new) { if(!instring || !old || !new){ return (char*)NULL; } size_t instring_size=strlen(instring); size_t new_size=strlen(new); size_t old_size=strlen(old); size_t diffsize=new_size-old_size; size_t diffsizeAll=diffsize; size_t outstring_size=instring_size*2 + 1; char *outstring; char *test; test=(char*)malloc(old_size+1); outstring =(char*) malloc(outstring_size); if(!outstring || !test){ return (char*)NULL; } if(instring_size<old_size || old_size==0) { strcpy(outstring, instring); free(test); return outstring; } outstring[0]='\0'; int i; for(i=0; i <= instring_size; i++) { strncpy(test,(instring+i),old_size); test[old_size]='\0'; if(strcmp(test,old)==0){ if((instring_size+diffsizeAll) > outstring_size) { outstring_size=outstring_size*2+1; outstring=realloc(outstring,outstring_size); if(!outstring){ free(test); return (char*)NULL; } } strcat(outstring,new); i=i+old_size-1; diffsizeAll=diffsizeAll+diffsize; }else{ test[1]='\0'; strcat(outstring,test); } } free(test); return outstring; } 

你去…这是用stringstrchar xreplacechar x每个出现的函数

 char *zStrrep(char *str, char x, char y){ char *tmp=str; while(*tmp) if(*tmp == x) *tmp++ = y; /* assign first, then incement */ else *tmp++; *tmp='\0'; return str; } 

一个示例用法可能是

  Exmaple Usage char s[]="this is a trial string to test the function."; char x=' ', y='_'; printf("%s\n",zStrrep(s,x,y)); Example Output this_is_a_trial_string_to_test_the_function. 

该函数来自我在Github上维护的string库 ,欢迎您来看看其他可用的函数,甚至有助于代码:)

https://github.com/fnoyanisi/zString

编辑:@siride是对的,上面的函数只replace字符。 只是写了这个,取代了string。

 #include <stdio.h> #include <stdlib.h> /* replace every occurance of string x with string y */ char *zstring_replace_str(char *str, const char *x, const char *y){ char *tmp_str = str, *tmp_x = x, *dummy_ptr = tmp_x, *tmp_y = y; int len_str=0, len_y=0, len_x=0; /* string length */ for(; *tmp_y; ++len_y, ++tmp_y) ; for(; *tmp_str; ++len_str, ++tmp_str) ; for(; *tmp_x; ++len_x, ++tmp_x) ; /* Bounds check */ if (len_y >= len_str) return str; /* reset tmp pointers */ tmp_y = y; tmp_x = x; for (tmp_str = str ; *tmp_str; ++tmp_str) if(*tmp_str == *tmp_x) { /* save tmp_str */ for (dummy_ptr=tmp_str; *dummy_ptr == *tmp_x; ++tmp_x, ++dummy_ptr) if (*(tmp_x+1) == '\0' && ((dummy_ptr-str+len_y) < len_str)){ /* Reached end of x, we got something to replace then! * Copy y only if there is enough room for it */ for(tmp_y=y; *tmp_y; ++tmp_y, ++tmp_str) *tmp_str = *tmp_y; } /* reset tmp_x */ tmp_x = x; } return str; } int main() { char s[]="Free software is a matter of liberty, not price.\n" "To understand the concept, you should think of 'free' \n" "as in 'free speech', not as in 'free beer'"; printf("%s\n\n",s); printf("%s\n",zstring_replace_str(s,"ree","XYZ")); return 0; } 

以下是输出

 Free software is a matter of liberty, not price. To understand the concept, you should think of 'free' as in 'free speech', not as in 'free beer' FXYZ software is a matter of liberty, not price. To understand the concept, you should think of 'fXYZ' as in 'fXYZ speech', not as in 'fXYZ beer' 
 /*замена символа в строке*/ char* replace_char(char* str, char in, char out) { char * p = str; while(p != '\0') { if(*p == in) *p == out; ++p; } return str; } 

你可以使用这个函数(注释说明它是如何工作的):

 void strreplace(char *string, const char *find, const char *replaceWith){ if(strstr(string, replaceWith) != NULL){ char *temporaryString = malloc(strlen(strstr(string, find) + strlen(find)) + 1); strcpy(temporaryString, strstr(string, find) + strlen(find)); //Create a string with what's after the replaced part *strstr(string, find) = '\0'; //Take away the part to replace and the part after it in the initial string strcat(string, replaceWith); //Concat the first part of the string with the part to replace with strcat(string, temporaryString); //Concat the first part of the string with the part after the replaced part free(temporaryString); //Free the memory to avoid memory leaks } } 
 DWORD ReplaceString(__inout PCHAR source, __in DWORD dwSourceLen, __in const char* pszTextToReplace, __in const char* pszReplaceWith) { DWORD dwRC = NO_ERROR; PCHAR foundSeq = NULL; PCHAR restOfString = NULL; PCHAR searchStart = source; size_t szReplStrcLen = strlen(pszReplaceWith), szRestOfStringLen = 0, sztextToReplaceLen = strlen(pszTextToReplace), remainingSpace = 0, dwSpaceRequired = 0; if (strcmp(pszTextToReplace, "") == 0) dwRC = ERROR_INVALID_PARAMETER; else if (strcmp(pszTextToReplace, pszReplaceWith) != 0) { do { foundSeq = strstr(searchStart, pszTextToReplace); if (foundSeq) { szRestOfStringLen = (strlen(foundSeq) - sztextToReplaceLen) + 1; remainingSpace = dwSourceLen - (foundSeq - source); dwSpaceRequired = szReplStrcLen + (szRestOfStringLen); if (dwSpaceRequired > remainingSpace) { dwRC = ERROR_MORE_DATA; } else { restOfString = CMNUTIL_calloc(szRestOfStringLen, sizeof(CHAR)); strcpy_s(restOfString, szRestOfStringLen, foundSeq + sztextToReplaceLen); strcpy_s(foundSeq, remainingSpace, pszReplaceWith); strcat_s(foundSeq, remainingSpace, restOfString); } CMNUTIL_free(restOfString); searchStart = foundSeq + szReplStrcLen; //search in the remaining str. (avoid loops when replWith contains textToRepl } } while (foundSeq && dwRC == NO_ERROR); } return dwRC; }