纯C 字符串操作函数 实现 (strcpy, strncpy, memcpy, memset, strcat, strlen ... )
来源:互联网 发布:天星教育php招聘 编辑:程序博客网 时间:2024/05/16 06:09
转:http://blog.csdn.net/crazyjixiang/article/details/6720236
实现C/C++中的字符串操作函数是很练内功的,别看着这些函数很简单,自己实现起来,还是有许多地方需要考虑的,所以没独立写过的朋友,可以自己敲敲看 . --By Crazybaby
strcpy:
- char* cb_strcpy(char* dst, const char* src) {
- assert((dst!=NULL) && (src!=NULL));
- char* retAddr = dst; /**< retAddr is in static , char retAddr[] will in Stack, So... */
- while ((*(dst++) = *(src++))!='\0') {
- ;
- }
- return retAddr;
- }
strncpy:
- char* cb_strncpy(char* dst, const char* src, size_t size) {
- assert((dst!=NULL) && (src!=NULL));
- char* retAddr = dst; /**< retAddr is in static , char retAddr[] will in Stack, So... */
- int i = 0;
- while (((*(dst++) = *(src++))!='\0') && ((i++) < size)) {
- ;
- }
- *(retAddr+size)='\0'; /**< cut off String */
- return retAddr;
- }
这个strncpy实现版本 和 stdlib.h 下的 strncpy 还是有区别的, 比如
- char a[30];
- strncpy(a, "Hello", 28); //a除了有Hello,之后会有23个repeat '\0' . 这样会有效率的问题.
- char b[30];
- cb_strncpy(b, "Hello", 28); // 而只有 Hello'\0'
CB: strncpy相对于strcpy来说 ,安全性提高了一个等级 . 另外一个要非常注意的地方那个是 strcpy 和 strncpy 都会遇到 '\0' 结束.
另外:当请求的目标地址空间比源字符串空间要小的时候,strncpy 将不再用”\0”来结束字符串。这是一个巨大的隐患,所以还是不安全
memcpy Version 1:
- char* cb_memcpyVer1(char* dst, const char* src, size_t size) {
- assert((dst!=NULL) && (src!=NULL));
- char* retAddr = dst;
- while (size-- > 0) {
- *(dst++) = *(src++);
- }
- return retAddr;
- }
CB: memcpy 和 strncpy 最大的区别是 memcpy不会遇到 '\0' 结束拷贝 .
memcpy Version 2 :
- char* cb_memcpyVer2(char* dst, const char* src, size_t size) {
- assert((dst!=NULL) && (src!=NULL));
- char* retAddr = dst;
- size_t i = 0;
- /* --- 解决数据区重叠问题 --- */
- if ((retAddr>src) && (retAddr<(src+size))) {
- for (i=size-1; i>=0; i--) {
- *(dst++) = *(src++);
- }
- }
- else
- {
- for (i=0; i<size; i++) {
- *(dst++) = *(src++);
- }
- }
- *(retAddr+size)='\0';
- return retAddr;
- }
CB: memcpyVersion1不能防止overlapping区域的问题, Ver2很好的解决了.
memcpy还有种蛋疼的写法:
- void* cb_memcpy(void* dest, const void* src, size_t count)
- {
- char* d = (char*)dest;
- const char* s = (const char*)src;
- /* --- 每次复制8bit --- */
- int n = (count + 7) / 8;
- switch(count & 7)
- {
- case 0: do { *d++ = *s++;
- case 7: *d++ = *s++;
- case 6: *d++ = *s++;
- case 5: *d++ = *s++;
- case 4: *d++ = *s++;
- case 3: *d++ = *s++;
- case 2: *d++ = *s++;
- case 1: *d++ = *s++;
- } while (--n > 0);
- }
- return dest;
- }
memset:
- void* cb_memset(void* buffer, int b, size_t size) {
- assert(buffer!=NULL);
- char* retAddr = (char*)buffer;
- while (size-- > 0) {
- *(retAddr++) = (char)b;
- }
- return retAddr;
- }
Memset使用时误区:
- char a[10];
- memset(a, 0, sizeof(char)*10); //这个操作完全没必要 因为下面这块内存马上要被使用了。
- memcpy(a, "Hello", 5);
strlen:
- int cb_strlen(const char* str) {
- assert(str!=NULL);
- int len = 0;
- while (*str!='\0') { /**< '\0', stop */
- str++;
- len++ ;
- }
- return len;
- }
Recursive strlen:
- int cb_strlen(const char *str)
- {
- if ((str == NULL) || (*str == '\0')) {
- return 0;
- }
- else
- {
- return cb_strlen(str+1)+1; /**< Rescursive */
- }
- }
strcat:
- char* cb_strcat(char* dst, char* src) {
- assert(src!=NULL);
- char* retAddr = dst;
- /* --- Find last position --- */
- while (*dst++ != '\0') {
- ;
- }
- dst--;
- while (*dst++ = *src++) {
- ;
- }
- return retAddr;
- }
strcmp:
- int cb_strcmp(char* str, char* str2) {
- assert((str!=NULL) && (str2!=NULL));
- char* pStr = str;
- char* pStr2 = str2;
- while (*pStr && *pStr2 && (*pStr==*pStr2)) {
- pStr++;
- pStr2++;
- }
- return (*pStr - *pStr2); /**< 相等则为0 , 前者大于后者大于0, 反之小于0 */
- }
strncmp:
- int cb_strncmp(char* str, char* str2, size_t size) {
- assert((str!=NULL) && (str2!=NULL));
- char* pStr = str;
- char* pStr2 = str2;
- while (size-- && *pStr && *pStr2 && (*pStr == *pStr2)) {
- pStr++;
- pStr2++;
- }
- return (*pStr - *pStr2);
- }
strchr:
- char* cb_strchr(char* str, char c){
- assert(str!=NULL);
- char* retAddr = str;
- while (*retAddr!=c) {
- retAddr++;
- }
- if (*retAddr == c) {
- return retAddr;
- }
- else
- {
- return NULL;
- }
- }
这些字符串操作函数实现时要注意这些问题 :
1. 需要检查指针的有效性,一般通过直接和NULL进行比较来判断。
2. 函数需要能够进行链式操作,也就是说 char* a = strcpy(b, "Hello");
3. src的值需要加 const
4. strcnpy 和 memcpy 有 '\0' 判断的区别
5. 内存区重叠问题 :
比如这个程序:
- int main(void) {
- char buffer[]="abcdefg";
- memcpy(buffer, buffer+2 ,3); //buffer+2(从c开始 长度3个 cde)
- printf("%s", buffer);
- }
这个结果为: cdedefg .
再看下面这个程序:
- int main(void) {
- char buffer[]="abcdefg";
- memcpy(buffer+2, buffer ,3); //如果你幸运的话 会出现 abcab[d]fg 中括号是随机值
- printf("%s", buffer);
- }
- 纯C 字符串操作函数 实现 (strcpy, strncpy, memcpy, memset, strcat, strlen ... )
- 纯C 字符串操作函数 实现 (strcpy, strncpy, memcpy, memset, strcat, strlen ... ) .
- 纯C 字符串操作函数 实现 (strcpy, strncpy, memcpy, memset, strcat, strlen ... )
- C语言字符串相关库函数的实现strcpy、memcpy、strncpy、strcat、strncpy、memset、memcpy、strcpy
- strlen, strcpy, strcat, strcmp, memset... (字符串操作函数的实现)
- memcpy、strcpy、strncpy、strlen、strcat几个函数的实现
- C语言中strlen、strcpy、strncpy、strcat、strnact、strcmp、memcpy函数的实现
- C语言中strlen、strcpy、strncpy、strcat、strnact、strcmp、memcpy函数的实现
- strcpy/strncpy/strcat/strcmp/strlen函数的c语言实现
- strcpy,strncpy, strlen, strcmp strcat函数实现
- C语言中字符串相关函数的实现(strcat strlen strcmp strcpy memcpy)
- c语言中字符串函数strlen()、strcat()、strcpy()、strcmp()及内存操作函数memset()、memcpy()、memcmp()、memmove()的使用及编码实现
- 模拟实现strcmp,strncmp,strstr,strcat,strncat,strcpy,strncpy,strlen ,memcpy,memmove等函数
- strcpy(),strncpy(),strcmp(),strcat(),memset(),memcpy(),atoi(),
- atoi itoa strcpy strcmp strlen strcat memcpy memset实现
- strcpy、strncpy与memcpy strlen strcat strcmp
- strlen,strcpy,strcat,strcmp四个函数的原型,memcpy,memset的实现
- memcmp,memcpy,memmove,memset,strcat,strcmp,strcpy,strlen 8个函数的实现
- 第十六章:线程栈
- 拖拽到控件
- 调整JVM大小
- mysql 导出备份
- NLS_DATE_FORMAT 环境变量定义
- 纯C 字符串操作函数 实现 (strcpy, strncpy, memcpy, memset, strcat, strlen ... )
- iPhone 5 创建应用程序
- poj1338 poj2591 poj2545 这三道题
- 开源分布式文件系统 MogileFS 和 FastDFS
- android LinearLayout和RelativeLayout实现精确布局
- 使用vs2005单步调试sqlite3.6.23
- sgu 185(最短路+最大流)
- 图像处理与机器视觉的主要任务
- 在Backtrack5中使用msfconsole出现Pcaprub module is not available错误