Chinaunix首页 | 论坛 | 博客
  • 博客访问: 563032
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-10-27 17:07:47

今天同事遇到一个问题问我,是关于以下代码中if ((unsigned char) ptr[0] & 0x80的意义在哪里?为啥要加这个判断?

点击(此处)折叠或打开

  1. int ah_str2lowcase(const char *raw_str, char *low_str, int max_len)
  2. {
  3.     char *ptr = low_str;
  4.     
  5.     strncpy(low_str, raw_str, max_len);    
  6.     low_str[max_len] = '\0';
  7.     while (*ptr){

  8.         if ((unsigned char) ptr[0] & 0x80) ///---------------这个判断的意义?
  9.             return 0;
  10.         *ptr = tolower((unsigned char) *ptr);
  11.         ptr++;
  12.     }

  13.     return 0;

  14. }
为了解释这个问题,必须要了解几种编码格式:
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

汉字 国标码 Unicode
B9FA 56FD
B1EA 6807
C2EB 7801

5.实例

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>

  6. int ah_str2lowcase(const char *raw_str, char *low_str, int max_len)
  7. {
  8.     char *ptr = low_str;

  9.     strncpy(low_str, raw_str, max_len);
  10.     low_str[max_len] = '\0';
  11.     
  12.     while (*ptr){
  13.         printf("ptr[0]=%x\n",(unsigned char)ptr[0]);
  14.         if ((unsigned char) ptr[0] & 0x80)
  15.             return 0;
  16.         *ptr = tolower((unsigned char) *ptr);
  17.         ptr++;
  18.     }

  19.     return 0;

  20. }

  21. int main(int argc, char *argv[])
  22. {
  23.     char raw_str[10] = "国标码";
  24.     char low_str[10];
  25.     
  26.     ah_str2lowcase(raw_str,low_str,10);

  27.     printf("low_str = %s\n",low_str);
  28.     return 0;
  29. }

编译运行:
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判断:

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>

  6. int ah_str2lowcase(const char *raw_str, char *low_str, int max_len)
  7. {
  8.     char *ptr = low_str;

  9.     strncpy(low_str, raw_str, max_len);
  10.     low_str[max_len] = '\0';
  11.     while (*ptr){
  12.         printf("ptr[0]=%x\n",(unsigned char)ptr[0]);
  13.         //if ((unsigned char) ptr[0] & 0x80)
  14.         // return 0;
  15.         *ptr = tolower((unsigned char) *ptr);
  16.         ptr++;
  17.     }

  18.     return 0;

  19. }

  20. int main(int argc, char *argv[])
  21. {
  22.     char raw_str[10] = "国标码";
  23.     char low_str[10];
  24.     
  25.     ah_str2lowcase(raw_str,low_str,10);

  26.     printf("low_str = %s\n",low_str);
  27.     return 0;
  28. }
编译运行:
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.解释原始问题
  
  1.         if ((unsigned char) ptr[0] & 0x80) ///---------------这个判断的意义?
  2.             return 0;

这个判断的意义是:因为有大小写的字母都小于127,就是正常的ASCII内,所有增加了这个判断,当字符大于ASCII码的时候就返回。其实tolower API函数本身就应该有这个功能,所以其实这个判断个人认为是多余的。如果有组合的字符出现,即某一个为大于127的字符,后面跟着A-Z的某一个时,会因为return导致后面的字符没有变成小写的。




阅读(1778) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~