概述
对个字符串的函数的解释根据的是C语言标准文档
<<INTERNATIONAL ISO/IEC STANDARD 9899>>,完全符合各注意事项可确保您的程序安全无恙,否则您的程序可能会有时段错误,有时不段错误,有时当机,有时不当机.
定义
字符串
字符串是以null结束的字符的序列,它包括第一个null字符,但不包括从第一个null之后的字符
指向字符串的指针
指向字符串的指针是,指向字符串第一字符的指针(低地址)
字符串的长度
在null字符之前的所有字符的总数,不把null算在内<o:p></o:p>
如 “123”的长度是3
字符串的结束位置
指的是\0所在的位置
字符串操作
以\0结束系列
strlen
原型:size_t strlen(const char *s);
功能:算字符串长度,不包括\0
注意事项:
1
指针s 必须合法
2
s所指字符串必须以\0结束
3
所返回的长度是不把结束符号\0算在内的
病例分析<o:p></o:p>
1 产品缺陷分析报告.doc 缺陷11
违反了注意事项3,错误的认为strlen
算出的长度包括\0<o:p></o:p>
<o:p> </o:p>
strchr<o:p></o:p>
原型<o:p></o:p>
#include <string.h>
char strchr(const char s, int c);
描述<o:p></o:p>
The strchr function locates the first
occurrence of c (converted to a char)in the
string pointed to by s. The terminating
null character is considered to be part of the
string.
返回值<o:p></o:p>
The strchr function returns a pointer to the
located character, or a null pointer if the
character does not occur in the string.
函数strchr 返回的指针指向c所在位置.如果c不在字符串s中出现则返回空指针
注意事项<o:p></o:p>
1 指针s必须合法
2 s所指字符串必须以\0结束
3 结束符号\0也参与了搜索,即可以将参数c赋为0,此时返回值将指向s的结束位置
<st1:chmetcnv unitname=”C” sourcevalue=”4” hasspace=”True” negative=”False” numbertype=”1” tcsc=”0” w:st=”on”>4 c</st1:chmetcnv>的取值范围必须是-128到127,如果是其它值,行为是未定义的
<o:p> </o:p>
strrchr
原型<o:p></o:p>
#include <string.h>
char strrchr(const char s, int c);
描述<o:p></o:p>
The strrchr function locates the last
occurrence of c (converted to a char)inthe
string pointed to by s. The terminating
null character is considered to be part of the
string.
返回值<o:p></o:p>
3 The strrchr function returns a pointer to
the character, or a null pointer if c does not
occur in the string.
注意事项<o:p></o:p>
跟函数 strchr 一样,不同之处,只是它从后往前搜索<o:p></o:p>
<st1:chsdate year=”1899” month=”12” day=”30” islunardate=”False” isrocdate=”False” w:st=”on”>7.21.5</st1:chsdate>.7 The strstr function<o:p></o:p>
原型<o:p></o:p>
#include
<string.h><o:p></o:p>
char
strstr(const char s1, const char *s2);<o:p></o:p>
描述<o:p></o:p>
The
strstr function locates the first occurrence in the string pointed to by s1 of
the<o:p></o:p>
sequence
of characters (excluding the terminating null character) in the string pointed
to<o:p></o:p>
by s2.<o:p></o:p>
返回值<o:p></o:p>
The
strstr function returns a pointer to the located string, or a null pointer if
the string<o:p></o:p>
is not
found. If s2 points to a string with
zero length, the function returns s1.<o:p></o:p>
注意事项<o:p></o:p>
1 指针s1合法,指针s2合法<o:p></o:p>
2 s1必须以\0 结束,s2必须以\0结束<o:p></o:p>
3 如果s2所指字符串长度为0,则返回s1<o:p></o:p>
4 如果找不到s2所指字符串,则返回NULL<o:p></o:p>
<o:p> </o:p>
病例分析<o:p></o:p>
1 产品缺陷分析报告.doc 缺陷2
违反了 注意事项 2<o:p></o:p>
<o:p> </o:p>
strcpy
原型<o:p></o:p>
#include <string.h>
char strcpy(char s1,
const char * s2);
Description<o:p></o:p>
The strcpy function
copies the string pointed to by s2 (including the terminating null<o:p></o:p>
character) into the
array pointed to by s1. If copying takes place between objects that<o:p></o:p>
overlap, the behavior is
undefined.<o:p></o:p>
Returns<o:p></o:p>
The strcpy function returns the value of s1.<o:p></o:p>
返回s1
注意事项<o:p></o:p>
1 s2所指字符串必须以\0结束
2 s1所指缓冲区间长度需>= strlen(s2)+1
3 s2所指前strlen(s2)+1个字节,不能s1所指的前 strlen(s2)+1个字节有重叠,否则行为是未定义的
strcat
原型
#include <string.h>
char strcat(char s1,
const char * s2);
描述
The strcat function appends a copy of the
string pointed to by s2 (including the
terminating null character) to the end of
the string pointed to by s1. The initial character
of s2 overwrites the null character at the
end of s1. If copying takes place between
objects that overlap, the behavior is
undefined.
Thestrcat function returns the value of s1.
注意事项:
1 指针
s1合法, 指s2合法
2 s1以\0结束,s2以\0结束
strcmp
原型<o:p></o:p>
#include <string.h>
int strcmp(const char s1, const char s2);
描述<o:p></o:p>
The strcmp function compares the string
pointed to by s1 to the string pointed to by
s2.
返回值<o:p></o:p>
The strcmp function returns an integer
greater than, equal to, or less than zero,
accordingly as the string pointed to by s1
is greater than, equal to, or less than the string
pointed to by s2.
注意事项<o:p></o:p>
1s1 必须以\0结束
2 s2 必须以\0结束
3 如果s1 长度小于s2长度,则s2中只有前strlen(s1)+1个字符对结果有影响
4如果s2 长度小于s1长度,则s1中只有前strlen(s2)+1个字符对结果有影响
5 比较两个字符是按无符号数比较的
<o:p> </o:p>
strn…系列
strncpy
原型
#include <string.h>
char strncpy(char restrict s1,
const char * restrict s2,
size_t n);
描述
The strncpy function copies not more than n
characters (characters that follow a null
character are not copied) from the array pointed to by s2 to the array pointed to by
s1. If copying takes place between objects
that overlap, the behavior is undefined.
If the array pointed to by s2 is a string
that is shorter than n characters, null characters
are appended to the copy in the array
pointed to by s1, until n characters in all have been
written.
<o:p> </o:p>
返回值
The strncpy function returns the value of
s1.
<o:p> </o:p>
注意事项<o:p></o:p>
1 s1 所指的前n个字节是已分配的内存,
2 s2 必须以\0结束, 或者从s2开始的前n个字节都是已分配的内存.
3
如果s2 以\0结束,则s2所指的前 strlen(s2)+1个字节不能与 s1所指的前n个字节重叠
如果s2不以\0结束,则则s2所指的前n个字节不能与 s1所指的前n个字节重叠
4
如果s2所指的前n个字节不含 \0,则经过拷贝后s1不以\0 结束.
病例分析<o:p></o:p>
病例1
int main()
{
char
src[]=”123”;<o:p></o:p>
char dst[4];<o:p></o:p>
strncpy(dst,src,8);<o:p></o:p>
return 0;<o:p></o:p>
}
违反了注意事项1,此代码在应用层会内存出错,但在内核不会出错.因为C库遵守了ISO C标准,会拷贝够8个字符(通过补若干个\0),而LINUX内核的代码出于对效率的考虑,只拷贝了4个字符.<o:p></o:p>
<o:p> </o:p>
病例2
int main()
{
char src[]=”<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”123” unitname=””” w:st=”on”>123”;
strncpy(src,src,4);
return 0;
}
违反了注意事项2,行为是未定义的,在某些编译器下会出错,某些编译器下不会出错.<o:p></o:p>
病例3
int main()
{
char src[]=”<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”12345” unitname=””” w:st=”on”>12345”;
char buf[6];
strncpy(buf,src,5);
printf(“%d\n”,strlen(buf); //(1)在此当机
return 0;
}
违反了注意事项4,buf 不以\0结束.在(1)中当机,此错误因在调用strncpy时不出错,在后续代码中才出错,非常难查.<o:p></o:p>
<o:p> </o:p>
strncat
原型<o:p></o:p>
#include <string.h>
char strncat(char restrict s1,
const char * restrict s2,
size_t n);
描述<o:p></o:p>
The strncat function appends not more than
n characters (a null character and
characters that follow it are not appended)
from the array pointed to by s2 to the end of
the string pointed to by s1. The initial
character of s2 overwrites the null character at the
end of s1. If copying takes place between objects that overlap, the
behavior is undefined.
. A terminating null character is always
appended to the result.
<o:p> </o:p>
返回值<o:p></o:p>
The strncatfunction returns the value of
s1.
注意事项<o:p></o:p>
1 s1 所指缓冲区间必须>= strlen(s1)+n+1个字节
2 拷贝的结果始终以\0结束,这点跟strncpy是不一样的
<o:p> </o:p>
病例分析:
int main()
{
char str1[]=”<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”123” unitname=””” w:st=”on”>123”;
char str2[]=”abcd”;
int
len1;
int
len2;
int
len;
char * obj;
<o:p> </o:p>
len1 = strlen(str1);
len2 = strlen(str2)
len
=len1 +len2;
obj = malloc(len);
strcpy(obj,str1);
#if 0
strncpy(obj+len1,str2,len2);
#else
strncat(obj, str2,strlen(s2));
#endif
return 0;
}
<o:p> </o:p>
说明: #else …
#endif之间的代码将导致内存出错,
obj至少要len+1个字节.
#if 0
… #else之间的代码不会出现内存错误,但为后续代码埋藏了隐患,因为obj
无\0结束符.
strncmp
原型<o:p></o:p>
#include <string.h>
int strncmp(const char s1, const char s2,
size_t n);
描述<o:p></o:p>
The strncmp function compares not more than
n characters (characters that follow a
null character are not compared) from the
array pointed to by s1 to the array pointed to
by s2.
返回值
The strncmp function returns an integer
greater than, equal to, or less than zero,
accordingly as the possibly null-terminated
array pointed to by s1 is greater than, equal
to, or less than the possibly
null-terminated array pointed to by s2.
注意事项
1 s1 长度>=n
2 s2长度>=n
3 返回值的符号以比较过程中第一对不相等的字符为准.假设第一对不相等的字符为a,b
如果a>b 返回的是正数,否则是负数.如果整个比较过程没发现不相等的字符对,则返回0.
4 s1,s2 从第n+1个字符开始的字符(如果存在的话)对比较结果无影响
5 n>=0
<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”True” sourcevalue=”6” unitname=”C” w:st=”on”>6 C</st1:chmetcnv>标准明确规定在比较过程中,将每个字符解释为unsigned
char
实例分析<o:p></o:p>
实例一
strncmp(“<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”123” unitname=””” w:st=”on”>123”,”<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”1234” unitname=””” w:st=”on”>1234”,3)
返回值为0
strncmp(“<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”123” unitname=””” w:st=”on”>123”,”<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”1234” unitname=””” w:st=”on”>1234”,4)
返回值<0
strncmp(“<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”123” unitname=””” w:st=”on”>123”,”<st1:chmetcnv tcsc=”0” numbertype=”1” negative=”False” hasspace=”False” sourcevalue=”1234” unitname=””” w:st=”on”>1234”,5)内存出错
实例二
include <stdio.h>
#include <string.h>
int main()
{
char
src[]=”123”;
char
obj[256]={‘1’,’2’,’3’,-1};
int
ret;
ret
= strcmp(obj,src);
printf(“%d\n”,ret);
<o:p> </o:p>
return
0;
<o:p> </o:p>
}VC gcc的测试结果都是输出1,按C标准解释结果应该是>0
总结
1 不要人为的假设一个字符串一定是以\0结束的,特别是对网络中的数据包.
2在无校验码的情况下,不建议在网络传输一个以\0结束的字符串.因为传输过成会出错
3如果要传\0结束的字符串给驱动,建议实现驱动的ioctl时在传入参数时加上magic number,确保此参数来自你的应用程序.
4strncpy的执行结果不一定
含有\0,strncat的结果一定含有0
5 在调用拷贝函数strcp strncpy 连接函数strcat strncat 确保你分配的缓冲区间足够大