2014-02-13 149 views
1

我有以下函數返回剝離從字符串中的空格,C/C++ isspace()所能跳過多字節字符串字符

char *rtrim(char *l_ptr) 
{ 
    char *lptr = l_ptr + strlen(l_ptr) - 1; 
    for (; lptr != l_ptr && isspace((int)*lptr); lptr--) 
     ; 
    *lptr = '\0'; 
     return lptr; 
} 

char *ltrim(char *l_ptr) 
{ 
    char *lptr; 
    for (lptr = l_ptr; *lptr != '\0' && isspace((int)*lptr); lptr++) 
     ; 
    return lptr; 
} 


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

的問題是它的修整字符以下 -

去除導致從空格「

  Ć" 

除去前導空格,得到的 「」

的字符是0xc6,之前有幾個空格。我已經檢查了包含setlocale(LC_ALL,「」);的代碼。 LANG設置爲pl_PL.isoo88592。任何幫助非常感謝。

謝謝。

+0

什麼字符編碼您使用的? –

+0

@JohnZwinck從他的LANG設置中,我猜測ISO 8859-2(Latin-2,東歐)。 –

+0

注意:'char * lptr = l_ptr + strlen(l_ptr) - 1;'如果'l_ptr'爲'「」'則爲UB。 (也可能是一個_long_循環。) – chux

回答

0

rtrim()有多個問題。

  1. isspace()僅在範圍unsigned char和EOF爲int定義。對於範圍在0到CHAR_MAX之間的值(通常爲0到127),需要在隱式轉換爲int之前轉換爲unsigned char。 (@詹姆斯觀世)

    C11dr第7.4.1節」 ......其值應是可表示爲unsigned char或應等於宏EOF的值。如果參數爲其他值時,行爲沒有定義。「

  2. char *lptr = l_ptr + strlen("") - 1;是壞的,因爲該指針值未知是有效的。需要新的方法。這也揭開序幕循環與

    for (; lptr != l_ptr ... ; lptr--)

  3. *lptr = '\0'; return lptr;總是retruns ""。 @ hvd可能需要字符串的開始。

  4. 建議重新寫:

    #include "ctype.h" 
    char *rtrim(char *l_ptr) { 
        unsigned char *ptr = (unsigned char *) l_ptr; 
        unsigned char *end = ptr; 
        while (*ptr) { 
        if (!isspace(*ptr++)) { 
         end = ptr; 
        } 
        } 
        *end = '\0'; 
        return l_ptr; 
    } 
    
+0

謝謝,您提出的更改使我的代碼正常工作。 – user3305937

+0

@ user3305937如果其中一個答案能夠很好地滿足您的帖子的需求,請接受它。獲得15個以上的代表積分後,請務必對所有您認爲有用的答案進行投票。 – chux

0

rtrim函數結束的

*lptr = '\0'; 
return lptr; 

這永遠不能返回比將被視爲一個空字符串的任何其他。在trim你然後直接返回該結果。

根據您想如何將這些功能的工作,你應該要麼使rtrim回報l_ptr原始值,它一直保持不變,並指向字符串的開頭,或使trim忽略的rtrim返回值。

你也有同樣的問題,所有的字符,而不僅僅是'Ć'

+0

我認爲在'rtrim'中返回字符串的結尾不是*有問題,而是''rtrim'用於實現'trim'的方式。 – hmn

+0

@hmn哦,當然,我想這也是一個有效的方法。將編輯。 – hvd

4

的問題是你如何調用isspaceisspace僅 已經定義的結果,如果輸入是在[0,UCHAR_MAX] 範圍(或是EOF)。在您的系統上,char可能已簽名,其中 表示(int)*lptr將導致 重音字符(代碼點大於127的字符), (不在合法範圍內)爲負值。

當調用的is...的一個參數的形式(那些 <cctype><ctype.h>),你應該始終char類型unsigned char什麼:isspace( static_cast<unsigned char>( *lptr ) )。 (中unsigned charint的隱式轉換會做正確的事。)

+0

雖然基於標準完全正確,但您確定這是導致OP的問題嗎?如果我沒有記錯,至少glibc有意支持函數中的負值,例如'isspace'作爲標準要求的擴展。 – hvd

+0

@ hvd這將解釋症狀。儘管如你所說,一些 實現_do_盡力使它工作(除了 對於Latin-1中的'''',其代碼點爲0xFF);我記得 這是Solaris下的情況。 (我不記得在Linux下嘗試了 ,看看'glibc'的功能。)我還需要至少一次過去的一次,在Windows (使用VC++)時不是這種情況。 –

0

如果與多字節字符工作可能會比較容易切換到wchar,以避免與CHAR(指針)操縱不必要的麻煩?

你也可以使用iswspace檢查如果字符是一個空白。

+0

他的環境似乎說他正在使用不是多字節的ISO 8859-2。 –