C删除字符串中的字符

发布于 2025-01-17 18:09:51 字数 477 浏览 6 评论 0原文

现在,我正在使用此代码在字符串中删除一些字符。

void eliminate(char *str, char ch){
    for(; *str != '\0';str++){
        if(*str == ch){
            strcpy(str, str+1);
            str--;
        }
    }
}

在char *str中,有一些字符串,例如

“ sll $ 6,$ 5,16”

在删除“ $”后,字符串看起来像这样。

“ SLL 6、5、16”

但在删除”,“”字符串变得非常奇怪。

“ SLL 6 5 6”

上面的代码有任何问题吗?而且,它仅发生在Linux和在线GDB中。我的窗口笔记本电脑中的VS代码很好地消除了目标char。

Now I'm using this code to delete some char in a string.

void eliminate(char *str, char ch){
    for(; *str != '\0';str++){
        if(*str == ch){
            strcpy(str, str+1);
            str--;
        }
    }
}

In the char *str there are some strings like

"sll $6, $5, 16"

After deleting "$", the string looks like this.

"sll 6, 5, 16"

But after deleting ",", the string became very strange.

"sll 6 5 6"

Is there any problem with the code above? And also, it only happens in Linux and online GDB. VS code in my window laptop eliminates the targeted char very well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海夜未眠 2025-01-24 18:09:52

对于使用函数strcpy进行重叠字符串的初学者,如本语句中的重叠字符串

strcpy(str, str+1);

会调用未定义的行为。

从C标准(7.23.2.3 strcpy函数)

2 strcpy函数复制字符串指向S2(包括
终止null字符)到S1指向的阵列中。 如果
复制发生在重叠的对象之间,行为是
未定义。

此语句

str--;

当删除字符是字符串的第一个字符时也可以调用未定义的行为。

关于函数声明的一些评论。

这样的功能应遵循C标准字符串功能的一般约定,并返回指针到结果字符串。

另一个一般惯例是,此类功能不检查传递的指针是否等于null。将有效的指针传递给字符串是该功能用户的责任。

同样,如果用户将传递'\ 0'作为要删除的字符,则该函数将对源字符串无能为力,然后将其返回。

这是一个演示程序,该程序显示如何声明和定义该函数。

#include <stdio.h>

char * eliminate( char *s, char c )
{
    if ( c != '\0' )
    {
        char *src = s, *dsn = s;

        do
        {
            if ( *src != c )
            {
                if ( dsn != src ) *dsn = *src;
                ++dsn;
            }
        } while ( *src++ );
    }

    return s;
}

int main( void )
{
    char s[] = "sll     $6, $5, 16";

    printf( "\"%s\"\n", eliminate( s, '

程序输出是

"sll     6, 5, 16"
) ); }

程序输出是

For starters using the function strcpy for overlapping strings as in this statement

strcpy(str, str+1);

invokes undefined behavior.

From the C Standard (7.23.2.3 The strcpy function)

2 The strcpy function copies the string pointed to by s2 (including
the terminating null character) into the array pointed to by s1. If
copying takes place between objects that overlap, the behavior is
undefined.

This statement

str--;

also can invoke undefined behavior when the deleted character is the first character of the string.

Some remarks about the function declaration.

Such a function should follow the general convention of C standard string functions and return pointer to the result string.

Another general convention is that such functions do not check whether the passed pointer is equal to NULL. It is the responsibility of the user of the function to pass a valid pointer to a string.

Also if the user will pass '\0' as the character to be deleted then the function shall do nothing with the source string and just return it.

Here is a demonstration program that shows how the function can be declared and defined.

#include <stdio.h>

char * eliminate( char *s, char c )
{
    if ( c != '\0' )
    {
        char *src = s, *dsn = s;

        do
        {
            if ( *src != c )
            {
                if ( dsn != src ) *dsn = *src;
                ++dsn;
            }
        } while ( *src++ );
    }

    return s;
}

int main( void )
{
    char s[] = "sll     $6, $5, 16";

    printf( "\"%s\"\n", eliminate( s, '

The program output is

"sll     6, 5, 16"
) ); }

The program output is

分開簡單 2025-01-24 18:09:51

正如注释中指出的那样strcpy()在用重叠的内存块来应对数据时,这是不安全的。 memmove(DST,SRC,LEN)是使用辅助缓冲区的替代方案,如果src&amp; DST内存重叠。

您可以简单地跳过角色以消除循环:

#include <stdio.h>

void drop_char (char *str, char ch) {
    if (!str) return;

    for(char* cp = str; 1 ; ) {
        if(*cp != ch)
            *str++ = *cp;
        if ('\0' == *cp++)
            break;
    }
}

int main () {
    char str [] = "sll     $6, $5, 16";
    printf ("Original   : [%s]", str);

    drop_char(str, '
);
    printf ("\nDropping $ : [%s]", str);

    drop_char(str, ',');
    printf ("\nDropping , : [%s]", str);

    printf ("\n");

    return 0;
}

As pointed out in comments strcpy() is not safe when coping data with overlapping memory blocks. memmove(dst, src, len) is the alternative which uses an auxiliary buffer in case of src & dst memory overlaps.

You can simply skip the character to eliminate in a loop:

#include <stdio.h>

void drop_char (char *str, char ch) {
    if (!str) return;

    for(char* cp = str; 1 ; ) {
        if(*cp != ch)
            *str++ = *cp;
        if ('\0' == *cp++)
            break;
    }
}

int main () {
    char str [] = "sll     $6, $5, 16";
    printf ("Original   : [%s]", str);

    drop_char(str, '
);
    printf ("\nDropping $ : [%s]", str);

    drop_char(str, ',');
    printf ("\nDropping , : [%s]", str);

    printf ("\n");

    return 0;
}
猫瑾少女 2025-01-24 18:09:51

在不使用显式指针数学的情况下,我们可以在迭代输入字符串时使用两个索引。 i 是每次迭代都会递增的索引,而 j 仅在找不到目标字符时递增。

void drop_char(char *str, char ch) {
    size_t i = 0, j = 0;    

    for (; str[i]; ++i) {
        if (str[i] != ch) 
            str[j++] = str[i];
    }

    str[j] = '\0';
}

如果我们有字符串 char test[] = "hello" 并调用 drop_char(test, 'l') 过程如下所示:

i = 0, j = 0
char: 'h'
'h' != 'l'
test[0] = 'h'

i = 1, j = 1
char: 'e'
'e' != 'l'
test[1] = 'e'

i = 2, j = 2
char: 'l'
'l' == 'l'

i = 3, j = 2
char: 'l'
'l' == 'l'

i = 4, j = 2
char: 'o'
'o' != 'l'
test[2] = 'o'

i = 5, j = 3
test[3] = '\0'

Without using explicit pointer math, we can use two indices as we iterate over the input string. i is an index with increments on each iteration, and j which only increments when the target character is not found.

void drop_char(char *str, char ch) {
    size_t i = 0, j = 0;    

    for (; str[i]; ++i) {
        if (str[i] != ch) 
            str[j++] = str[i];
    }

    str[j] = '\0';
}

If we have the string char test[] = "hello" and call drop_char(test, 'l') the process looks like:

i = 0, j = 0
char: 'h'
'h' != 'l'
test[0] = 'h'

i = 1, j = 1
char: 'e'
'e' != 'l'
test[1] = 'e'

i = 2, j = 2
char: 'l'
'l' == 'l'

i = 3, j = 2
char: 'l'
'l' == 'l'

i = 4, j = 2
char: 'o'
'o' != 'l'
test[2] = 'o'

i = 5, j = 3
test[3] = '\0'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文