C / C ++ isspace()跳过多字节字符串字符

时间:2014-02-13 12:24:04

标签: c++ c string

我有以下函数返回从字符串中删除空格

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。任何帮助非常感谢。

感谢。

4 个答案:

答案 0 :(得分:4)

问题在于您如何致电isspace。仅isspace 如果输入在[0,UCHAR_MAX]范围内,则定义了结果 (或EOF)。在您的系统上,可能会签署char 意味着(int)*lptr将导致负值 重音字符(代码点大于127的字符), 这不属于合法范围。

调用is...的一个参数形式时(在...中) <cctype><ctype.h>),您应始终投出任何内容 char键入unsigned charisspace( static_cast<unsigned char>( *lptr ) )。 (unsigned char的隐式转换 到int会做正确的事。)

答案 1 :(得分:0)

您的rtrim功能以

结尾
*lptr = '\0';
return lptr;

除了将被视为空字符串之外,它不能返回任何其他内容。在trim中,您可以直接返回该结果。

根据您希望这些功能的工作方式,您应该让rtrim返回原始值l_ptr,该值保持不变并指向字符串的开头,或者使trim 1}}忽略rtrim的返回值。

所有字符都会遇到同样的问题,而不只是'Ć'

答案 2 :(得分:0)

如果您正在处理多字节字符,那么切换到wchar会更容易,以避免使用char(指针)操作造成不必要的麻烦?

您可以使用iswspace来检查角色是否为空格。

答案 3 :(得分:0)

rtrim()有多个问题。

  1. isspace()仅针对int范围内的unsigned char和EOF进行了定义。对于0到CHAR_MAX范围之外的值(通常为0到127),需要在隐式转换为unsigned char之前转换为int。 (@James Kanze)

      

    C11dr§7.4.1“......其值应表示为unsigned char或等于宏EOF的值。如果参数具有任何其他值,则行为未定义。“

  2. char *lptr = l_ptr + strlen("") - 1;很糟糕,因为未知指针值有效。需要新的方法。这也会使用

    启动 long 循环

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

  3. *lptr = '\0'; return lptr;总是重新""。 @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;
    }