首先讨论一个有关的话题,关于字符串结束符:'\0':
1、‘\0’是转移字符,意思是告诉程序,这不是字符0;
2、'\0'在内存里就是8位的00000000,而0则是'\0'的ASCII码表示,是第一个ASCII码,也叫NUL,数字0的ASCII码是48。
3,、在调试程序时,'\0'可以看到在内存里面是0,这是ASCII码的表示,也可以看作是一个unsigned int类型。
NUL: 0x00,0值字符,用于结束ASCII字符串,和'\0'类似(可以理解为别名),但是在c/c++中没有定义,如果要使用的话,需要自定义为 #define NUL '\0';
NULL: 定义为0或0L或(void *)0,用于指示一个指针值是空,即什么都不指;
NULL是在<stddef.h>头文件中专门为空指针定义的一个宏。NUL是ASCII字符集中第一个字符的名称,它对应于一个零值。C语言中没有NUL这样的预定义宏。注意:在ASCII字符集中,数字0对应于十进制值48,不要把数字0和'\0'(NUL)的值混同起来。
NULL可以被定义为(void *)0,而NUL可以被定义为'\0'。NULL和NUL都可以被简单地定义为0,这时它们是等价的,可以互换使用,但这是一种不可取的方式。为了使程序读起来更清晰,维护起来更容易,你在程序中应该明确地将NULL定义为指针类型,而将NUL定义为字符类型。
字符串操作函数的列表链接:http://see.xidian.edu.cn/cpp/u/hs2/
1.strcpy函数:
具体实现:
char * __cdecl strcpy(char * dst, const char * src)
{
char * cp = dst;
while( *cp++ = *src++ ); /* Copy src over dst */
return( dst );
}
存在问题分析:
1.如果源字符串的空间大于目标字符串的空间,有可能出现对未分配内存区域进行写的情况;
2.strncpy函数:为了解决上面的问题,引入了这个strncpy函数
具体实现:
char * __cdecl strncpy ( char * dest, const char * source, size_t count)
{
char *start = dest;
while (count && (*dest++ = *source++)) /* copy string */
count--;
if (count) /* pad out with zeroes */
while (--count)
*dest++ = '\0';
return(start);
}
存在问题分析:
1、如果count的大小大于dest的长度,那么还是会出现上面所说的对未分配内存进行写操作的情况,所以在调用的时候,调用者自己必须清楚这个问题。
2、如果count的大小为n,而source的长度大于n,dest的空间长度也大于n,那么在拷贝完成后,dest里面的内容会缺少字符串结束符'\0',
(例如count为3,source为“qwert”,dest为“yuiop”,则dest里面的内容为'qweop',在e后面没有字符结束标志字符'\0'。所以需要开发者手动加入'\0'到dest中。
3.strcmp函数:
具体实现:
int __cdecl strcmp (
const char * src,
const char * dst
)
{
int ret = 0 ;
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
4.strncmp函数
具体实现:
int __cdecl strncmp ( const char * first, const char * last, size_t count)
{
if (!count)
return(0);
while (--count && *first && *first == *last)
{
first++;
last++;
}
return( *(unsigned char *)first - *(unsigned char *)last );
}
/*
*Exit:
* returns <0 if first < last
* returns 0 if first == last
* returns >0 if first > last
*/
分析:该函数需要注意的地方是返回值,当*first>*last的时候,返回值是一个>0的数,当*first<*last的时候,返回值是一个<0的数
5.strcat函数
具体实现:
char * __cdecl strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}
问题分析:
strcat函数可能存在对dst开始的后面实际未分配的地址进行写操作的可能。
6.strncat
具体实现:
char * __cdecl strncat (char * front, const char * back, size_t count)
{
char *start = front;
while (*front++)
;
front--;
while (count--)
if (!(*front++ = *back++))
return(start);
*front = '\0';
return(start);
}
问题分析:该函数保证了front字符串始终以'\0'结尾,但是count的选择还是要自己注意,也有可能出现越界写内存的可能。
7.strnicmp用于windows程序中,对应linux下面的函数名是strncasecmp:
功能:还是比较两个字符串中前n个数字的大小,只不过忽略大小写,即同一个字母的大写和小写看着是相等的。
具体实现:
int __cdecl _strnicmp (
const char * first,
const char * last,
size_t count
)
{
int f,l;
#ifdef _MT
int local_lock_flag;
#endif /* _MT */
if ( count )
{
#if defined (_WIN32)
if ( __lc_handle[LC_CTYPE] == _CLOCALEHANDLE ) {
#endif /* defined (_WIN32) */
do {
if ( ((f = (unsigned char)(*(first++))) >= 'A') &&
(f <= 'Z') )
f -= 'A' - 'a';
if ( ((l = (unsigned char)(*(last++))) >= 'A') &&
(l <= 'Z') )
l -= 'A' - 'a';
} while ( --count && f && (f == l) );
#if defined (_WIN32)
}
else {
_lock_locale( local_lock_flag )
do {
f = _tolower_lk( (unsigned char)(*(first++)) );
l = _tolower_lk( (unsigned char)(*(last++)) );
} while (--count && f && (f == l) );
_unlock_locale( local_lock_flag )
}
#endif /* defined (_WIN32) */
return( f - l );
}
return( 0 );
}
8.strtok和strtok_r函数:
函数实现:
- char *strtok_r(char *s, const char *delim, char **save_ptr) {
- char *token;
- if (s == NULL) s = *save_ptr;
- /* Scan leading delimiters. */
- s += strspn(s, delim);
- if (*s == '\0')
- return NULL;
- /* Find the end of the token. */
- token = s;
- s = strpbrk(token, delim);
- if (s == NULL)
- /* This token finishes the string. */
- *save_ptr = strchr(token, '\0');
- else {
- /* Terminate the token and make *SAVE_PTR point past it. */
- *s = '\0';
- *save_ptr = s + 1;
- }
- return token;
- }
- char *strtok(char *s, const char *delim)
- {
- static char *last;
- return strtok_r(s, delim, &last);
- }
见下面两个链接:
http://blog.csdn.net/liuintermilan/article/details/6280816
http://blog.csdn.net/liuintermilan/article/details/6283705
9.strpbrk函数:
功能描述:依次检验字符串s1中的字符,当被检验字符在字符串s2中也包含时,则停止检验,并返回该字符位置,空字符NULL不包括在内。
具体实现:
10.strchr:
功能描述:查找字符串s中首次出现字符c的位置
函数实现:
char
*
strchr
(
char
* s,
char
c)
{
while
(*s !=
'\0'
&& *s != c)
{
++s;
}
return
*s == c ?s:NULL;
}
11.strstr:
函数原型:extern char *strstr(const char *str1, const char *str2);
功能描述:该函数返回str2第一次在str1中的位置,如果没有找到,返回NULL
char
*
strstr
(constchar*s1,constchar*s2)
{
constchar*p=s1;
constsize_tlen=
strlen
(s2);
for
(;(p=
strchr
(p,*s2))!=0;p++)
{
if
(
strncmp
(p,s2,len)==0)
return
(
char
*)p;
}
return
(0);
}