C语言如何删除字符串

时间:2016-02-14 00:19:37

标签: c

假设我有一个包含以下文字的字符串:

#Line1 Hello, today I ate 3 crackers for dinner
#Line2 and 4 crackers with some soup for lunch.
#Line3 For breakfast tomorrow, I plan on eating
#Line4 bacon, eggs, and ham.

我希望将字符串的一部分从一个子字符串剪切到另一个子字符串,例如从"#Line3"\n以获得以下输出:

#Line1 Hello, today I ate 3 crackers for dinner
#Line2 and 4 crackers with some soup for lunch.
#Line4 bacon, eggs, and ham.

(基本上从#Line3\n基本上删除了所有内容,实质上删除了整个第3行)

我已经读过这可以通过函数memmove来完成,但是无法弄清楚如何正确地这样做。但是,如果有人有一个不涉及memmove的解决方案,当然这同样值得赞赏。

这是我到目前为止所拥有的:

int str_cut(char *str, char *begin, int len)
{
    int l = strlen(str);
    if (strlen(begin) + len > l) len = l - begin;
    memmove(str + strlen(begin), str + begin + len, l - len + 1);
    return len;
}

到目前为止,完成我想要的东西还远远不够,因为它取决于知道需要剪切的长度以及我想要它做的是在两个字符之间剪切,以配合我之前的例子切断“line3”和\n

之间的所有内容

3 个答案:

答案 0 :(得分:0)

使用memcpy,您可以将两个部分复制到两个缓冲区中,然后使用strcat连接它们。

Get a substring of a char*

答案 1 :(得分:0)

使用memmove非常简单:

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

char *
strfilter(const char *str, const char *substr)
{
    char *res = strdup(str), *ptr = NULL;
    size_t len = 0;

    if (!res)
        return NULL;

    ptr = strstr(res, substr);

    if (!ptr)
    {
        free(res);
        return NULL;
    }

    len = strlen(ptr) - strlen(substr);
    memmove(ptr, ptr + strlen(substr), len);
    memset(ptr + len, 0, strlen(ptr + len));

    return res;
}

char *
strfilter2(const char *str, const char *start, const char *end)
{
    char *res = strdup(str), *ptr1 = NULL, *ptr2 = NULL, *tmp = NULL;
    size_t len1 = 0, len2 = 0;

    if (!res)
        return NULL;

    ptr1 = strstr(res, start);
    ptr2 = strstr(res, end);

    if (!ptr1 || !ptr2)
        return NULL;

    if (ptr1 > ptr2)
    {
        tmp = ptr2;
        ptr2 = ptr1;
        ptr1 = tmp;
        tmp = end;
        end = start;
        start = tmp;
    }

    len1 = strlen(start);
    len2 = strlen(ptr2);
    memmove(ptr1 + len1, ptr2, len2);
    memset(ptr1 + len1 + len2, 0, strlen(ptr1 + len1 + len2));

    return res;
}

int
main(void)
{
    const char *str = "Hello, today I ate 3 crackers for dinner\n"
                      "and 4 crackers with some soup for lunch.\n"
                      "For breakfast tomorrow, I plan on eating\n"
                      "bacon, eggs, and ham.\n";
    char *res = strfilter2(str, "and 4 crackers with some soup for lunch.\n", "bacon, eggs, and ham.\n");

    if (!res)
    {
        perror("strfilter2()");
        return 1;
    }

    puts(res);
    free(res);

    return 0;
}

该函数只是找到你要删除的子字符串,并用它后面的所有内容覆盖它,然后它将字符串的其余部分清零。

编辑: 添加了strfilter2以消除两个子串之间的内容。

答案 2 :(得分:0)

要剪切出你需要找到的字符串的一部分 - 当然 - 首先要剪切的部分的开始和结束标记。为此,您可以使用strstr.然后将剩余部分(结束标记后的所有内容)复制到找到开始标记的位置:

char * cut_between(
  char * const str,
  char const * const from,
  char const * const to) {
  char * const startMark = strstr(str, from);
  if (! startMark) {
    return NULL;
  }
  char * const endMark =
    strstr(startMark+strlen(from), to);
  if (endMark) {
    strcpy(startMark, endMark+strlen(to));
    return startMark + strlen(startMark) + 1;
  } else {
    *startMark = '\0';
    return startMark + 1;
  }
}

成功时,上面的函数返回超出结果字符串末尾的指针。这对于缓冲区压缩非常有用,例如:

int main() {
  char * const input = malloc(400);
  fgets(input, 400, stdin);
  char const * const end =
    cut_between(input, "from", "to");
  if (end) {
    char const * const result =
      realloc(input, end - input);
    puts(result);
    // OMG missing free(s), well ... OK for this simple test.
  }
  return 0;
}

(Live on ideone)

请注意上述测试中缺少的错误检查。在生产代码中,必须添加这些代码。