【问题标题】:Removing substring from a string?从字符串中删除子字符串?
【发布时间】:2011-01-28 21:46:08
【问题描述】:

我有一个 C 函数,它接受一个名为 'buffer' 的字符串并对其进行解析,它将匹配关键字并使用它在结构中分配值。

但是,我想完全忽略一些关键字。

此程序解析 VCard 文件(.vcf,虚拟名片)。

这是一个可能提供的示例行缓冲区:

FN;CHARSET=UTF-8:David Celery

FN是我感兴趣的关键字,David Celery是与FN关联的值。

但是,我根本不关心 CHARSET=UTF-8。

所以我的问题是,有没有办法让我扫描我的缓冲区并简单地将“CHARSET=UTF-8”替换为“”,这样我就不必担心解析它(以及其他类似的关键字我只是想忽略)。

谢谢,

【问题讨论】:

  • 到目前为止你尝试过什么?如果你在 C 语言中处理字符串,而你不能做这么基本的事情,那么我建议你考虑使用内置字符串支持的语言(例如 C++、Java、C#、Python、Delphi 等)

标签: c string


【解决方案1】:

看看一个简单的 ANSI C 解决方案,例如:

void removeSubstring(char *s,const char *toremove)
{
  while( s=strstr(s,toremove) )
    memmove(s,s+strlen(toremove),1+strlen(s+strlen(toremove)));
}

【讨论】:

  • 我在尝试使用此代码时收到警告和段错误。某处有错误吗?如果重要的话,我正在使用 c99。
  • 如果你存储了strlen(toremove),效率会更高——每个循环不需要确定两次。
  • 性能不是问题;此代码也适用于更多情况,我认为这是您或您的编译器问题
  • @user411313。我同意 ThiefMaster 的观点,手册中充满了糟糕的例子。为什么不在这里发布更高效、更干净的代码。它甚至可能使您的答案成为更好的投票目标。
  • @user411313 @ThiefMaster:其实没关系——不管strlen调用是否被缓存,它仍然是一个O(mn^2)算法。最好使用 O(mn) 算法,但它有点复杂。
【解决方案2】:

别人有一个 C 字符串查找和替换函数,您可能会发现它很有用 here

编辑:根据评论请求,包含来自下面链接的代码 sn-p

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
 * Description:
 *   Find and replace text within a string.
 *
 * Parameters:
 *   src  (in) - pointer to source string
 *   from (in) - pointer to search text
 *   to   (in) - pointer to replacement text
 *
 * Returns:
 *   Returns a pointer to dynamically-allocated memory containing string
 *   with occurences of the text pointed to by 'from' replaced by with the
 *   text pointed to by 'to'.
 */
char *replace(const char *src, const char *from, const char *to)
{
   /*
    * Find out the lengths of the source string, text to replace, and
    * the replacement text.
    */
   size_t size    = strlen(src) + 1;
   size_t fromlen = strlen(from);
   size_t tolen   = strlen(to);
   /*
    * Allocate the first chunk with enough for the original string.
    */
   char *value = malloc(size);
   /*
    * We need to return 'value', so let's make a copy to mess around with.
    */
   char *dst = value;
   /*
    * Before we begin, let's see if malloc was successful.
    */
   if ( value != NULL )
   {
      /*
       * Loop until no matches are found.
       */
      for ( ;; )
      {
         /*
          * Try to find the search text.
          */
         const char *match = strstr(src, from);
         if ( match != NULL )
         {
            /*
             * Found search text at location 'match'. :)
             * Find out how many characters to copy up to the 'match'.
             */
            size_t count = match - src;
            /*
             * We are going to realloc, and for that we will need a
             * temporary pointer for safe usage.
             */
            char *temp;
            /*
             * Calculate the total size the string will be after the
             * replacement is performed.
             */
            size += tolen - fromlen;
            /*
             * Attempt to realloc memory for the new size.
             */
            temp = realloc(value, size);
            if ( temp == NULL )
            {
               /*
                * Attempt to realloc failed. Free the previously malloc'd
                * memory and return with our tail between our legs. :(
                */
               free(value);
               return NULL;
            }
            /*
             * The call to realloc was successful. :) But we'll want to
             * return 'value' eventually, so let's point it to the memory
             * that we are now working with. And let's not forget to point
             * to the right location in the destination as well.
             */
            dst = temp + (dst - value);
            value = temp;
            /*
             * Copy from the source to the point where we matched. Then
             * move the source pointer ahead by the amount we copied. And
             * move the destination pointer ahead by the same amount.
             */
            memmove(dst, src, count);
            src += count;
            dst += count;
            /*
             * Now copy in the replacement text 'to' at the position of
             * the match. Adjust the source pointer by the text we replaced.
             * Adjust the destination pointer by the amount of replacement
             * text.
             */
            memmove(dst, to, tolen);
            src += fromlen;
            dst += tolen;
         }
         else /* No match found. */
         {
            /*
             * Copy any remaining part of the string. This includes the null
             * termination character.
             */
            strcpy(dst, src);
            break;
         }
      }
   }
   return value;
}
void test(const char *source, const char *search, const char *repl)
{
   char *after;
   after = replace(source, search, repl);
   printf("\nsearch = \"%s\", repl = \"%s\"\n", search, repl);
   if ( after != NULL )
   {
      printf("after  = \"%s\"\n", after);
      free(after);
   }
}
int main(void)
{
   const char before[] = "the rain in Spain falls mainly on the plain";
   printf("before = \"%s\"\n", before);
   test(before, "the", "THEE");
   test(before, "the", "A");
   test(before, "cat", "DOG");
   test(before, "plain", "PLANE");
   test(before, "ain", "AINLY");
   return 0;
}
/* my output
before = "the rain in Spain falls mainly on the plain"
search = "the", repl = "THEE"
after  = "THEE rain in Spain falls mainly on THEE plain"
search = "the", repl = "A"
after  = "A rain in Spain falls mainly on A plain"
search = "cat", repl = "DOG"
after  = "the rain in Spain falls mainly on the plain"
search = "plain", repl = "PLANE"
after  = "the rain in Spain falls mainly on the PLANE"
search = "ain", repl = "AINLY"
after  = "the rAINLY in SpAINLY falls mAINLYly on the plAINLY"
*/

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    查看 string.h 中的方法。

    示例:(在 CodePad 上)

    #include <string.h>
    #include <stdio.h>
    #include <stddef.h>
    
    int main()
    {
        const char * source = "FN;CHARSET=UTF-8:David Celery";
        const char * newBegin = strrchr(source, ':');
        if (!newBegin)
        {
            puts("Error!");
            return -1;
        }
        newBegin++;
        puts(newBegin);
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      您可以忽略它们,而不是删除它们,例如:

      #define KEY_TO_IGNORE "CHARSET=UTF-8"
      
      char key[80];
      char value[80];
      char *text = "FN;CHARSET=UTF-8:David Celery";
      
      sscanf(text, "%2s;" KEY_TO_IGNORE ":%s", key, value);
      
      printf("key: %s, value: %s\n", key, value);
      

      【讨论】:

      • 我认为我们并没有试图解决世界上所有的问题,只是给出方法的建议,但是 YMMV。
      猜你喜欢
      • 2019-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2021-06-24
      • 2014-08-17
      相关资源
      最近更新 更多