C의 문자열에서 서브스트링을 대체하는 기능은 무엇입니까?
(의 경우)char *
) 문자열, 서브스트링의 모든 항목을 찾아 대체 문자열로 대체합니다.이 기능을 실현하는 단순한 기능은 없습니다.<string.h>
.
최적화 도구에서는 대부분의 로컬 변수를 제거해야 합니다.tmp 포인터는 strcpy가 null을 찾기 위해 스트링을 사용할 필요가 없음을 확인하기 위해 존재합니다.tmp는 각 콜 후에 결과의 끝을 가리킵니다.(스트rcpy가 귀찮을 수 있는 이유에 대해서는 화가 Shlemiel의 알고리즘을 참조해 주세요.)
// 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;
}
없어요.
strstr, strcat 또는 strcpy와 같은 것을 사용하여 직접 롤링을 해야 합니다.
strstr을 사용하여 새로운 버퍼에 복사하는 서브스트링과 strncpy를 검색하여 독자적인 치환 함수를 구축할 수 있습니다.
네가 원하는 게 아니라면replace_with
원하는 길이와 같은 길이입니다.replace
새 문자열을 복사하는 데 새 버퍼를 사용하는 것이 가장 좋습니다.
표준 C 라이브러리에서는 이 기능이 제공되지 않습니다.이는 char*만 지정해도 치환 문자열이 치환되는 문자열보다 길면 문자열에 할당된 메모리를 늘릴 수 없기 때문입니다.
std:: string을 사용하면 더 쉽게 실행할 수 있지만, 이 경우에도 단일 함수는 사용할 수 없습니다.
creativeandcritical.net의 ref_str() 함수는 빠르고 신뢰할 수 있습니다.또한 이 페이지에는 UTF-8로 인코딩된 문자열을 포함한 Unicode 문자열과 함께 사용할 수 있는 와이드 문자열 바리안트 repl_wcs()가 포함되어 있으며, 도우미 기능을 통해 이 페이지에서 데모 코드를 링크할 수 있습니다.뒤늦게 완전 공개:저는 그 페이지와 그 기능의 저자입니다.
여기 이 기능을 하는 샘플 코드가 있습니다.
#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;
}
이 함수는 문자열에 새 길이를 위한 여분의 공간이 있는 경우에만 작동합니다.
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);
}
이것은 첫 번째 오카렌스만 대체합니다.
C의 문자열은 동적으로 증가할 수 없기 때문에 일반적으로 inplace 치환은 작동하지 않습니다.따라서 치환을 위한 충분한 공간이 있는 새 문자열에 공간을 할당한 후 원래 문자열과 치환을 더한 부분을 새 문자열로 복사해야 합니다.strncpy를 사용하는 부분을 복사하기 위해 사용합니다.
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);
}
// 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);
}
여기 제 것이 있습니다.모두 char*로 해 주세요.이것에 의해, 콜이 용이하게 됩니다.
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;
}
이 기능을 사용할 수 있습니다(코멘트에서는 동작 방법에 대해 설명합니다).
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
}
}
strrep()을 사용할 수 있습니다.
char* strrep ( const char * cadena , const char * strf , const char * strr )
strrep(스트링 치환).'cadena'에서 'strf'를 'strr'로 바꾸고 새 문자열을 반환합니다.strrep을 사용한 후 코드 내에서 반환된 문자열을 해방해야 합니다.
Parameters cadena 텍스트.strf 찾을 텍스트.strr 치환 텍스트.
Returns 치환된 텍스트가 갱신되었습니다.
프로젝트는 https://github.com/ipserc/strrep 에서 보실 수 있습니다.
제안된 기능의 대부분은 이해하기 어렵기 때문에 다음과 같이 생각했습니다.
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;
}
출력은 free'd여야 합니다.
다음은 다음 요건에 따라 작성한 것입니다.
길이가 길거나 짧거나 관계없이 패턴을 바꿉니다.
메모리 누수를 본질적으로 방지하기 위해 malloc(명시적 또는 암묵적)를 사용하지 마십시오.
패턴의 발생 횟수를 바꿉니다.
하위 문자열이 검색 문자열과 동일한 바꾸기 문자열을 허용합니다.
라인 어레이의 사이즈가 교환품을 보관하기에 충분한지 확인할 필요는 없습니다.발신자가 회선의 사이즈가 새로운 스트링을 보관 유지하기에 충분한 것을 알지 않는 한, 이 조작은 기능하지 않습니다.
/* 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* replace_char(char* str, char in, char out) {
char * p = str;
while(p != '\0') {
if(*p == in)
*p == out;
++p;
}
return str;
}
이것은 시마다 입니다.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'
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;
}
즉, 자체 억제 기능과 다기능성을 갖추고 있을 뿐만 아니라 효율적이며 재귀 때마다 필요에 따라 버퍼를 확장 또는 축소할 수 있습니다.
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);
}
}
}
string.h의 strlen만 사용합니다.
내 영어실력에 대해 미안해
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;
}
stren 코드가 string.h 호출을 회피하는 경우
int strlen(char * string){//use this code to avoid calling string.h
int lenght = 0;
while(string[lenght] != '\0'){
lenght++;
}
return lenght;
}
언급URL : https://stackoverflow.com/questions/779875/what-function-is-to-replace-a-substring-from-a-string-in-c
'programing' 카테고리의 다른 글
vuex 이름에서 mapState가 여러 모듈로 증가함 (0) | 2022.07.28 |
---|---|
Eclipse에서 Javadoc HTML 파일을 생성하는 방법은 무엇입니까? (0) | 2022.07.28 |
1.#의 기능INF00, -1.#IND00 및 -1.#IND는요? (0) | 2022.07.28 |
Windows가 fork()에 가장 가까운 것은 무엇입니까? (0) | 2022.07.28 |
C/C++ NaN 상수(리터럴) (0) | 2022.07.28 |