[英]C/C++ isspace() skipping multibyte string characters
我有以下函数返回字符串中的空格,
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。 任何帮助,不胜感激。
谢谢。
问题是您如何调用isspace
。 仅当输入在[0,UCHAR_MAX]
范围内(或为EOF
)时[0,UCHAR_MAX]
isspace
才会定义结果。 在您的系统上, char
可能是带符号的,这意味着(int)*lptr
将导致带重音符号的字符(代码点大于127的字符)为负值,该值不在合法范围内。
调用is...
的一种参数形式( <cctype>
或<ctype.h>
那些参数)时,应始终将任何char
类型的类型isspace( static_cast<unsigned char>( *lptr ) )
为unsigned char
: isspace( static_cast<unsigned char>( *lptr ) )
。 (将unsigned char
隐式转换为int
会做正确的事情。)
您的rtrim
函数以
*lptr = '\0';
return lptr;
除了将被视为空字符串之外,它永远不会返回任何内容。 在trim
你然后直接返回该结果。
根据你想如何将这些功能的工作,你应该要么使rtrim
原值返回l_ptr
,它一直保持不变,并指向字符串的开头,或使trim
忽略的返回值rtrim
。
您可能会对所有字符都'Ć'
同样的问题,而不仅仅是'Ć'
。
如果您正在使用多字节字符,则可能更容易切换到wchar
,以避免使用char(pointer)操作不必要的麻烦?
您可以使用iswspace
来检查字符是否为空白。
rtrim()
有多个问题。
isspace()
仅在unsigned char
和EOF范围内为int
定义。 对于超出0到CHAR_MAX范围(通常为0到127)范围内的值,需要在隐式转换为int
之前转换为unsigned char
。 (@詹姆斯·坎泽)
C11dr§7.4.1“ ...其值应表示为
unsigned char
或等于宏EOF
的值。如果自变量具有任何其他值,则行为是不确定的。”
char *lptr = l_ptr + strlen("") - 1;
不好,因为该指针值未知有效。 需要新的方法。 这也开始了一个漫长的循环
for (; lptr != l_ptr ... ; lptr--)
*lptr = '\\0'; return lptr;
总是重播""
。 @hvd可能希望以字符串开头。
建议改写:
#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; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.