在C语言中编写String.trim()函数

7

可能的重复问题:
C语言中消除前导和尾随空格的简便方法?
在 C 语言中剪切字符串

我正在编写 C 语言中的 String trim 方法,这是我想出的代码。我认为它可以消除前导和尾随的空格,但我希望代码能更加简洁。你能提供改进建议吗?

void trim(char *String)
{
int i=0;j=0;
char c,lastc;
while(String[i])
{
   c=String[i];
   if(c!=' ')
   {
     String[j]=c;
     j++;
   }
   else if(lastc!= ' ')
   {
     String[j]=c;
     j++;

   }
   lastc = c;
   i++;
}

这段代码看起来干净吗?

2
它只检查空格字符。空白通常包括检查TAB、回车和换行符。 - user177800
8
这是一个关于在C语言中去除字符串首尾空格的问题。以下是一个简单的代码示例:#include #include #include char* trim(char* str) { size_t len = 0; char *frontp = str; char *endp = NULL; if(str == NULL) { return NULL; } if(str[0] == '\0') { return str; } len = strlen(str); endp = str + len; while(isspace((unsigned char)*frontp)) { ++frontp; } if(endp != frontp) { while(isspace((unsigned char)*(--endp)) && endp != frontp) {} } if(frontp != str && endp == frontp) *str = '\0'; else if(str + len - 1 != endp) *(endp + 1) = '\0'; endp = str; if(frontp != str) { while(*frontp) { *endp++ = *frontp++; } *endp = '\0'; } return str; } int main() { char test[] = " trim me! "; printf("Before: \"%s\"\n", test); trim(test); printf("After: \"%s\"\n", test); } - James Kolpack
在这里发布了一个答案:https://dev59.com/OHRB5IYBdhLWcg3wV156#1431206 - JRL
如果lastc从未被赋值,则else if(lastc!= ' ')会怎样。考虑在http://codereview.stackexchange.com/上发布。 - Mawg says reinstate Monica
7个回答

4
看起来不太干净。假设第一个字符是空格,您正在使用未定义值的lastc。在末尾留下一个空格(如果末尾有空格,则当其被读取时c 就是一个空格,而lastc则不会)。 此外,您还没有结束字符串。假设您解决了未初始化的lastc问题,您将把" abc"转换为"abcbc",因为它在任何时候都没有被缩短。代码还会折叠字符串内部的多个空格。这不是您所描述的行为;这是期望的行为吗?

3

如果您明智地使用标准库函数,例如isspace()memmove(),通常可以使您的代码更易读:

#include <string.h>
#include <ctype.h>

void trim(char *str)
{
    char *start, *end;

    /* Find first non-whitespace */
    for (start = str; *start; start++)
    {
        if (!isspace((unsigned char)start[0]))
            break;
    }

    /* Find start of last all-whitespace */
    for (end = start + strlen(start); end > start + 1; end--)
    {
        if (!isspace((unsigned char)end[-1]))
            break;
    }

    *end = 0; /* Truncate last whitespace */

    /* Shift from "start" to the beginning of the string */
    if (start > str)
        memmove(str, start, (end - start) + 1);
}

1
我可以在商业软件中使用这个吗? - Mawg says reinstate Monica

1

这段代码存在几个问题。它只检查空格,而不是制表符或换行符。您正在复制字符串的整个非空白部分。并且在设置 lastc 之前使用了它。

以下是另一种版本(已编译但未经测试):

char *trim(char *string)
{
    char *start;
    int len = strlen(string);
    int i;

    /* Find the first non whitespace char */
    for (i = 0; i < len; i++) {
        if (! isspace(string[i])) {
            break;
        }
    }

    if (i == len) {
        /* string is all whitespace */
        return NULL;
    }

    start = &string[i];

    /* Remove trailing white space */
    for (i = len; i > 0; i--) {
        if (isspace(string[i])) {
            string[i] = '\0';
        } else {
            break;
        }
    }

    return start;
}

1

有一些问题:变量lastc可能未初始化。你可以使用for循环代替while循环,例如。此外,trim/strip函数通常会替换空格、制表符和换行符。

这是我很久以前写的一个使用指针的解决方案:

void trim(char *str)
{
    char *ptr = str;
    while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') ++ptr;

    char *end = ptr;
    while(*end) ++end;

    if(end > ptr)
    {
        for(--end; end >= ptr && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n'); --end);
    }

    memmove(str, ptr, end-ptr);
    str[end-ptr] = 0;
} 

1
这是我的解决方案。
简短、简单、干净、有注释,经过轻微测试。
它使用了“isspace”分类函数,因此您可以轻松更改“空格”的定义以进行修剪。
void trim(char* String)
{
    int dest;
    int src=0;
    int len = strlen(String);

    // Advance src to the first non-whitespace character.
    while(isspace(String[src])) src++;

    // Copy the string to the "front" of the buffer
    for(dest=0; src<len; dest++, src++) 
    {
        String[dest] = String[src];
    }

    // Working backwards, set all trailing spaces to NULL.
    for(dest=len-1; isspace(String[dest]); --dest)
    {
        String[dest] = '\0';
    }
}

当strlen(String)为0时,这可能是危险的。 - user85509
空格符不仅仅是空格字符。 - Mawg says reinstate Monica

0

不要将字符与空格字符' '进行比较,我会使用“isspace”函数,我相信它在ctype.h中定义。


0

我不知道所谓的“清洁”,但我觉得这个代码难以理解。如果我需要做这件事,我会最初考虑两个阶段:

  1. 找出从开头要删除多少个字符,然后将剩余的字符串(包括空终止符)memmove到起始地址。(如果允许返回不同的起始指针,则可能不需要memmove,但如果是这样,您需要非常注意内存卫生。)
  2. 找出从(新的)结尾要删除多少个字符,并在那里设置一个新的空终止符。

如果有速度问题,我可能会更仔细地研究像您正在尝试实现的一次性解决方案。

顺便说一句,您可能希望使用isspace()而不是仅检查空格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接