当我们学习了字符串以后,会有极大的时间和机会接触 string.h 头文件中的这些函数。这里会有几个常用的函数拿出来详细的介绍;(有*号的相对来说重要一点,会附带源码)
1、strcat**
在C++中,则存在于头文件中。
返回指向dest的指针。
下来是他的源代码~
char *strcat(char *strDest, const char *strSrc)//将源字符串加const,表明其为输入参数
{
char *address = strDest;//该语句若放在assert之后,编译出错
assert((strDest != NULL) && (strSrc != NULL));//对源地址和目的地址加非0断言
while(*strDest) //是while(*strDest!=’\0’)的简化形式 //若使用while(*strDest++),则会出错
//因为循环结束后 strDest还会执行一次++,那么strDest
{ strDest++;
}
while(*strDest++ = *strSrc++)
{ NULL;
}
return address;
}
2. strncat**
原型: char *strncat(char *dest, const char *src, size_t n);
用法: #include <string.h>
功能: 把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
说明: src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
strncat实现
char * _strncat(char * dest, const char * src, int count) { assert((dest != NULL)&&(src != NULL)); char * ret = dest; while(*dest != '\0') dest++; //这里*dest已经是指到字符串的尾部,就是‘\0’前一个地址。 while(count--) { if((*dest++ = *src ++) == '\0') //if语句中是可以执行计算和赋值的,while也可以。 return ret; }
*dest = '\0'; return ret; }
3.memchr
原型:extern void *memchr(void *str, char ch, unsigned count)
用法:从str所指内存区域的前count个字节查找字符ch。
#include <string.h>
功能:当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回NULL。
说明:返回void*类型指针(或者NULL)。
4.memcmp
原型:intmemcmp(constvoid*buf1,constvoid*buf2,unsignedintcount);
用法:#include或#include
功能:比较内存区域buf1和buf2的前count个字节。
说明:该函数是按字节比较的。
例如:
s1,s2为字符串时候memcmp(s1,s2,1)就是比较s1和s2的第一个字节的ascII码值;
memcmp(s1,s2,n)就是比较s1和s2的前n个字节的ascII码值;
如:char*s1="abc";
char*s2="acd";
intr=memcmp(s1,s2,3);
就是比较s1和s2的前3个字节,第一个字节相等,第二个字节比较中大小已经确定,不必继续比较第三字节了所以 r=-1.
5.memcpy **
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include <string.h>
功能:由src所指内存区域复制count个字节到dest所指内存区域。
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
函数实现:
void *memcpy(void *dest,void *src, unsigned int count)
{
assert((dest!=NULL)&&(src!=NULL));
if(dest==src)
return src;
char* d=(char*)dest;
char* s=(char*)src;
while(count-- > 0) //这个count的初始值每次循环都减1,直到count小于或者等于0的时候,这个循环就结束了,会跳出这个循环
*d++=*s++;
return dest;
}
6.memmove**
原型:void *memmove( void* dest, const void* src, size_t count );
用法:<string.,h>
功能:将指针src指向的前n个字节拷贝到dest指向的前n个内存区域中。当src和desc有重复区域时,先将desc向后移,然后再进行拷贝操作.
说明:memmove用于从src拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。由src所指内存区域复制count个字节到dest所指内存区域。
函数实现:
#include <iostream> #include <cstdio> #include <cstring> void * my_memmove( void * const dest, const char * const src, size_t n ) { if( 0 == n ) { return NULL; } if( NULL == dest || NULL == src ) { return NULL; } char * psrc = (char *)src; char * pdest = (char *)dest; if( pdest <= psrc || pdest > psrc + n ) { std::cout << "forward overlapping" << std::endl; // copy forward direction for( size_t i = 0; i < n; i++ ) { *pdest = *psrc; pdest++; psrc++; } } else { std::cout << "backward overlapping" << std::endl; // copy backward direction pdest = pdest + n; psrc = psrc + n; for( size_t i = 0; i< n; i++ ) { *pdest = *psrc; pdest--; psrc--; } } return dest; }
7.memset**
函数原型:void *memset(void *s, char ch, unsigned n);
用法:<string.h>
功能:将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作。
说明:总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。
例子:
main(){
char *s="Golden Global View";
clrscr();
memset(s,'G',6);//貌似这里有点问题//
printf("%s",s);
getchar();
return 0;
}
【这个问题相当大,程序根本就运行不下去了,你这里的S指向的是一段只读的内存,而你memset又试图修改它,所以运行时要出错,修改办法char *s修改为char s[]】 只能修改和你一致的类型的!
#include <string.h>
#include <stdio.h>
#include <memory.h>
int main(void)
{
char buffer[] = "Hello world/n";
printf("Buffer before memset: %s/n", buffer);
memset(buffer, '*', strlen(buffer) );
printf("Buffer after memset: %s/n", buffer);
return 0;
}
输出结果:
Buffer before memset: Hello world
Buffer after memset: ***********
函数实现 :
8.strchr*
函数原型: char* strchr(char* str,char ch);
函数功能: 找出str指向的字符串中第一次出现字符ch的位置(大小写敏感)
函数用法: 返回指向该位置的指针,如找不到,则返回空指针 <string.h>返回指向第一次出现字符ch位置的指 针,如果没找到则返回NULL。
参数说明: str-待搜索的字符串,ch-查找的字符
代码实现:
char * strchr(const char *str, int ch)
{
while (*str && *str != (char)ch)
str++;
if (*str == (char)ch)
return((char *)str);
return(NULL);
}
9.strcmp AND stricmp*
函数简介原型:extern int strcmp(const char *s1,const char * s2);
用法:#include <string.h> 功能:比较字符串s1和s2。
说明: 当s1<s2时,返回值<0 ; 当s1=s2时,返回值=0 ; 当s1>s2时,返回值>0 , 即:两个字符串自左向右逐个字 符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。如: "A"<"B" "a">"A" "computer">"compare" 特别注意:strcmp(const char *s1,const char * s2)这里面只能比较字符串,数 不能比较 字等其他形式的参数。
功能:比较字符串s1和s2。
一般形式:strcmp(字符串1,字符串2) 说明: 当s1<s2时,返回值<0 当s1=s2时,返回值=0 当s1>s2时,返回值>0
注意不同的字符串长度也可以比较,他只是从第一个字符开始比较ASCII码值.
函数实现:
int __cdecl strcmp (constchar * src,constchar * dst)
{
int ret = 0 ;
while( ! (ret = *(unsignedchar *)src - *(unsignedchar *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
elseif ( ret >0 )
ret = 1 ;
return( ret );
}
然而我觉得strcmp其实就够了。。。 人家区分大小写,这个stricmp就显得有点多余了... 他就是不区分大小写。
11.strcpy***
原型声明:extern char *strcpy(char* dest, const char *src);
头文件:#include
功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
这个大家常用的函数。。。很常见
代码实现:
#inlcude<assert.h>
char *strcpy(char *dst,const char *src)
{
assert((dst!=NULL)&&(src!=NULL));//assert的作用是现计算表达式expression,如果其值为假(即为0), 那么它先向stderr打印一条出错信息,然后通过调用abort来终止程序运行。:
char *tmp= dst;
while((*dst++= *src++) ; //这里如果dst=‘\0’那么det的ASCLL码值为0所以执行完判断就结束了,但是这里 赋值就在判断里,所以完整的拷贝下来;
return tmp;
}
12.strcspn
函数原型:extern int strcspn(char *str1,char *str2)
参数说明:str1为参照字符串,即str2中每个字符分别与str1中的每个字符比较。
所在库名:#include <string.h>
函数功能:以str1为参照,比较字符串str2中的字符是否与str中某个字符相等(也就是检索str2中的字符是否在str1中存在),如果第一次发现相等,则停止并返回在str1中这个匹配相等的字符的索引值,失败则返回str1的长度。
返回说明:返回在str1中这个匹配相等的字符的索引值,是一个整数值。
13.strlen***
原型:extern unsigned int strlen(char *s);
头文件:string.h
格式:strlen (字符数组名)
功能:计算字符串s的(unsigned int型)长度,不包括'\0'在内
说明:返回s的长度,不包括结束符NULL。
代码实现:
#include<assert.h>
char *strlen(const char *det)
{
int count=0;
while(*det++);
}
他统计是并不包括那个 '\0'
14.strncmp*
原型:int strncmp(char *str1, char *str2, int maxlen);
头文件: #include<stdio.h>
功能:比较字符串str1和str2的大小,如果str1小于str2,返回值就<0,反之如果str1大于str2,返回值就>0,如果str1等于str2,返回值就=0,len指的是str1与str2的比较的字符数。此函数功能即比较字符串str1和str2的前len个字符。
说明:此函数功能即比较字符串str1和str2的前maxlen个字符。如果前maxlen字节完全相等,返回值就=0;在前maxlen字节比较过程中,如果出现str1[n]与str2[n]不等,则返回(str1[n]-str2[n])
函数实现:跟strcmp实现也很接近.~~~
15.strncpy***
原型:char *strcpy(char *dest, char *src);
头文件:#include<stdio.h>
功能:把src所指由'\0'结束的字符串复制到dest所指的数组中。
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
注意:当src串长度>dest串长度时,程序仍会将整个src串复制到dest区域,可是dest数组已发生溢出。
因此会导致dest栈空间溢出以致产生崩溃异常。如果不考虑src串的完整性,可以把dest数组最后一元素置为NULL,从dest串长度处插入NULL截取字串。
函数实现:和strcpy很接近.
16.strstr**
函数原型:extern char *strstr(char *haystack, char *needle)
所在库名:#include <string.h>
函数功能:从字符串haystack中寻找needle第一次出现的位置,但是该函数不比较结束符NULL。
参数说明:haystack为一个源字符串的指针,needle为一个目的字符串的指针。
返回指向第一次出现needle位置的指针,如果没找到则返回NULL。
函数实现:
char *myStrstr(const char *target, const char *pattern)
{
assert(target);
assert(pattern);
const char *t_start = target;
const char *p_start = pattern;
const char *t_old = target;
while (*t_old != '\0'){
t_start = t_old;
while (*t_start != '\0' && *p_start != '\0'){
if (*t_start == *p_start){
t_start++, p_start++;
continue;
}
else{
p_start = pattern;
t_old++;
break;
}
}
if ( *p_start == '\0' ){
return t_old;
}
if ( *p_start != '\0' && *t_start == '\0'){
break;
}
}
return NULL;
}
17.strrchr*
函数原型:extern char * strrchr (const char *s, int c)
参数说明:s为一个字符串的指针,c为一个待查找字符。
所在库名:#include <string.h>
函数功能:查找在s字符串中最后一次出现字符c的位置。
返回说明:如果str中存在字符ch,返回出现ch的位置的指针;否则返回NULL。
函数的实现:
char * my_strrchr(const char * str,int ch)
{
char *p = (char *)str;
while (*str) str++;
while (str-- != p && *str != (char)ch);
if (*str == (char)ch)
return( (char *)str );
return(NULL);
}
其实我把这些整合出来一方面是多多认识这些字符串的函数,丰富自己的知识,一方面通过实现这些库函数和他的源代码就行对比,学习大师编程的思想和套路。 而且整合出来也方便大家查阅。后面的函数实现里的注释我会慢慢加上的。写这个用了差不多半周,有点心累....... 毕竟菜鸡0.0 (带星号的一定要熟悉熟悉更熟悉,以后可能把有些的拿出来细细的写一篇,比如这个strncpy就很关键,用法很挺多的。)