我怎样才能调整这个算法来处理多次出现的关键字来修改? [英] How can I tweak this algorithm to deal with multiple occurrences of a keyword to modify?

查看:251
本文介绍了我怎样才能调整这个算法来处理多次出现的关键字来修改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想搜索所有出现的字符串(第一个参数),并在第一个字符串出现之前添加另一个字符串(第二个参数)。



理想情况下,我希望每一个 dime 被替换为 limedime
我已经设法做到这一点,但是,只有第一次出现这个词。
任何不是第一个的匹配字符串都没有被检测到,也没有做任何事情。另外,包含 dime 的多行可以根据前面所做的修改进行修改,这不是我想要的。



<这是我得到的一些示例输出:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ c>

会变成

 一些东西

如果我有这个

  dime 
notimportant!
毛钱
毛钱

我会得到

  limedime 
notimportant!
limelimedime
limelimelimedime

编辑:我修改了代码,使用 stdin 轻松测试,并且还包含 replace_str()

  #include< string.h> 
#include< stdio.h>
#include< stdlib.h>
$ b char * replace_str(char * str,char * orig,char * rep)
{
static char buffer [4096];
char * p; $!
$ b if(!(p = strstr(str,orig)))
return str;

strncpy(buffer,str,p-str);
buffer [p-str] ='\0';

sprintf(buffer +(p-str),%s%s,rep,p + strlen(orig));

返回缓冲区;


void replace(char * patternoo,char * replacearoo){

char buff [BUFSIZ]; //输入行
char newbuff [BUFSIZ]; //任何编辑的结果

char pattern [200];
strcpy(pattern,patternoo);

char替换[200];
strcpy(replace,replacearoo);

while(fgets(buff,BUFSIZ,stdin)!= NULL){
if(strstr(buff,pattern)!= NULL){
//这是我们的地方DO模式替换
strcpy(newbuff,replace_str(buff,pattern,strcat(replace,pattern)));

} else {
strcpy(newbuff,buff);
}
printf(%s,newbuff);


int main(){

replace(dime,lime);



$ b现在,我想这也许不是太好,因为我只是在看线?我不确定我能做什么,逐个阅读每个字符?这对我来说似乎有点多,但我不太确定。是否有任何快速和肮脏的方法来修复我当前的算法呢?或者我将不得不重新开始并采取一个全新的方法?

解决方案

鉴于您插入 lime 在每次出现角钱之前,你需要读一行,找到每一个角钱在输入缓冲区中,找到后将输入缓冲区的未处理部分复制到输出缓冲区,然后添加 lime ,然后添加 dime ,然后在毛钱之后继续搜索。



这意味着: p>

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

static void replace(char * pattern,char * replace)
{
char buff [BUFSIZ]; //输入行
char newbuff [BUFSIZ]; //任何编辑的结果
size_t replen = strlen(replace);
size_t patlen = strlen(pattern);

while(fgets(buff,BUFSIZ,stdin)!= NULL)
{
newbuff [0] ='\0';
char * dst = newbuff;
char * data = buff;
char * patt; ((patt = strstr(data,pattern))!= NULL)

{
memmove(dst,data,(patt - data));
dst + =(patt - data);
memmove(dst,replace,replen);
dst + =补充;
memmove(dst,pattern,patlen);
dst + = patlen;
data = patt + patlen;
}
* dst ='\0';
printf(%s%s,newbuff,data);


$ b $ int main(void)
{
replace(dime,lime);
返回0;



$ b $ p
$ b

代码很容易忽略输入行过长的扩展 - 你需要工作以确保它不会溢出输出缓冲区。由于您为每个角钱(4个字符)插入4个字符( lime ),最坏的情况是需要两倍的空间在输出中就像在输入中一样。所以,改变 newbuff [2 * BUFSIZ] 的大小将会处理这些溢出问题 - 对于你前缀的特定字符串。过长的输入线可能会导致错过。如果一个 dime 在两个缓冲区之间的边界被分开,它将被错过。



data (从你的问题炮制出来):

 东西

应该变成

东西limedime东西limedime东西

,如果我有这个

毛钱
不重要!
毛钱
毛钱毛钱
毛钱一角毛钱

我会得到石灰和硬币嘉豪:

limedime
不重要!
limeime
limedime limedime
limedime limedime limedime

运行程序( repstr ,我称之为):

  $ ./repstr<数据
东西limedime东西limedime东西东西

应该成为

东西limelimedime东西limelimedime东西东西

,如果我有这个

limedime
不重要!
limeime
limedime limedime
limedime limedime limedime

我会买石灰和limerimes嘉豪:

limelimedime
不重要!
limelimedime
limelimedime limelimedime
limelimedime limelimedime limelimedime
$


I would like to search for all occurrences of a string (first parameter) and have another string (second parameter) be added before all occurrences of the first string.

Ideally, I would like every occurrence of dime to be replaced with limedime. I have managed to do this, however, for only the first occurrence of the word. Any matching string which is not the first is not detected, and nothing is done. Also, multiple lines containing dime get modified based on modifications done on previous lines, which is not what I would like.

Here is some sample output that I get:

something dime something dime something something

will become

something limedime something dime something something

and if I have this

dime
notimportant!
dime
dime

I will get

limedime
notimportant!
limelimedime
limelimelimedime

EDIT: I've modified the code so you can easily test it with stdin, and have also included replace_str():

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

char *replace_str(char *str, char *orig, char *rep)
{
  static char buffer[4096];
  char *p;

  if(!(p = strstr(str, orig)))  
    return str;

  strncpy(buffer, str, p-str); 
  buffer[p-str] = '\0';

  sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));

  return buffer;
}

void replace(char* patternoo, char* replacearoo){

    char buff[BUFSIZ];      // the input line
    char newbuff[BUFSIZ];   // the results of any editing

    char pattern[200];
    strcpy(pattern, patternoo);

    char replace[200];
    strcpy(replace, replacearoo);

    while ( fgets( buff, BUFSIZ, stdin ) != NULL ) {
        if ( strstr( buff, pattern ) != NULL ) {
             //THIS IS WHERE WE DO pattern replacing    
                strcpy(newbuff, replace_str(buff, pattern, strcat(replace,pattern)));             

        } else {
              strcpy( newbuff, buff );
        }
          printf("%s", newbuff);
    }
}
int main(){

    replace("dime", "lime");
}

Now, I'm thinking that maybe this way isn't too great, since I'm only looking at lines? I'm not sure what I can do, read every character one by one? It seems a bit much to me, but I am not so sure. Is there any quick and dirty way to fix my current algorithm though? Or would I have to start over and take a whole new approach?

解决方案

Given that you insert lime before each occurrence of dime, you need to read a line, find each occurrence of dime in the input buffer, and when found, copy the unprocessed part of the input buffer to the output buffer, then add lime, then add dime, and then resume your search after the dime.

That translates to:

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

static void replace(char *pattern, char *replace)
{
    char buff[BUFSIZ];      // the input line
    char newbuff[BUFSIZ];   // the results of any editing
    size_t replen = strlen(replace);
    size_t patlen = strlen(pattern);

    while (fgets(buff, BUFSIZ, stdin) != NULL)
    {
        newbuff[0] = '\0';
        char *dst = newbuff;
        char *data = buff;
        char *patt;
        while ((patt = strstr(data, pattern)) != NULL)
        {
            memmove(dst, data, (patt - data));
            dst += (patt - data);
            memmove(dst, replace, replen);
            dst += replen;
            memmove(dst, pattern, patlen);
            dst += patlen;
            data = patt + patlen;
        }
        *dst = '\0';
        printf("%s%s", newbuff, data);
    }
}

int main(void)
{
    replace("dime", "lime");
    return 0;
}

The code blithely ignores the existence of over-long expansions of input lines — you need to work to make sure that it does not overflow the output buffer. Since you insert 4 characters (lime) for each dime (4 characters), at worst you need twice as much space in the output as there is in the input. So, changing the size of newbuff[2 * BUFSIZ] would deal with those overflow problems — for the specific strings you're prefixing. Overlong input lines could cause misses too. If a dime was split across the boundary between two buffers full, it would be missed.

Given a file called data (concocted from your question):

something dime something dime something something

    should become

something limedime something limedime something something

    and if I have this

dime
not important!
dime
dime dime
dime dime dime

    I will get limes and dimes galore:

limedime
not important!
limedime
limedime limedime
limedime limedime limedime

The output from running the program (repstr, I called it) is:

$ ./repstr < data
something limedime something limedime something something

    should become

something limelimedime something limelimedime something something

    and if I have this

limedime
not important!
limedime
limedime limedime
limedime limedime limedime

    I will get limes and limedimes galore:

limelimedime
not important!
limelimedime
limelimedime limelimedime
limelimedime limelimedime limelimedime
$

这篇关于我怎样才能调整这个算法来处理多次出现的关键字来修改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆