常见的几个库函数
strcpy()
原型声明:char strcpy(char dest, const char *src);
功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
#include <assert.h> char* strcpy(char* dest, const char* src) //point1: 源字符串不变,需要加const保证 { if(src == dest) //重叠 { return src; } assert(dest != NULL && src != NULL); //point2: 保证指针有效 char* temp = dest; //point3: 下面涉及到指针的移动,而我们需要返回dest的头指针。所以dest保留,用temp来移动 while((*temp++ = *src++) != '\0') /*point4: 末尾的'\0'也要复制过来 *上面先执行 *temp++ = *src++ ,再判断*src 是否等于 '\0' *所以保证了 '\0' 先复制后判断 */ return dest; //piont5: 返回dest头指针,支持链式表达式 }
链式的例子:
int length = strlen(strcpy(strA,strB));
strncpy()
strcpy()是一个高危函数,因为没有指定复制的大小,当dest的空间比src小时,就会出错,而我们没法进行控制。于是有了比较安全的strncpy():
把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。
#include <assert.h> char* strncpy(char* dest, const char* src, unsigned int n) { assert(dest != NULL && src!= NULL); char* temp = dest; while(n-->0 && (*temp++ = *src++)!= '\0') /*上面语句两种终止情况: *1、n=0,此时下面的语句不执行,如果未到达src末尾 *不会自动在dest末尾添加 '\0' 的,所以需要使用者自己添加 *2、n>0 但是src已经到达末尾,那么执行下面语句,将 *dest填充 '\0' 达到长度n */ while(n-->0) *temp = '\0'; return dest; }
strcmp()
比较两个字符串
设这两个字符串为str1,str2,
若str1==str2,则返回零;
若str1>str2,则返回正数;
若str1<str2, 返回负数。
#include <assert.h> int strcmp(const char* str1, const char* str2) { assert(dest != NULL && src!= NULL); /*不可用while(*str1++ == *str2++) 来比较,当不相等时仍会执行一次++, *return 返回的比价值实际上是下一个字符。应将++放到循环体中 */ while(*str1 && *str2 && *str1 == *str2) { str1++; str2++; } return *str1 - *str2; /* 若相等,则*str1 - *str2 = '\0' - '\0' = 0; * 否则,*str1 - *str2 != 0; * 因为前面的位都相等,所以只需要比较当前位来确定返回值 */ }
strcat()
把src所指字符串添加到dest结尾处(覆盖dest结尾处的’\0’)。
#include <assert.h> char* strcat(char *dest, const char* src) { assert(dest != NULL && src != NULL); char* temp = dest; while(*temp != '\0) //不要 (*temp++ != '\0') { temp++; } while((*temp = *src) != '\0') { temp ++; src++; } return dest; }
strlen()
功能:计算给定字符串的(unsigned int型)长度,不包括’\0’在内
说明:返回s的长度,不包括结束符NULL。
#include <assert.h> unsigned int strlen(const char* s) { assert(s != NULL); unsigned int len = 0; while(*s++ != '\0') { len++; } return len; }
#include <assert.h> const char* strstr(const char* src, const char* sub) { //入口检查 assert(src != NULL && sub != NULL); const char* bp; const char* sp; // while(*src) { bp = src; //用于src遍历 sp = sub; //用于sub遍历 //每一次src+1 ,然后与 sub 依次比较 while(*bp++ == *sp++) { if(!*sp) { //找到了 return src; } } src++; } return NULL; }
memset()
memset是计算机中C/C++语言函数。将s所指向的某一块内存中的前n个 字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针。
void* memset(void* str,int c, size_t n) { assert(str != NULL); void* s = str; while(n--) { *(char*)s = (char)c; s = (char*)s+1; } return str; }
memcpy()
内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
void* memcpy(void* dest, const void void* src, size_t n) { assert(dest != NULL && src != NULL); char *temp = (char*)dest; char *s_src = (char*)src; while(n--) { *temp++ = *s_src++; } return dest; }
memmove()
memmove() 函数从src内存中拷贝n个字节到dest内存区域,但是源和目的的内存可以重叠。函数返回一个指向dest的指针。
memcpy与memmove唯一区别就是在对待重叠区域的时候,memmove可以正确的完成对应的拷贝,而memcpy不能。
内存覆盖的情形有以下两种,
void* memmove(void* dest, const void* src, size_t n) { assert(dest != NULL && src != NULL); char* psrc = (char*)src; char* pdest = (char*)dest; //pdest在psrc后面,且两者距离小于n时,从尾部开始移动. 其他情况从头部开始移动 if(pdest > psrc && pdest-psrc <n) { pdest = pdest+n-1; //以为第一个值为 p+0 psrc = psrc+n-1; while(n--) { *pdest-- = *psrc--; } else{ while(n--) { *pdest++ = *psrc++; } } } return dest; }