修剪掉字符串上的字符?

问题描述

我需要一个C函数,该函数需要一个字符串(分配在堆栈上,而不是堆上),该字符串在正面和背面可能具有相同的字符;我要剪裁那些字符。我可能不知道有多少个页眉/页脚字符,也不一定总是知道有问题的字符。

换句话说,如果我的原始字符串是:

xxxThis is a string.xxxx

...然后我想要...

This is a string.

返回。理想情况下,我会喜欢这样的解决方案:

char str1[50] = “xxxThis is a string.xxxx”;
str1 = trimString( str1 );
printf(“Returned string is:: %s\n”,str1);       // prints “This is a string.”

这是我的代码:

char* trimString( char* str1,char x ){
        int i = 0;
        int j = (int)strlen( str1 ) - 1;
        printf("string is :: >>%s<<\n",str1);
        while( str1[i] == x ){
                i++;
        }
        while( str1[j] == x ){
                j--;
        }

        str1 = strncpy( str1,str1+i,(j-i) );

        return str1;
}


int main(){

        char str1[50] = "xxxThis is a string.xxxx";
        str1[25] = '\0';
        printf("%s\n",trimString( str1,'x' ) );
        printf("END OF PROGRAM.\n");
        return 0;
}

以下是输出:

This is a stringing.xxxx
END OF PROGRAM.

有两个明显的问题。首先,我认为我正确地去除了'x'字符,但是当我将修剪后的字符串复制回“ str1”变量时,我只会用新字符串覆盖旧字符串的前n个字符。原始字符串的其余部分仍然存在。

更严重的是,我并没有达到像这样调用此函数的目标:

str1 = trimString( str1,‘x’ );

我可以用类似这样的方式调用我的函数:

char tmpStr[50] = trimString( str1,‘x’ );
memcpy( str1,tmpStr );

但这很痛苦,现在我不得不担心临时字符串的大小。另外,我认为我必须多次调用trimString(),所以如果我能用一行代码来执行而不必担心管理临时字符串等,那将是很棒的。>

有什么建议或建议吗?

解决方法

您在这里。

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

char * trimString( char *s,char c )
{
    size_t i = 0;
    
    while ( s[i] == c ) i++;
    
    size_t n = strlen( s + i );
    
    while ( n && s[n + i - 1] == c ) --n;
    
    s[n + i] = '\0';
    
    if ( i != 0 )
    {
        memmove( s,s + i,n + 1 );
    }
    
    return s;
}

int main(void) 
{
    char s[50] = "xxxThis is a string.xxxx";
    
    puts( s );
    puts( trimString( s,'x' ) );
    
    return 0;
}

程序输出为

xxxThis is a string.xxxx
This is a string.

对于您的函数实现,然后它可以在例如用户传递空字符串时调用未定义的行为。在这种情况下,变量j的值可以为负

    int j = (int)strlen( str1 ) - 1;
    

并使用此负值,该函数将访问字符数组之外的内存。

    while( str1[j] == x ){
            j--;
    }

此外,无法检查j的当前值是否等于或小于0。

此外,您可能无法使用函数strncpy

str1 = strncpy( str1,str1+i,(j-i) );

无论如何,此调用都会忘记复制终止零。

请注意,只有在i不等于0的情况下,才需要在字符数组内移动字符串。否则就足以正确设置终止零。

为使功能更安全,您可以在函数内检查所传递的字符(第二个参数)是否等于零。

例如

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

char * trimString( char *s,char c )
{
    if ( c != '\0' )
    {
        size_t i = 0;
    
        while ( s[i] == c ) i++;
    
        size_t n = strlen( s + i );
    
        while ( n && s[n + i - 1] == c ) --n;
    
        s[n + i] = '\0';
    
        if ( i != 0 )
        {
            memmove( s,n + 1 );
        }
    }
    
    return s;
}

int main(void) 
{
    char s[50] = "xxxThis is a string.xxxx";
    
    puts( s );
    puts( trimString( s,'x' ) );
    
    return 0;
}
,

您需要在移位的字符串的末尾添加一个空终止符。

您还需要使用memmove()代替strncpy(),因为后者不允许在重叠的字符串之间进行复制。

要复制的长度出现一个错误的错误。

#include <stdio.h>
#include <memory.h>

char* trimString( char* str1,char x ){
    int i = 0;
    int j = (int)strlen( str1 ) - 1;
    printf("string is :: >>%s<<\n",str1);
    while( str1[i] == x ){
        i++;
    }
    while( str1[j] == x ){
        j--;
    }

    memmove( str1,(j-i+1) );
    str1[j - i + 1] = '\0'; // add null terminator

    return str1;
}

int main(){

    char str1[50] = "xxxThis is a string.xxxx";
    str1[25] = '\0';
    printf("%s\n",trimString( str1,'x' ) );
    printf("END OF PROGRAM.\n");
    return 0;
}

你不能做

str1 = trimString(...);

因为您不能分配给数组。您所能做的就是修改其内容。

由于该函数修改了给定的数组,因此不需要分配。您可以这样写:

trimString(str1,'x');
printf("%s\n",str1);

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...