10.3 例题
由于指针的存在,C语言对字符串的操作非常容易。C语言对字符串几乎所有的操作都是通过“char *”类型的指针与字符串结尾的'\0'标志相互配合完成的。
10.3.1 求字符串长度
题目:求字符串长度。
所谓字符串长度是指字符串中'\0'之前有多少个字符,这个'\0'是指字符串中第一个'\0'。C语言提供了求字符串长度的一个库函数strlen()(2),实际上读者也可以容易地写出这个函数。
程序代码10-3
程序输出为:
上面代码中,“const char *”表示指针指向的字符对象在计算长度时不应该被改变。把形参定义为“const”这样的类别可以防止函数中可能的一些错误。尽管“const”这个修饰不是必需的,但由于它可以让代码书写者不关心函数中是否存在误改写指针所指向的对象的情况,也就是不必亲自检查这些错误,因而可以把注意力放到问题本身上面。毫无疑问,这是一个良好的编程习惯。
10.3.2 比较两个字符串的大小
题目:比较两个字符串的大小。
字符串的大小实际是根据字符的编号确定的。比较两个字符串时,若对应字符相同则比较下一个字符,遇到字符不同时,就根据不同字符各自的编号的大小确定字符串的大小。若一直到'\0',对应字符都相同则两字符串相等。如:
程序代码10-4
程序输出如图10-4所示。
图10-4 比较两个字符串的大小
练习
本小节的例题在比较两个字符串“""”时,其输出是很成问题的。请自己完成该题目的编码并弥补这个缺点。
10.3.3 scanf中的转换
题目:输入一字符串,判断是否为一个十六进制整数形式的字符串,如果是,转变成一个“int”量存储。
讨论:这差不多是scanf("%X",&n)所做的事情。在编程之前首先要对输入的情况作适当考察。首先,"%X"所对应的部分应该是以非空白字符开始,然后读取数字字符,遇到空白字符结束。这表明下面的输入都是合法的输入。
很明显,数字字符前面的空白字符应该跳过不读。
很多人容易忽视到下面两种可能。
换句话说,空白字符跳过之后,可能遇到的并不是数字字符而是正负号。这是在编程之前必须考虑到的,否则,程序必然失败。
其他的一些意外也应该在考虑范围之内,比如在遇到非法的字符时应该如何处理。
这个两个“T”就不是十六进制数字。甚至也可能出现如下情况。
如果编程之前没有想到这些,则写出来的代码也是错的,并且很难修改。从这个意义上讲,编程的水平取决于测试的水平。对于本题目来说,全面的测试方案是编程的前提,而且准备这个方案本身比编程要难得多。
如表10-1所示,这些测试用例涵盖了前面所提到的各种可能,这是最基本的测试用例集,更严格的测试则需要更多的测试用例,但这不是本书所主要关注的内容。其中[]表示按照原来格式输出的含义。
表10-1 测试用例
程序代码10-5
请自己根据前面的测试用例进行测试。
代码中用buhefa()函数判断字符是否是合法的十六进制字符,用表达式('0'<=c&&c<='9')判断字符是否为数字字符。C语言也提供了具有类似功能的库函数,这些库函数的函数原型写在“ctype.h”,文件中,在使用这些库函数时,应在调用前写上预处理命令:
下一小节将介绍这些函数的功能。
练习
题目:输入一个字符串,判断是否为一个八进制整数形式的字符串,如果是,转变成int类型量存储。
10.3.4 字符处理库函数
如表10-2所示,使用这些标准函数会使代码更加简洁,在一定程度上也提高了代码的正确性,更重要的是增强了代码的可移植性。要知道,并非所有的环境都使用ASCII码(3),用('A'<=c&&c<='z')这样的表达式来判断“c”,是否是大写字母字符也不是总成立的,然而使用isupper()这样的标准库函数却不存在这样的问题。
表10-2 C语言的字符处理函数
2 对于标准ASCII码(共128个字符)字符集,控制符是指码值为0~31和127的字符。
作为编程练习,不提倡使用标准函数,但在写正规的程序时应尽量使用标准函数,这不但可以增强程序的正确性和运行效率,代码的可移植性也得到提高。
练习
1.使用C语言的标准函数改写程序代码10-5,并进行测试。
2.写出判断一个字符是否是英文字母的表达式。
3.编写程序统计一行字符中空白字符、大写字母、小写字母、数字字符各自的个数。
4.编写程序,结合输入重定向统计一个文本文件中单词数。
5.编写程序,把一字符串的内容复制到一个字符数组中存储。