C删除两个字符之间的子字符串

oyxsuwqo  于 2023-01-12  发布在  其他
关注(0)|答案(4)|浏览(142)

我有两个字符串可以用char * 来指向:

char *s = "this is a string";
char *s = "this is a string [this is more string]";

我希望能够从char中移除括号和它们的内容(如果它们存在的话)。在C中做这件事的最好方法是什么?
谢谢!

lrpiutwd

lrpiutwd1#

首先,你必须访问允许你修改的内存。对于歇斯底里的葡萄干,C仍然允许你声明指向常量字符数组的指针为非常数......但是你仍然不能修改它们。
相反,声明一个由常量数据初始化的数组。

char s[] = "hello world";

这样就得到了一个11+1字符的可变数组(不可变源字符串的 * 副本 *)。
然而,我们常常希望能够在琴弦上工作,所以我们需要确保有足够的空间来演奏它们。

char s[100] = "hello world";  // string capacity == 99+1. In use == 11+1.
s[6] = '\0';              // now string contains "hello ". In use == 6+1.
strcat( s, "everyone" );  // now string contains "hello everyone". In use == 14+1.

要从字符串中 * 删除 * 内容,必须首先确定开始和结束的位置:

char s[] = "this is a string [this is more string] original string";
char * first = strchr( s, '[' );  // find the '['
char * last  = strchr( s, ']' );  // find the ']'
if (first and last)  // if both were found...
  // ...copy the end of the string over the part to be replaced
  memmove( first, last+1, strlen(last+1)+1 );
// s now contains "this is a string  original string"

注意到这里所有的+1了吗?请注意:

  • of where 您正在索引字符串(您希望从']'之后的 * 复制到字符串末尾)
  • 字符串必须以一个空终止符结束,即一个零值字符(我们也应该复制它,所以我们在strlen中添加了一个)。

记住,string只是一个字符数组,其中最后一个 used 字符后面紧跟一个零值字符(空终止符)。所有用于处理其他类型数组的方法都适用于处理字符串(AKA字符数组)。

cngwdvgl

cngwdvgl2#

这是那些"有趣"的问题之一,吸引了超过其份额的答案。
完全归功于其他人的回答,他们注意到试图修改"字符串字面量"会触发UB(字符串字面量通常存储在内存的一个 * 不可变 *"只读"区域中)(感谢@chux-reinstatemonica的澄清)。
下面的代码将把这一点带到下一个层次,它处理由一对分隔符('['&']')限定的多个区域,也处理 * nested * 示例。代码很简单,使用cut作为计数器,确保嵌套被考虑在内。假定源串是"良好形成的"。

#include <stdio.h>

int main( void ) {
    char *wb =
         "Once [upon] a [time] there [lived a] princess. "
         "She [ was [a hottie]]. The end.";
    char wo[100]; // big enough

    int cut = 0;
    size_t s = 0, d = 0; 

    for( ; wb[s]; s++ ) {
        cut += ( wb[s] == '[' ); // entering region to cut?
        if( !cut ) wo[ d++ ] = wb[ s ]; // not cutting, so copy
        cut -= ( wb[s] == ']' ); // exiting region that was cut?
        if( cut < 0 ) cut = 0; // in case of spurious ']'
    }
    wo[ d ] = '\0'; // terminate shortened string

    puts( wb );
    puts( wo );

    return 0;
}
Once [upon] a [time] there [lived a] princess. She [ was [a hottie]]. The end.
Once  a  there  princess. She . The end.

现在,删除输出阵列中的多个连续SP可能是一个小挑战。这可以非常容易地"动态"完成,并作为练习留下。
人们开始看到像这样的东西如何可以扩展到一个"中缀计算器程序"。总是有新的东西!

zengzsys

zengzsys3#

使用string.h中定义的strchnul函数

*(strchrnul(s, '[')) = '\0';

你可能需要定义_GNU_SOURCE宏,它不能处理字符串。

8dtrkrch

8dtrkrch4#

字符串是只读的,不应该被修改。试图修改一个字符串会导致未定义的行为。但是,它们 * 可以 * 用于初始化字符数组。

char s[] = "this is a string [this is more string]";

如果要删除括号和括号之间的字符,首先需要使用strchr确定字符串包含这两个字符。存储了这些指针后,可以使用strncpystrcat的指针算法创建一个新字符串,减去要排除的部分。

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

int main(void) {
    char s[] = "this is a string [this is more string] foo";
    char *start = NULL, *end = NULL;

    if ((start = strchr(s, '[')) == NULL 
        || (end = strchr(s, ']')) == NULL) {
        printf("Invalid string.\n");
        return 1;
    }

    char s2[strlen(s) + 1];

    size_t start_length = start - s;

    strncpy(s2, s, start_length);
    s2[start_length] = '\0';
    strcat(s2, &end[1]);

    printf(">%s<\n", s2);

    return 0;
}

输出:

>this is a string  foo<

或者,我们可以简单地通过从end指针+1复制到start指针来修改原始字符串。

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

int main(void) {
    char s[] = "this is a string [this is more string]";
    //char s2[strlen(s) + 1];

    char *start = NULL, *end = NULL;

    if ((start = strchr(s, '[')) == NULL 
        || (end = strchr(s, ']')) == NULL) {
        printf("Invalid string.\n");
        return 1;
    }

    strcpy(start, end+1);

    printf(">%s<\n", s);

    return 0;
}

进一步的改进是只查找开始字符 * 之后 * 的结束字符。

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

int main(void) {
    char s[] = "this is a string [this is more string]";
    //char s2[strlen(s) + 1];

    char *start = NULL, *end = NULL;

    if ((start = strchr(s, '[')) == NULL 
        || (end = strchr(start+1, ']')) == NULL) {
        printf("Invalid string.\n");
        return 1;
    }

    strcpy(start, end+1);

    printf(">%s<\n", s);

    return 0;
}

相关问题