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

后端 未结 30 2354
一个人的身影
一个人的身影 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:37

    Here's a solution similar to @adam-rosenfields in-place modification routine but without needlessly resorting to strlen(). Like @jkramer, the string is left-adjusted within the buffer so you can free the same pointer. Not optimal for large strings since it does not use memmove. Includes the ++/-- operators that @jfm3 mentions. FCTX-based unit tests included.

    #include 
    
    void trim(char * const a)
    {
        char *p = a, *q = a;
        while (isspace(*q))            ++q;
        while (*q)                     *p++ = *q++;
        *p = '\0';
        while (p > a && isspace(*--p)) *p = '\0';
    }
    
    /* See http://fctx.wildbearsoftware.com/ */
    #include "fct.h"
    
    FCT_BGN()
    {
        FCT_QTEST_BGN(trim)
        {
            { char s[] = "";      trim(s); fct_chk_eq_str("",    s); } // Trivial
            { char s[] = "   ";   trim(s); fct_chk_eq_str("",    s); } // Trivial
            { char s[] = "\t";    trim(s); fct_chk_eq_str("",    s); } // Trivial
            { char s[] = "a";     trim(s); fct_chk_eq_str("a",   s); } // NOP
            { char s[] = "abc";   trim(s); fct_chk_eq_str("abc", s); } // NOP
            { char s[] = "  a";   trim(s); fct_chk_eq_str("a",   s); } // Leading
            { char s[] = "  a c"; trim(s); fct_chk_eq_str("a c", s); } // Leading
            { char s[] = "a  ";   trim(s); fct_chk_eq_str("a",   s); } // Trailing
            { char s[] = "a c  "; trim(s); fct_chk_eq_str("a c", s); } // Trailing
            { char s[] = " a ";   trim(s); fct_chk_eq_str("a",   s); } // Both
            { char s[] = " a c "; trim(s); fct_chk_eq_str("a c", s); } // Both
    
            // Villemoes pointed out an edge case that corrupted memory.  Thank you.
            // http://stackoverflow.com/questions/122616/#comment23332594_4505533
            {
              char s[] = "a     ";       // Buffer with whitespace before s + 2
              trim(s + 2);               // Trim "    " containing only whitespace
              fct_chk_eq_str("", s + 2); // Ensure correct result from the trim
              fct_chk_eq_str("a ", s);   // Ensure preceding buffer not mutated
            }
    
            // doukremt suggested I investigate this test case but
            // did not indicate the specific behavior that was objectionable.
            // http://stackoverflow.com/posts/comments/33571430
            {
              char s[] = "         foobar";  // Shifted across whitespace
              trim(s);                       // Trim
              fct_chk_eq_str("foobar", s);   // Leading string is correct
    
              // Here is what the algorithm produces:
              char r[16] = { 'f', 'o', 'o', 'b', 'a', 'r', '\0', ' ',                     
                             ' ', 'f', 'o', 'o', 'b', 'a', 'r', '\0'};
              fct_chk_eq_int(0, memcmp(s, r, sizeof(s)));
            }
        }
        FCT_QTEST_END();
    }
    FCT_END();
    

提交回复
热议问题