背景
PM给我下了个需求:下单信息中,如果有全角字符,弹窗提示。接到这个需求之后第一反应是直接把string全部转成半角:
NSString *string;
string = @"测试半角+quanjiao";
NSMutableString *convertedString = [string mutableCopy];
CFStringTransform((CFMutableStringRef)convertedString, NULL, kCFStringTransformFullwidthHalfwidth, false);
NSLog(@"ddc:%@",convertedString);
完美
这时候PM说了:不要给用户转,有风险,让他自己重新填。
第一反应是正则匹配,但是并没有找到适合的正则表达式(也不会写),最终采取的办法是:
- (BOOL)checkHaveFullwidthWithString:(NSString *)inputString {
NSString *temp =nil;
for(int i =0; i < [inputString length]; i++)
{
temp = [inputString substringWithRange:NSMakeRange(i,1)];
if ([temp lengthOfBytesUsingEncoding:NSUTF8StringEncoding]>1) {
NSLog(@"第%d个字是:%@,为全角",i+1,temp);
return YES;
}
}
return NO;
}
什么是全角
最终采取的方法看似曲线救国,并且有局限性(不支持中文),但是反而从根本上解释了全角的含义。
全角是一种电脑字符,且每个全角字符占用两个标准字符(或半角字符)位置。每个普通字符(或半角字符)只占用一字节的空间(一字节有8位,共256个编码空间),而汉语等文字语言的字库量远大于256个,所以改用两个字节来储存。
所以lengthOfBytesUsingEncoding这个方法取出了这个字符的字节长度,长度大于1时,一定是全角。
字符串编码
因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。
由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码。
ASCII之后,为了兼容多国语言,又统一成Unicode编码,但是ASCII编码是1个字节,而Unicode编码通常是2个字节。如果是纯英文文本,Unicode要比ASCII多占用一倍空间。为了解决这个问题,推出了了长度可变的UTF-8:英文字母被编码成1个字节,汉字通常是3个字节。而ASCII实际上可以被看成是UTF-8的一部分,支持UTF-8就一定支持ASCII。