Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的就地字符串替换_C_Algorithm_String Algorithm - Fatal编程技术网

C语言中的就地字符串替换

C语言中的就地字符串替换,c,algorithm,string-algorithm,C,Algorithm,String Algorithm,写一个函数 void inplace(char *str, const char pattern, const char* replacement, size_t mlen) 输入: str:以\0结尾的字符串。输入表明我们需要一个就地算法 图案:一个字母 替换:字符串 mlen:内存大小包含字符串str从内存的开头开始,并且mlen应该大于strlen(str) 最后的结果仍然由str指出 请注意,应替换所

写一个函数

void inplace(char *str, 
             const char pattern, 
             const char* replacement, 
             size_t mlen)
输入:
str
:以
\0
结尾的字符串。输入表明我们需要一个就地算法

图案
:一个字母

替换
:字符串

mlen
:内存大小包含字符串
str
从内存的开头开始,并且
mlen
应该大于
strlen(str)


最后的结果仍然由
str
指出

请注意,应替换所有出现的图案

比如说,

helelo\0……….

这里的“helelo”是要在末尾替换为
'\0'
的字符串。
'\0'
之后仍然有L个有效字节。我们想用“123”代替“e”

一种简单的方法是这样的,我们通过
str
,当一个模式匹配时,我们用替换字符串填充剩余的位置,然后用替换字符串替换模式


如果原始字符串的长度为
n
,并且只包含
e
,则需要
(n-1)+(n-2)+……+1
轮班

是否有一种算法只扫描一次字符串,且内存消耗恒定


我想至少要通过两次。在第一次传递时,计算将被替换的字符数。给定
count
和替换字符串的长度,可以计算最终字符串的长度。(您应该验证它是否适合缓冲区。)

在第二步中,向后扫描字符串(从最后一个字符开始),将字符复制到其最终位置。遇到搜索字符时,将替换字符串复制到该位置

在您的示例中,长度增加为2。你会的

copy str[5] which is '\0' to str[7]
copy str[4] which is 'o' to str[6]
copy str[3] which is 'l' to str[5]
copy str[2] which is 'l' to str[4]
at str[1] you find the 'e' so str[3]='3' str[2]='2' str[1]='1'
此时,输出索引与输入索引相同,因此可以中断循环



正如@chux在注释中指出的,替换字符串为空或只有一个字符的情况可以通过向前传递字符串来处理。因此,代码应该分别处理这些情况。

我认为至少两次通过。在第一次传递时,计算将被替换的字符数。给定
count
和替换字符串的长度,可以计算最终字符串的长度。(您应该验证它是否适合缓冲区。)

在第二步中,向后扫描字符串(从最后一个字符开始),将字符复制到其最终位置。遇到搜索字符时,将替换字符串复制到该位置

在您的示例中,长度增加为2。你会的

copy str[5] which is '\0' to str[7]
copy str[4] which is 'o' to str[6]
copy str[3] which is 'l' to str[5]
copy str[2] which is 'l' to str[4]
at str[1] you find the 'e' so str[3]='3' str[2]='2' str[1]='1'
此时,输出索引与输入索引相同,因此可以中断循环



正如@chux在注释中指出的,替换字符串为空或只有一个字符的情况可以通过向前传递字符串来处理。因此,代码应该分别处理这些情况。

一个候选单通道解决方案

对于
str
中的每个字符,递归。在递归之后,进行替换

它确实会反复出现

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

// return 0:success else 1:fail
static int inplace_help(char *dest, const char *src, int pattern,
        const char* replacement, size_t rlen, size_t mlen) {
  printf("'%p' '%s' %c\n", dest, src, pattern);
  if (*src == pattern) {
    if (rlen > mlen) return 1;
    if (inplace_help(dest + rlen, src + 1, pattern, replacement, rlen,
            mlen - rlen)) return 1;
    memcpy(dest, replacement, rlen);
    return 0;
  }
  if (mlen == 0) return 1;
  int replace1 = *src;
  if (*src) {
    if (inplace_help(dest + 1, src + 1, pattern, replacement, rlen, mlen - 1)) {
      return 1;
    }
  }
  *dest = replace1;
  return 0;
}

void inplace(char *str, const char pattern, const char* replacement,
        size_t mlen) {
  if (pattern == 0) return;
  if (mlen == 0) return;
  if (*replacement == 0) return;  // Insure str does not shrink.
  inplace_help(str, str, pattern, replacement, strlen(replacement), mlen - 1);
}

int main(void) {
  char str[1000] = "eeeeec";
  inplace(str, 'e', "1234", sizeof str);
  printf("'%s'\n", str);  // --> '12341234123412341234c'
  return 0;
}
#包括
#包括
#包括
#包括
//返回0:成功,否则返回1:失败
静态int就地帮助(char*dest,const char*src,int模式,
常量字符*替换,大小,大小){
printf(“%p”%s“%c\n”,dest,src,pattern);
如果(*src==模式){
如果(rlen>mlen)返回1;
if(就地)帮助(目的地+rlen,src+1,模式,更换,rlen,
mlen-rlen)返回1;
memcpy(目的地、替换、rlen);
返回0;
}
如果(mlen==0)返回1;
int replace1=*src;
如果(*src){
if(就地帮助(目的地+1、src+1、模式、替换、rlen、mlen-1)){
返回1;
}
}
*dest=replace1;
返回0;
}
就地无效(字符*str、常量字符模式、常量字符*替换、,
尺寸(mm){
如果(模式==0)返回;
如果(mlen==0)返回;
if(*replacement==0)返回;//确保str不收缩。
就地帮助(str、str、模式、替换、strlen(替换)、mlen-1);
}
内部主(空){
字符str[1000]=“eeeee c”;
就地(str,'e','1234',str尺寸);
printf(“%s”\n,str);//-->“123412344123412344c”
返回0;
}

一个候选单通道解决方案

对于
str
中的每个字符,递归。在递归之后,进行替换

它确实会反复出现

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

// return 0:success else 1:fail
static int inplace_help(char *dest, const char *src, int pattern,
        const char* replacement, size_t rlen, size_t mlen) {
  printf("'%p' '%s' %c\n", dest, src, pattern);
  if (*src == pattern) {
    if (rlen > mlen) return 1;
    if (inplace_help(dest + rlen, src + 1, pattern, replacement, rlen,
            mlen - rlen)) return 1;
    memcpy(dest, replacement, rlen);
    return 0;
  }
  if (mlen == 0) return 1;
  int replace1 = *src;
  if (*src) {
    if (inplace_help(dest + 1, src + 1, pattern, replacement, rlen, mlen - 1)) {
      return 1;
    }
  }
  *dest = replace1;
  return 0;
}

void inplace(char *str, const char pattern, const char* replacement,
        size_t mlen) {
  if (pattern == 0) return;
  if (mlen == 0) return;
  if (*replacement == 0) return;  // Insure str does not shrink.
  inplace_help(str, str, pattern, replacement, strlen(replacement), mlen - 1);
}

int main(void) {
  char str[1000] = "eeeeec";
  inplace(str, 'e', "1234", sizeof str);
  printf("'%s'\n", str);  // --> '12341234123412341234c'
  return 0;
}
#包括
#包括
#包括
#包括
//返回0:成功,否则返回1:失败
静态int就地帮助(char*dest,const char*src,int模式,
常量字符*替换,大小,大小){
printf(“%p”%s“%c\n”,dest,src,pattern);
如果(*src==模式){
如果(rlen>mlen)返回1;
if(就地)帮助(目的地+rlen,src+1,模式,更换,rlen,
mlen-rlen)返回1;
memcpy(目的地、替换、rlen);
返回0;
}
如果(mlen==0)返回1;
int replace1=*src;
如果(*src){
if(就地帮助(目的地+1、src+1、模式、替换、rlen、mlen-1)){
返回1;
}
}
*dest=replace1;
返回0;
}
就地无效(字符*str、常量字符模式、常量字符*替换、,
尺寸(mm){
如果(模式==0)返回;
如果(mlen==0)返回;
if(*replacement==0)返回;//确保str不收缩。
就地帮助(str、str、模式、替换、strlen(替换)、mlen-1);
}
内部主(空){
字符str[1000]=“eeeee c”;
就地(str,'e','1234',str尺寸);
printf(“%s”\n,str);//-->“123412344123412344c”
返回0;
}

以下假设分配给字符串的内存在某个时间点已初始化为某个内容,因为标准C似乎不允许访问未初始化的内存。在实践中,它会很好地工作。