程序是对数据的表示和处理。对于数值型数据,可以直接处理;对于数值型以外的数据,例如文本(字符和字符串),图形图像,音频视频,还涉及到数据的表示(数据编码)的问题。1C语言对字符和字符常量的约定 字符编码有ASCII、GB2312,Unicode等。处理字符或字符串数据时,其实质是对字符编码的操作。ASCII编码使用一个字节的整数来编码西文字符,而整数在计算机中是区分signed和unsigned的,对于unsigned的,一个字符的表示范围是0255(0x000000000xFFFFFFFF),对于signed,通常使用补码来编码,也就是区分符号,一个字节的值域(表示的整数范围)是:128127,虽然ASCII只使用了0x000000000x0FFFFFFF的区段(0127),但字符类型为了与数值型整数在处理时达到统一,char类型也可以区分unsigned和signed,char默认是signed的。 ASCII对数字字符进行连续编码,字符转数字只需减去0即可:charch3;intdch0;字符转数字 ASCII对大写字母和小写字母也进行了连续编码,为方便处理(包括大小写转换),但其编码值做了特殊考虑: Bin Oct Dec Hex 缩写字符 解释 (二进制) (八进制) (十进制) (十六进制) 01000001 101hr65hr0x41 A 大写字母A 01100001 141hr97hr0x61 a 小写字母a 大、小写字母只有在第6位(从低位到高位)存在区别,这样在大小写转换时特别方便。charstr〔〕AbCdEf;while(p!)(p)aA;如果是大写,改成小写,将log2(aA)log2(32),将低位到高位的第6位置1;printf(s,str);while(p!)(p)(aA);如果是小写,改成大写,将log2(aA)log2(32),将低位到高位的第6位置0;printf(s,str);ABCDEF 转义字符也可以用ASCII码来表示字符,但只能用8进制或16进制,8进制0开头例如23且最多3位、16进制x开头例如xa且最多两位;printf(ccc,60,48,0);000,用8进制表示转义字符时,前导0可以省略printf(ccc,101,65,A);AAA,用8进制表示转义字符时,如果超过3位,不要用前导0printf(ccc,101,65,A);1AA101在内存中变成了831h,四个位存储10,也就是8h,四个位存储1,也就是31h,其整数就是831h,截断成一个字节后就是31h,也就是字符1 在C中,unicode编码的字符一般以wchart类型存储,固定使用两个字符的长度。 includestdio。hincludestdlib。hincludelocale。hintmain(void){chars〔〕中;汉字在CC中是用2个字节表示printf(dd,s〔0〕,s〔1〕);charm〔3〕;m〔0〕42;m〔1〕48;m〔2〕0;puts(m);两个字节连起来凑成一个汉字。printf(cc,s〔0〕,s〔1〕);printf(cc,214,208);d6,d0都是字符256模数的关系(补码其负数补码模)setlocale(LCALL,chs);wchartwcLN2D;wprintf(Lc,wc);system(pause);return0;}4248中中中中 中英文混合的字符统计:includestdio。hincludestring。hintgbkstrlen(charstr){p用于后面遍历while(p)若是结束符0,则结束循环{if(p0((p1)0(p1)63))中文汉字情况{str移动一位,p移动移动2位,因此长度加1p2;}str不动,p移动一位,长度加1}返回地址之差}intmain(){charstr〔〕abc你好123中国456;printf(d,strlen(str)gbkstrlen(str));4getchar();}2C语言对字符串的约定 C语言中,字符串是借助于字符型的一维数组来存放的,并规定以字符作为字符串结束标志。由前面的知识我们知道,‘是一个转义字符,称为空值,它的ASCII编码值为0。‘作为标志占用存储空间,但不计入串的实际长度。 在字符串输出或逐个字符处理时,或者需要其长度信息,或者有一个结束标志,如果选择一个结束标志,在字符串处理时会更加方便。循环时可用字符结束标志作为循环结束标志,在用作函数参数时,不需要额外提供一个长度参数。 例如字符串处理的库函数都是以结束标志为循环终止条件的,包括strlen(),如果用strlen()去处理字符数组,除非其有一个显式的声明,否则会出错。charstr〔〕abc456;有一个隐式的存储charchs〔〕{a,b,c,4,5,6};printf(ss,str,chs);abc456abc456烫abc456printf(dddd,sizeof(str),sizeof(chs),strlen(str),strlen(chs));76614,14是一个随机值;3C语言中表示字符串常量的约定 虽然C语言中没有字符串数据类型,但却允许使用字符串常量。字符串常量是由双引号括起来的一串字符,在表示字符串常量时,不需要人为在其末尾加入‘’,例如字符串常量Hello!不必写成Helllo!,C编译程序将自动完成这一工作,在末尾加上结束标志。 字符串常量与其它常量不一样,其存储在内存的常量区。4C语言中字符串常量给出的是地址值。 一个字符串常量都分别占用内存中一串连续的存储空间。这些连续的存储空间实际上就是字符型的一维数组。这些数组虽然没有名字,但C编译系统却以字符串常量的形式给出存放每一字符串的存储空间的首地址,不同的字符串具有不同的起始地址。也就是说,在C语言中,字符串常量被隐含的处理成了一个以结尾的无名字符型一维数组。因此,若有以下定义: charsp,s〔10〕; 则以下赋值语句是不合法的。 sHello!; 因为,字符串常量在赋值过程中给出的是这个字符串在内存中所占的一串连续存储单元的首地址,而s是一个不可重新赋值的数组名,因此,些赋值不合法,而以下赋值是合法的。 spHello!; 此赋值语句并不是把字符串的内容放入sp中,而只是把字符串在内存中所占的首地址赋予了char类型的指针变量sp,使指针变量sp指向该字符串。 当然,也不能使用sp去修改其指向的常量值,如 sp〔2〕L;非法操作 如果需要操作字符元素,将其存储到数组中即可。5字符数组与字符串的区别 字符数组的每个元素中可存放一个字符,但它并不限定最后一个字符应该是什么,而在C语言中,因为有关字符串的大量操作都与串结束标志有关,因此,在字符数组中的有效字符后面加上这一特定操作后,我们就可以把这种一维字符型数组看作字符串变量,但它又不同于一般的变量。要注意的是,仅仅可以在字符数组内存放字符串,不能通过赋值语句将字符串常量或其他字符数组中的字符串直接赋给字符串变量。换句话说,字符串是字符数组的一种具体应用。 看汇编:5:chararr〔〕H00401028moveax,〔stringhellow(00422f78)〕0040102Dmovdwordptr〔ebp8〕,eax00401030movcx,wordptr〔stringhellow4(00422f7c)〕00401037movwordptr〔ebp4〕,cx6:charpH0040103Bmovdwordptr〔ebp0Ch〕,offsetstringhellow(00422f78) 字符串常量存储在常量区,例如上例Hello存储在(00422f78)。6字符串与文本文档 小的文本文档你可以用一个字符串或字符串数组来处理,使用做换行来分段即可。 大的文本文档你可以通过链表(链式存储)来存储,链表的一个节点可以存储一个段落。 与文本文档相关的输入输出,使用FILE结构体和相应的一些文件处理函数即可完成。 End