今天同事遇到一个问题问我,是关于以下代码中
if ((unsigned char) ptr[0] & 0x80) 的意义在哪里?为啥要加这个判断?
-
int ah_str2lowcase(const char *raw_str, char *low_str, int max_len)
-
{
-
char *ptr = low_str;
-
-
strncpy(low_str, raw_str, max_len);
-
low_str[max_len] = '\0';
-
while (*ptr){
-
-
if ((unsigned char) ptr[0] & 0x80) ///---------------这个判断的意义?
-
return 0;
-
*ptr = tolower((unsigned char) *ptr);
-
ptr++;
-
}
-
-
return 0;
-
-
}
为了解释这个问题,必须要了解几种编码格式:
1.ASCII码
ASCII码(American Standard Code For Information Interchange,美国标准信息交换码),由美国国家标准局指定,目前计算机中用得最广泛的字符集及其编码。ASCII码有7位码和8位码两种形式。
7位ASCII码是用7位二进制数进行编码的,可以表示128个字符,就构成了如下表:
由表可看出最高位均为0,我们称之为“标准ASCII码”;
英语用128个符号编码就够了,但是用来表示其它语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用128位ASCII码表示,于是,一些欧洲国家就决定,利用字节闲置的最高位编入新的符号,这样一来,就可以表示最多256个符号了。
将最高位置1,我们又得到了128个字符,称之为“扩展ASCII码”,表如图:
2.Unicode
为了统一各国自己定义的编码,Unicode产生了,它用两个字节来尝试覆盖各国编码语言。事实上,Unicode对汉字的支持不是很好,简体加繁体总共有六七万个汉字,而2个字节的Unicode最多能表示65536个,才6万多个,所以Unicode只能排除一些几乎不能用的汉字,好在常用的汉字也就7000多个。
3.国标码
我国用来表示汉字的编码方式。
4.汉字对应的国标码和Unicode
5.实例
-
#include <unistd.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <ctype.h>
-
-
int ah_str2lowcase(const char *raw_str, char *low_str, int max_len)
-
{
-
char *ptr = low_str;
-
-
strncpy(low_str, raw_str, max_len);
-
low_str[max_len] = '\0';
-
-
while (*ptr){
-
printf("ptr[0]=%x\n",(unsigned char)ptr[0]);
-
if ((unsigned char) ptr[0] & 0x80)
-
return 0;
-
*ptr = tolower((unsigned char) *ptr);
-
ptr++;
-
}
-
-
return 0;
-
-
}
-
-
int main(int argc, char *argv[])
-
{
-
char raw_str[10] = "国标码";
-
char low_str[10];
-
-
ah_str2lowcase(raw_str,low_str,10);
-
-
printf("low_str = %s\n",low_str);
-
return 0;
-
}
编译运行:
gwwu@hz-dev4.wgw.com:~/test>gcc -g str2lowcase.c -o str2lowcase -Wall
gwwu@hz-dev4.wgw.com:~/test>./str2lowcase
ptr[0]=b9
low_str = 国标码
去掉if判断:
-
#include <unistd.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <ctype.h>
-
-
int ah_str2lowcase(const char *raw_str, char *low_str, int max_len)
-
{
-
char *ptr = low_str;
-
-
strncpy(low_str, raw_str, max_len);
-
low_str[max_len] = '\0';
-
while (*ptr){
-
printf("ptr[0]=%x\n",(unsigned char)ptr[0]);
-
//if ((unsigned char) ptr[0] & 0x80)
-
// return 0;
-
*ptr = tolower((unsigned char) *ptr);
-
ptr++;
-
}
-
-
return 0;
-
-
}
-
-
int main(int argc, char *argv[])
-
{
-
char raw_str[10] = "国标码";
-
char low_str[10];
-
-
ah_str2lowcase(raw_str,low_str,10);
-
-
printf("low_str = %s\n",low_str);
-
return 0;
-
}
编译运行:
gwwu@hz-dev4.wgw.com:~/test>gcc -g str2lowcase.c -o str2lowcase -Wall
gwwu@hz-dev4.wgw.com:~/test>./str2lowcase
ptr[0]=b9
ptr[0]=fa
ptr[0]=b1
ptr[0]=ea
ptr[0]=c2
ptr[0]=eb
low_str = 国标码
6.解释原始问题
-
if ((unsigned char) ptr[0] & 0x80) ///---------------这个判断的意义?
-
return 0;
这个判断的意义是:因为有大小写的字母都小于127,就是正常的ASCII内,所有增加了这个判断,当字符大于ASCII码的时候就返回。其实tolower API函数本身就应该有这个功能,所以其实这个判断个人认为是多余的。如果有组合的字符出现,即某一个为大于127的字符,后面跟着A-Z的某一个时,会因为return导致后面的字符没有变成小写的。
阅读(1778) | 评论(0) | 转发(0) |