How do I trim leading/trailing whitespace in a standard way?

后端 未结 30 2029
一个人的身影
一个人的身影 2020-11-22 02:06

Is there a clean, preferably standard method of trimming leading and trailing whitespace from a string in C? I\'d roll my own, but I would think this is a common problem wit

30条回答
  •  無奈伤痛
    2020-11-22 02:27

    Here's my C mini library for trimming left, right, both, all, in place and separate, and trimming a set of specified characters (or white space by default).

    contents of strlib.h:

    #ifndef STRLIB_H_
    #define STRLIB_H_ 1
    enum strtrim_mode_t {
        STRLIB_MODE_ALL       = 0, 
        STRLIB_MODE_RIGHT     = 0x01, 
        STRLIB_MODE_LEFT      = 0x02, 
        STRLIB_MODE_BOTH      = 0x03
    };
    
    char *strcpytrim(char *d, // destination
                     char *s, // source
                     int mode,
                     char *delim
                     );
    
    char *strtriml(char *d, char *s);
    char *strtrimr(char *d, char *s);
    char *strtrim(char *d, char *s); 
    char *strkill(char *d, char *s);
    
    char *triml(char *s);
    char *trimr(char *s);
    char *trim(char *s);
    char *kill(char *s);
    #endif
    

    contents of strlib.c:

    #include 
    
    char *strcpytrim(char *d, // destination
                     char *s, // source
                     int mode,
                     char *delim
                     ) {
        char *o = d; // save orig
        char *e = 0; // end space ptr.
        char dtab[256] = {0};
        if (!s || !d) return 0;
    
        if (!delim) delim = " \t\n\f";
        while (*delim) 
            dtab[*delim++] = 1;
    
        while ( (*d = *s++) != 0 ) { 
            if (!dtab[0xFF & (unsigned int)*d]) { // Not a match char
                e = 0;       // Reset end pointer
            } else {
                if (!e) e = d;  // Found first match.
    
                if ( mode == STRLIB_MODE_ALL || ((mode != STRLIB_MODE_RIGHT) && (d == o)) ) 
                    continue;
            }
            d++;
        }
        if (mode != STRLIB_MODE_LEFT && e) { // for everything but trim_left, delete trailing matches.
            *e = 0;
        }
        return o;
    }
    
    // perhaps these could be inlined in strlib.h
    char *strtriml(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_LEFT, 0); }
    char *strtrimr(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_RIGHT, 0); }
    char *strtrim(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_BOTH, 0); }
    char *strkill(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_ALL, 0); }
    
    char *triml(char *s) { return strcpytrim(s, s, STRLIB_MODE_LEFT, 0); }
    char *trimr(char *s) { return strcpytrim(s, s, STRLIB_MODE_RIGHT, 0); }
    char *trim(char *s) { return strcpytrim(s, s, STRLIB_MODE_BOTH, 0); }
    char *kill(char *s) { return strcpytrim(s, s, STRLIB_MODE_ALL, 0); }
    

    The one main routine does it all. It trims in place if src == dst, otherwise, it works like the strcpy routines. It trims a set of characters specified in the string delim, or white space if null. It trims left, right, both, and all (like tr). There is not much to it, and it iterates over the string only once. Some folks might complain that trim right starts on the left, however, no strlen is needed which starts on the left anyway. (One way or another you have to get to the end of the string for right trims, so you might as well do the work as you go.) There may be arguments to be made about pipelining and cache sizes and such -- who knows. Since the solution works from left to right and iterates only once, it can be expanded to work on streams as well. Limitations: it does not work on unicode strings.

提交回复
热议问题