C语言如何剪切字符串的一部分

C语言如何剪切字符串的一部分,c,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以获得以下输出: #Line

假设我有一个字符串,其中包含以下文本:

#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
的所有内容,实质上删除了整个第三行)

我已经读到,这可以通过函数
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

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


使用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;
}
#包括
#包括
#包括
煤焦*
strfilter(常量字符*str,常量字符*substr)
{
char*res=strdup(str),*ptr=NULL;
尺寸长度=0;
如果(!res)
返回NULL;
ptr=strstrstr(res,substr);
如果(!ptr)
{
免费(res);
返回NULL;
}
len=strlen(ptr)-strlen(substr);
memmove(ptr、ptr+strlen(substr)、len);
memset(ptr+len,0,strlen(ptr+len));
返回res;
}
煤焦*
strfilter2(常量字符*str,常量字符*start,常量字符*end)
{
char*res=strdup(str),*ptr1=NULL,*ptr2=NULL,*tmp=NULL;
大小_t len1=0,len2=0;
如果(!res)
返回NULL;
ptr1=strstr(res,启动);
ptr2=strstrstr(res,end);
如果(!ptr1 | |!ptr2)
返回NULL;
如果(ptr1>ptr2)
{
tmp=ptr2;
ptr2=ptr1;
ptr1=tmp;
tmp=结束;
结束=开始;
启动=tmp;
}
len1=strlen(开始);
len2=strlen(ptr2);
memmove(ptr1+len1、ptr2、len2);
memset(ptr1+len1+len2,0,strlen(ptr1+len1+len2));
返回res;
}
int
主(空)
{
const char*str=“你好,今天我晚餐吃了3块饼干\n”
“午餐吃4块饼干和一些汤。\n”
“明天的早餐,我打算吃\n”
“培根、鸡蛋和火腿。\n”;
char*res=strfilter2(str,“午餐吃4块饼干和一些汤。\n”、“培根、鸡蛋和火腿。\n”);
如果(!res)
{
perror(“strfilter2()”);
返回1;
}
卖出(res);
免费(res);
返回0;
}
该函数只查找要删除的子字符串,并用其后的所有内容覆盖它,然后将字符串的其余部分归零

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

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

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;
}


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

我认为如果您将代码包括在内,阅读会更好,我们可能会指出您的错误。请稍候。我没有包含任何内容的原因是,我所拥有的内容实际上是无关紧要的,但请稍候。我如何修改它,使其不剪切整行内容,而是剪切两个子字符串之间的所有内容?就我所做的而言,我不一定知道整条路线。尝试strfilter2。尝试“开始”和“艺术”作为
start
end
:)如果结束标记在开始标记之前怎么办?