修剪C中的字符串

时间:2009-03-18 00:26:45

标签: c winapi string

简要说明:

我使用win32和标准C api(使用MSVC2008进行编译,以便在C中使用.NET的String.Trim相当于所以如果需要我可以访问所有C ++内容,但我只是想修剪一个char*)。

鉴于有strchrstrtok以及各种其他字符串函数,肯定应该有一个修剪函数,或者可以重新利用的函数......

由于

15 个答案:

答案 0 :(得分:21)

没有标准的库函数可以做到这一点,但是推出自己的函数并不难。关于这样做有existing question关于源代码的答案。

答案 1 :(得分:12)

这让我想写自己的 - 我不喜欢那些提供的。在我看来应该有3个功能。

char *ltrim(char *s)
{
    while(isspace(*s)) s++;
    return s;
}

char *rtrim(char *s)
{
    char* back = s + strlen(s);
    while(isspace(*--back));
    *(back+1) = '\0';
    return s;
}

char *trim(char *s)
{
    return rtrim(ltrim(s)); 
}

答案 2 :(得分:11)

您可以使用ctype.h中的标准isspace()函数来实现此目的。只需比较字符数组的开头和结尾字符,直到两端都不再有空格。

“空格”包括:

  

''(0x20)空格(SPC)

     

'\ t'(0x09)水平标签(TAB)

     

'\ n'(0x0a)换行符(LF)

     

'\ v'(0x0b)垂直制表符(VT)

     

'\ f'(0x0c)feed(FF)

     

'\ r'(0x0d)回车(CR)

虽然没有能够为你完成所有工作的功能,但你必须重复自己的解决方案,以反复比较给定字符数组的每一面,直到没有空格。

修改

由于您可以访问C ++,Boost已经a trim implementation等着您,让您的生活更轻松。

答案 3 :(得分:4)

很高兴看到这样的实现。我通常会这样修剪:

char *trim(char *s) {
    char *ptr;
    if (!s)
        return NULL;   // handle NULL string
    if (!*s)
        return s;      // handle empty string
    for (ptr = s + strlen(s) - 1; (ptr >= s) && isspace(*ptr); --ptr);
    ptr[1] = '\0';
    return s;
}

快速可靠 - 为我服务多年。

答案 4 :(得分:3)

/* Function to remove white spaces on both sides of a string i.e trim */

void trim (char *s)
{
    int i;

    while (isspace (*s)) s++;   // skip left side white spaces
    for (i = strlen (s) - 1; (isspace (s[i])); i--) ;   // skip right side white spaces
    s[i + 1] = '\0';
    printf ("%s\n", s);
}

答案 5 :(得分:2)

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

char* trim(char* input);


int _tmain(int argc, _TCHAR* argv[])
{
    char sz1[]="  MQRFH  ";
    char sz2[]=" MQRFH";
    char sz3[]="  MQR FH";
    char sz4[]="MQRFH  ";
    char sz5[]="MQRFH";
    char sz6[]="M";
    char sz7[]="M ";
    char sz8[]=" M";
    char sz9[]="";
    char sz10[]="        ";

    printf("sz1:[%s] %d\n",trim(sz1), strlen(sz1));
    printf("sz2:[%s] %d\n",trim(sz2), strlen(sz2));
    printf("sz3:[%s] %d\n",trim(sz3), strlen(sz3));
    printf("sz4:[%s] %d\n",trim(sz4), strlen(sz4));
    printf("sz5:[%s] %d\n",trim(sz5), strlen(sz5));
    printf("sz6:[%s] %d\n",trim(sz6), strlen(sz6));
    printf("sz7:[%s] %d\n",trim(sz7), strlen(sz7));
    printf("sz8:[%s] %d\n",trim(sz8), strlen(sz8));
    printf("sz9:[%s] %d\n",trim(sz9), strlen(sz9));
    printf("sz10:[%s] %d\n",trim(sz10), strlen(sz10));

    return 0;
}

char *ltrim(char *s) 
{     
    while(isspace(*s)) s++;     
    return s; 
}  

char *rtrim(char *s) 
{     
    char* back;
    int len = strlen(s);

    if(len == 0)
        return(s); 

    back = s + len;     
    while(isspace(*--back));     
    *(back+1) = '\0';     
    return s; 
}  

char *trim(char *s) 
{     
    return rtrim(ltrim(s));  
} 

输出:

sz1:[MQRFH] 9
sz2:[MQRFH] 6
sz3:[MQR FH] 8
sz4:[MQRFH] 7
sz5:[MQRFH] 5
sz6:[M] 1
sz7:[M] 2
sz8:[M] 2
sz9:[] 0
sz10:[] 8

答案 6 :(得分:1)

static inline void ut_trim(char * str) {
   char * start = str;
   char * end = start + strlen(str);

   while (--end >= start) {   /* trim right */
      if (!isspace(*end))
         break;
   }
   *(++end) = '\0';

   while (isspace(*start))    /* trim left */
      start++;

   if (start != str)          /* there is a string */
      memmove(str, start, end - start + 1);
}

答案 7 :(得分:1)

当返回值始终等于参数时,我喜欢它。这样,如果字符串数组已分配malloc(),则可以再次安全地free()

/* Remove leading whitespaces */
char *ltrim(char *const s)
{
        size_t len;
        char *cur;

        if(s && *s) {
                len = strlen(s);
                cur = s;

                while(*cur && isspace(*cur))
                        ++cur, --len;

                if(s != cur)
                        memmove(s, cur, len + 1);

        }

        return s;
}

/* Remove trailing whitespaces */
char *rtrim(char *const s)
{
        size_t len;
        char *cur;

        if(s && *s) {
                len = strlen(s);
                cur = s + len - 1;

                while(cur != s && isspace(*cur))
                        --cur, --len;

                cur[isspace(*cur) ? 0 : 1] = '\0';
        }

        return s;
}

/* Remove leading and trailing whitespaces */
char *trim(char *const s)
{
        rtrim(s);  // order matters
        ltrim(s);

        return s;
}

答案 8 :(得分:1)

void ltrim(char str[PATH_MAX])
{
        int i = 0, j = 0;
        char buf[PATH_MAX];
        strcpy(buf, str);
        for(;str[i] == ' ';i++);

        for(;str[i] != '\0';i++,j++)
                buf[j] = str[i];
        buf[j] = '\0';
        strcpy(str, buf);
}

答案 9 :(得分:0)

这个怎么样......它只需要对字符串进行一次迭代(不使用strlen,它遍历字符串)。当函数返回时,你得到一个指向修剪后的字符串开头的指针,该字符串以空值终止。该字符串从左侧修剪空格(直到找到第一个字符)。在最后一个非空格字符之后,字符串也会被修剪掉所有尾随空格。

char* trim(char* input) {
    char* start = input;
    while (isSpace(*start)) { //trim left
        start++;
    }

    char* ptr = start;
    char* end = start;
    while (*ptr++ != '\0') { //trim right
        if (!isSpace(*ptr)) { //only move end pointer if char isn't a space
            end = ptr;
        }
    }

    *end = '\0'; //terminate the trimmed string with a null
    return start;
}

bool isSpace(char c) {
    switch (c) {
        case ' ':
        case '\n':
        case '\t':
        case '\f':
        case '\r':
            return true;
            break;
        default:
            return false;
            break;
    }
}

答案 10 :(得分:0)

/* iMode 0:ALL, 1:Left, 2:Right*/
char* Trim(char* szStr,const char ch, int iMode)
{
    if (szStr == NULL)
        return NULL;
    char szTmp[1024*10] = { 0x00 };
    strcpy(szTmp, szStr);
    int iLen = strlen(szTmp);
    char* pStart = szTmp;
    char* pEnd = szTmp+iLen;
    int i;
    for(i = 0;i < iLen;i++){
        if (szTmp[i] == ch && pStart == szTmp+i && iMode != 2)
            ++pStart;
        if (szTmp[iLen-i-1] == ch && pEnd == szTmp+iLen-i && iMode != 1)
            *(--pEnd) = '\0';
    }
    strcpy(szStr, pStart);
    return szStr;
}

答案 11 :(得分:0)

这是我的实现,表现得像libc中的内置字符串函数(也就是说,它需要一个c-string,它会修改它并将它返回给调用者)。

它修剪了领先的空间和将剩余的字符向左移动,因为它从左到右解析字符串。然后它标记字符串的新结尾并开始向后解析它,用'\ 0'替换尾随空格,直到它找到非空格字符或字符串的开头。我相信这些是这项特定任务的最小可能迭代次数。

// ----------------------------------------------------------------------------
// trim leading & trailing spaces from string s (return modified string s)
// alg:
// - skip leading spaces, via cp1
// - shift remaining *cp1's to the left, via cp2
// - mark a new end of string
// - replace trailing spaces with '\0', via cp2
// - return the trimmed s
//
char *s_trim(char *s)
{
    char *cp1;                              // for parsing the whole s
    char *cp2;                              // for shifting & padding

    // skip leading spaces, shift remaining chars
    for (cp1=s; isspace(*cp1); cp1++ )      // skip leading spaces, via cp1
        ;
    for (cp2=s; *cp1; cp1++, cp2++)         // shift left remaining chars, via cp2
        *cp2 = *cp1;
    *cp2-- = 0;                             // mark new end of string for s

    // replace trailing spaces with '\0'
    while ( cp2 > s && isspace(*cp2) )
        *cp2-- = 0;                         // pad with '\0's

    return s;
}

答案 12 :(得分:0)

不是最好的方式,但它有效

char* Trim(char* str)
{
    int len = strlen(str);
    char* buff = new char[len];
    int i = 0;
    memset(buff,0,len*sizeof(char));
    do{
        if(isspace(*str)) continue;
        buff[i] = *str; ++i;
    } while(*(++str) != '\0');
    return buff;
}

答案 13 :(得分:-4)

void inPlaceStrTrim(char* str) {
    int k = 0;
    int i = 0;
    for (i=0; str[i] != '\0';) {
        if (isspace(str[i])) {
            // we have got a space...
            k = i;
            for (int j=i; j<strlen(str)-1; j++) {
                str[j] = str[j+1];
            }
            str[strlen(str)-1] = '\0';
            i = k; // start the loop again where we ended..
        } else {
            i++;
        }
    }
}

答案 14 :(得分:-6)

最简单的事情就是简单的循环。我将假设您希望修剪后的字符串返回原位。

char *
strTrim(char * s){
    int ix, jx;
    int len ;
    char * buf 
    len = strlen(s);  /* possibly should use strnlen */
    buf = (char *) malloc(strlen(s)+1);

    for(ix=0, jx=0; ix < len; ix++){
       if(!isspace(s[ix]))
          buf[jx++] = s[ix];

    buf[jx] = '\0';
    strncpy(s, buf, jx);  /* always looks as far as the null, but who cares? */
    free(buf);            /* no good leak goes unpunished */
    return s;             /* modifies s in place *and* returns it for swank */
 }

这也消除了嵌入的空白,如果String.Trim没有,那么它需要更多的逻辑。