ด้วยchar *
สตริง( ) ฉันต้องการค้นหาเหตุการณ์ที่เกิดขึ้นทั้งหมดของสตริงย่อยและแทนที่ด้วยสตริงอื่น ฉันไม่เห็นฟังก์ชั่นง่ายๆที่ทำได้ใน<string.h>
.
ด้วยchar *
สตริง( ) ฉันต้องการค้นหาเหตุการณ์ที่เกิดขึ้นทั้งหมดของสตริงย่อยและแทนที่ด้วยสตริงอื่น ฉันไม่เห็นฟังก์ชั่นง่ายๆที่ทำได้ใน<string.h>
.
คำตอบ:
เครื่องมือเพิ่มประสิทธิภาพควรกำจัดตัวแปรโลคัลส่วนใหญ่ ตัวชี้ tmp อยู่ที่นั่นเพื่อให้แน่ใจว่า strcpy ไม่ต้องเดินสตริงเพื่อค้นหา null tmp ชี้ไปที่จุดสิ้นสุดของผลลัพธ์หลังจากการโทรแต่ละครั้ง (ดูอัลกอริทึมของจิตรกรของ Shlemielว่าเหตุใด 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;
}
size_t
แทนint
สำหรับขนาดวัตถุ / สตริงและดัชนีที่กำหนดเอง จุดประสงค์ของstrcpy(tmp, orig);
ท้ายที่สุดคืออะไร? ดูเหมือนไม่ถูกต้อง
for
ลูปแรกfor (count = 1; ins = strstr(ins + rep_len, rep); ++count) {}
นั้นได้จากนั้นtmp
จะใช้สำหรับการเขียนเท่านั้น
สิ่งนี้ไม่มีให้ในไลบรารี C มาตรฐานเนื่องจากมีเพียงถ่าน * คุณไม่สามารถเพิ่มหน่วยความจำที่จัดสรรให้กับสตริงได้หากสตริงแทนที่ยาวกว่าสตริงที่ถูกแทนที่
คุณสามารถทำได้โดยใช้ std :: string ได้ง่ายขึ้น แต่ถึงอย่างนั้นก็ไม่มีฟังก์ชันเดียวที่จะทำเพื่อคุณ
ไม่มีเลย
คุณต้องม้วนของคุณเองโดยใช้สิ่งต่างๆเช่นstrstrและ strcat หรือ strcpy
strcat()
เป็นคำแนะนำที่ไม่ดี
คุณสามารถสร้างฟังก์ชันการแทนที่ของคุณเองโดยใช้ strstr เพื่อค้นหาสตริงย่อยและ strncpy เพื่อคัดลอกส่วนต่างๆไปยังบัฟเฟอร์ใหม่
เว้นแต่สิ่งที่คุณต้องการจะreplace_with
มีความยาวเท่ากับสิ่งที่คุณต้องการคุณreplace
ควรใช้บัฟเฟอร์ใหม่เพื่อคัดลอกสตริงใหม่
นี่คือตัวอย่างโค้ดบางส่วนที่ทำได้
#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);
}
repl_str ()ฟังก์ชั่นใน creativeandcritical.net เป็นไปอย่างรวดเร็วและเชื่อถือได้ รวมอยู่ในหน้านั้นด้วยคือตัวแปรสตริงแบบกว้างrepl_wcs ()ซึ่งสามารถใช้ได้กับสตริง Unicode รวมถึงที่เข้ารหัสใน UTF-8 ผ่านฟังก์ชันตัวช่วย - โค้ดสาธิตจะเชื่อมโยงจากเพจ การเปิดเผยข้อมูลทั้งหมดที่ล่าช้า: ฉันเป็นผู้เขียนหน้านั้นและหน้าที่ในหน้านั้น
pos_cache = realloc(pos_cache
free(pos_cache);
ฟังก์ชัน at
realloc
อาจล้มเหลว หากเป็นเช่นนั้นระบบจะส่งกลับNULL
และปล่อยให้ตัวชี้เก่าเหมือนเดิม p = realloc(p, x)
เมื่อเกิดความล้มเหลวให้เขียนตัวชี้ฮีปที่ถูกต้องอีกครั้งp
ด้วยNULL
และหากนั่นp
เป็นการอ้างอิงเพียงอย่างเดียวของคุณไปยังวัตถุฮีปนั้นตอนนี้คุณก็รั่วไหล มันเป็นความผิดพลาดของมือใหม่แบบคลาสสิก
ฉันพบว่าฟังก์ชั่นที่นำเสนอส่วนใหญ่ยากที่จะเข้าใจ - ดังนั้นฉันจึงคิดสิ่งนี้:
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;
}
ผลลัพธ์ต้องเป็นอิสระ
คุณสามารถใช้ฟังก์ชันนี้ (ความคิดเห็นอธิบายวิธีการทำงาน):
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
}
}
นี่คือสิ่งที่ฉันสร้างขึ้นตามข้อกำหนดเหล่านี้:
แทนที่รูปแบบไม่ว่าจะยาวหรือสั้น
อย่าใช้ malloc ใด ๆ (โดยชัดแจ้งหรือโดยนัย) เพื่อหลีกเลี่ยงการรั่วไหลของหน่วยความจำภายใน
แทนที่จำนวนของรูปแบบที่เกิดขึ้น
ทนต่อสตริงการแทนที่ที่มีสตริงย่อยเท่ากับสตริงการค้นหา
ไม่ต้องตรวจสอบว่า Line array มีขนาดเพียงพอที่จะทำการเปลี่ยนหรือไม่ เช่นไม่ได้ผลเว้นแต่ผู้โทรจะรู้ว่าเส้นมีขนาดเพียงพอที่จะเก็บสตริงใหม่ได้
/* 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);
}
ข้อเสนอแนะใด ๆ ในการปรับปรุงรหัสนี้ได้รับการยอมรับด้วยความยินดี เพียงโพสต์ความคิดเห็นและฉันจะทดสอบ
นี่เป็นของฉันทำให้เป็นถ่าน * ทั้งหมดซึ่งทำให้การโทรง่ายขึ้น ...
char *strrpc(char *str,char *oldstr,char *newstr){
char bstr[strlen(str)];
memset(bstr,0,sizeof(bstr));
int i;
for(i = 0;i < strlen(str);i++){
if(!strncmp(str+i,oldstr,strlen(oldstr))){
strcat(bstr,newstr);
i += strlen(oldstr) - 1;
}else{
strncat(bstr,str + i,1);
}
}
strcpy(str,bstr);
return str;
}
คุณสามารถใช้ strrep ()
ถ่าน * strrep (const char * cadena, const char * strf, const char * strr)
strrep (สตริงแทนที่) แทนที่ 'strf' ด้วย 'strr' ใน 'cadena' และส่งคืนสตริงใหม่ คุณต้องปลดปล่อยสตริงที่ส่งคืนในโค้ดของคุณหลังจากใช้ strrep
Parameters cadena สตริงที่มีข้อความ strf ข้อความที่ต้องการค้นหา strr ข้อความแทนที่
ส่งคืนข้อความที่อัปเดตด้วยการแทนที่
สามารถดูโครงการได้ที่https://github.com/ipserc/strrep
การแก้ไขการตอบสนองของ fann95 โดยใช้การปรับเปลี่ยนในสถานที่ของสตริงและสมมติว่าบัฟเฟอร์ที่ชี้ไปทีละบรรทัดมีขนาดใหญ่พอที่จะเก็บสตริงผลลัพธ์ได้
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);
}
มีคุณไป .... นี้เป็นฟังก์ชั่นที่จะเปลี่ยน occurance ของทุกchar x
กับchar y
ภายในตัวอักษรstr
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คุณยินดีเป็นอย่างยิ่งที่จะได้ดูฟังก์ชั่นอื่น ๆ ที่มีอยู่หรือแม้แต่ร่วมให้โค้ด :)
https://github.com/fnoyanisi/zString
แก้ไข: @siride ถูกต้องฟังก์ชันด้านบนจะแทนที่ตัวอักษรเท่านั้น เพิ่งเขียนอันนี้ซึ่งแทนที่สตริงอักขระ
#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;
}
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;
}
char *replace(const char*instring, const char *old_part, const char *new_part)
{
#ifndef EXPECTED_REPLACEMENTS
#define EXPECTED_REPLACEMENTS 100
#endif
if(!instring || !old_part || !new_part)
{
return (char*)NULL;
}
size_t instring_len=strlen(instring);
size_t new_len=strlen(new_part);
size_t old_len=strlen(old_part);
if(instring_len<old_len || old_len==0)
{
return (char*)NULL;
}
const char *in=instring;
const char *found=NULL;
size_t count=0;
size_t out=0;
size_t ax=0;
char *outstring=NULL;
if(new_len> old_len )
{
size_t Diff=EXPECTED_REPLACEMENTS*(new_len-old_len);
size_t outstring_len=instring_len + Diff;
outstring =(char*) malloc(outstring_len);
if(!outstring){
return (char*)NULL;
}
while((found = strstr(in, old_part))!=NULL)
{
if(count==EXPECTED_REPLACEMENTS)
{
outstring_len+=Diff;
if((outstring=realloc(outstring,outstring_len))==NULL)
{
return (char*)NULL;
}
count=0;
}
ax=found-in;
strncpy(outstring+out,in,ax);
out+=ax;
strncpy(outstring+out,new_part,new_len);
out+=new_len;
in=found+old_len;
count++;
}
}
else
{
outstring =(char*) malloc(instring_len);
if(!outstring){
return (char*)NULL;
}
while((found = strstr(in, old_part))!=NULL)
{
ax=found-in;
strncpy(outstring+out,in,ax);
out+=ax;
strncpy(outstring+out,new_part,new_len);
out+=new_len;
in=found+old_len;
}
}
ax=(instring+instring_len)-in;
strncpy(outstring+out,in,ax);
out+=ax;
outstring[out]='\0';
return outstring;
}
ฟังก์ชันนี้ใช้ได้เฉพาะเมื่อสตริง ur มีช่องว่างเพิ่มเติมสำหรับความยาวใหม่
void replace_str(char *str,char *org,char *rep)
{
char *ToRep = strstr(str,org);
char *Rest = (char*)malloc(strlen(ToRep));
strcpy(Rest,((ToRep)+strlen(org)));
strcpy(ToRep,rep);
strcat(ToRep,Rest);
free(Rest);
}
สิ่งนี้จะแทนที่เหตุการณ์แรกเท่านั้น
ที่นี่เป็นของฉันมันมีอยู่ในตัวและมีความหลากหลายรวมถึงมีประสิทธิภาพมันจะเติบโตหรือลดขนาดบัฟเฟอร์ตามความจำเป็นในการเรียกซ้ำแต่ละครั้ง
void strreplace(char *src, char *str, char *rep)
{
char *p = strstr(src, str);
if (p)
{
int len = strlen(src)+strlen(rep)-strlen(str);
char r[len];
memset(r, 0, len);
if ( p >= src ){
strncpy(r, src, p-src);
r[p-src]='\0';
strncat(r, rep, strlen(rep));
strncat(r, p+strlen(str), p+strlen(str)-src+strlen(src));
strcpy(src, r);
strreplace(p+strlen(rep), str, rep);
}
}
}
ใช้ strlen จาก string.h
ขอโทษสำหรับภาษาอังกฤษของฉัน
char * str_replace(char * text,char * rep, char * repw){//text -> to replace in it | rep -> replace | repw -> replace with
int replen = strlen(rep),repwlen = strlen(repw),count;//some constant variables
for(int i=0;i<strlen(text);i++){//search for the first character from rep in text
if(text[i] == rep[0]){//if it found it
count = 1;//start searching from the next character to avoid repetition
for(int j=1;j<replen;j++){
if(text[i+j] == rep[j]){//see if the next character in text is the same as the next in the rep if not break
count++;
}else{
break;
}
}
if(count == replen){//if count equals to the lenght of the rep then we found the word that we want to replace in the text
if(replen < repwlen){
for(int l = strlen(text);l>i;l--){//cuz repwlen greater than replen we need to shift characters to the right to make space for the replacement to fit
text[l+repwlen-replen] = text[l];//shift by repwlen-replen
}
}
if(replen > repwlen){
for(int l=i+replen-repwlen;l<strlen(text);l++){//cuz replen greater than repwlen we need to shift the characters to the left
text[l-(replen-repwlen)] = text[l];//shift by replen-repwlen
}
text[strlen(text)-(replen-repwlen)] = '\0';//get rid of the last unwanted characters
}
for(int l=0;l<repwlen;l++){//replace rep with repwlen
text[i+l] = repw[l];
}
if(replen != repwlen){
i+=repwlen-1;//pass to the next character | try text "y" ,rep "y",repw "yy" without this line to understand
}
}
}
}
return text;
}
หากคุณต้องการรหัส strlen เพื่อหลีกเลี่ยงการเรียก string.h
int strlen(char * string){//use this code to avoid calling string.h
int lenght = 0;
while(string[lenght] != '\0'){
lenght++;
}
return lenght;
}