字符串长度:
字符串以NUL('\0')结尾,包含在 string.h 头文件中。
产度就是包含字符的个数。 标准库保留了所有以 str 开头的函数
库函数 strlen 原型如下:
size_t strlen( char const *string ) ;
注意它的返回值是 size_t 类型,在头文件 stddef.h 中定义,是 usigned int 类型,若是在表达式中使用无符号数,可能出现不可预知的结果。eg:
if( strlen( x ) > = strlen( y ) ) ... 和 if( strlen( x) - strlen( y ) >= 0 )...
事实上它们是不相等的。第二个语句结果永远是真,strlen的结果是无符号数,所以 >= 左边的表达式是无符号数,而无符号数不会是负数。
表达式中如果同时包含signed和unsigned,可能会产生奇怪的结果。比如下面的语句:
if ( strlen( x ) >= 10 )... if ( strlen( x ) - 10 >= 0 )
原因和上面一样,如果你把strlen的返回值转换为int就能够消除这个结果。
提示: 你可能想自己编写库函数,灵活运用 register声明和一些技巧,但,库函数有时候是用汇编语言实现的,目的就是充分发挥机器的特殊字符串操作指令,即使没有,我们应该把时间花在程序其他部分的算法改进上。 寻找一种更好的算法比改进一种差劲的算法要更有效率,复用已经存在的软件要比重新开发一个效率更高。
不受限制的字符串函数:
长度受限制的字符串函数
...
strncpy( buffer, name, SIZE );
buffer[ SIZE - 1 ] = '\0' ;
这样就能够确保它正确工作, strncpy最多向dst复制n个字符(再加一个NUL字符),它不管dst的空间够不够。
字符串查找基础:
第一个查找ch在str第一次出现的位置,第二个查找最后一次出现的位置,没找到都返回NULL指针。
查找任何几个字符:
char *strpbrk ( char const *str, char const *group );
它不是查找特定的字符,而是查找任何一组字符第一次在str中出现的位置。函数将指向第一个匹配group中任何一个字符的位置,未找到返回NULL。
查找一个子串:
char *strstr ( char const *s1, char const *s2 );
函数在s1中查找整个s2第一次出现的位置,没找到返回NULL。如果s2是空指针,则返回s1.
我们可以利用strstr来实现strrstr或者strrpbrk,eg:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *my_strrstr( char const *s1, char const *s2 )
{
register char *last;
register char *current;
last = NULL;
if( *s2 != '\0' ){
current = strstr( s1, s2 );
while( current != '\0' ){
last = current;
current = strstr( last+1, s2 );
}
}
return last;
}
高级字符串查找:
这样,变量len1=2,len2=11.
下面的代码将计算一个指向字符串中第一个非空白字符的指针:
ptr = buffer + strspn( buffer, " \n\r\f\t\v" ) ;
strcspn和strspn刚好相反。
查找标记:
char *strtok ( char *str, char const *sep );
strtok从字符串中隔离各个单独的称为标记的部分,丢弃分隔符。sep参数是字符串,定义了分隔符的字符集合。strtok找到str的下一个标记,并将其用NUL结尾,然后返回一个指向这个标记的指针。
警告: strtok会修改它所处理的字符串,如果源串不能修改,就复制一份拷贝传递给strtok。
流程: 如果strtok的第一个参数不是NULL,函数将找到字符串的第一个标记,strtok同时将保存它在字符串中的位置。如果strtok第一个参数是NULL,函数就在同一个字符串中从这个被保存的位置开始像前面一样查找下一个标记。 如果字符串内不存在更多的标记,strtok函数返回一个NULL指针。 典型的情况下,第一次调用strtok时,向它传递一个指向字符串的指针。 然后,这个函数重复调用(第一个参数为空),知道它返回NULL为止。
例子:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void print_tokens( char *line )
{
static char whitespace[] = " \t\f\r\v\n";
char *token;
for( token = strtok( line, whitespace );
token != NULL;
token = strtok( NULL, whitespace ) )
printf("the next token is :%s\n", token );
}
提取标记的时候,你可以在每次调用strtok函数时使用不同的分隔符集合,当一个字符串的不同部分由不同的字符集合分隔时,这个技巧很好!
警告: 由于strtok函数保存它所处理的函数的局部状态信息,所以你不能用它同时解析两个字符串!!!
字符操作:
最后我们来总结一下字符串吧:
二:不要在表达式中混用有符号数和无符号数。
三:使用strcpy函数把一个长字符串复制到一个较短的数组中。
四:使用strcat函数把一个字符串添加到一个数组中,到时数组溢出。
五:不要把strcmp函数的返回值当做bool值测试
六:不要把strcmp的返回值和1 以及 -1 比较
七:使用并非以NUL字符结尾的字符序列
八:使用strncpy函数产生不以NUL字节结尾的字符串
九:把strncpy函数和strxxx族函数混用
十:忘了strtok函数会修改它所处理的字符串
十一:strtok函数不能同时处理两个字符串
编程提示的总结:
一:不要试图自己编写功能相同的函数来取代库函数(可以模仿写,看源码,做尝试)。
二:使用字符分类和转换函数可以提高函数的移植性。