编程实现C库函数
1.memcpy函数
memcpy 函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);拷贝多少个?有一个size变量控制拷贝的字节数;
函数原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:可以拷贝任何类型的对象,因为函数的参数类型是void*(未定义类型指针),也就是说传进去的实参可以是int*,short*,char*等等,但是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节;
- /********memcpy()函数原型为:void* memcpy(void* dest, const void* src, size_t n); 返回指向dest的空类型指针*********/
- //返回void* 类型的原因,是为了使用链式表达,即strlen((char*)(memcpy(dest,src,n)),这样可以直接计算dest的长度,是程序代码更简洁
- /****注意void* 指针的使用,即该函数允许传入任何类型的指针数据****/
- void* memcpy(void *dest,const void *src, size_t n)
- {
- assert((dest != NULL) && (src != NULL));
- char *dest_t = (char*)dest; //转换成字符型一个个复制拷贝,由于函数拷贝的过程是一个字节一个字节的拷贝的,
- //所以实际操作的时候要把void*强制转化为char*,
- char *src_f = (char*)src; //这样在指针加的时候才会保证每次加一个字节
- while (n-- > )
- {
- *(dest_t++) = *(src_f++);
- }
- return dest;//void* 一定要返回一个值(指针),这个和void不太一样!函数返回指向dest的指针
- }
注1:与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。
2:如果目标数组dest本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。

- //memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;
- char a[100], b[50];
- memcpy(b, a,sizeof(b)); //注意如用sizeof(a),会造成b的内存地址溢出。
- strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:
- char a[100], b[50];
- strcpy(a,b);

2.strcpy函数
写法一、
- 1 char * strcpy( char *strDest, const char *strSrc )
- 2 {
- 3 assert( (strDest != NULL) && (strSrc != NULL) );//检测输入指针是否能访问
- 4 char *address = strDest;
- 5 while( (*strDest++ = * strSrc++) != ‘\0’ ); //复制字符串
- 6 return address;//返回指针
- 7 }
写法二、

- /********strcpy()函数原型为:char *strcpy(char* dest, const char *src); 返回指向dest的指针*********/
- //返回char* 类型的原因,是为了使用链式表达,即strlen(strcpy(dest,src)),这样可以直接计算dest的长度,是程序代码更简洁
- char* strcpy(char *dest, char *src)
- {
- if(dest == NULL || src == NULL)
- return NULL;
- char *res = dest;//保存原始dst的首地址
- while(*src != '\0')
- {
- *dest = *src;
- dest++;
- src++;
- }
- *dest = '\0';
- return res;
- }
3.strcat函数
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针。

- #include <stdio.h>
- #include <iostream>
- using namespace std;
- char* strcat(char *dest, char *src)
- {
- if (dest == NULL)
- return NULL;
- if (src == NULL)
- return dest;
- char *head = dest;
- while (*dest != '\0')
- dest++;
- while (*src != '\0')
- {
- *dest = *src;
- dest++;
- src++;
- }
- *dest = '\0';
- return head;
- }
- int main()
- {
- char dest[] = "nihao";
- char src[] = "zhouyang";
- char *res = strcat(dest, src);
- cout << dest << endl;
- system("pause");
- return 0;
- }

4.strcmp函数
功能:比较两个字符串大小。
实际上是对字符的ASCII码进行比较,实现原理如下:首先比较两个串的第一个字符,若不相等,则停止比较并得出两个ASCII码大小比较的结果;如果相等就接着比较第二个字符然后第三个字符等等。无论两个字符串是什么样,strcmp函数最多比较到其中一个字符串遇到结束符'/0'为止,就能得出结果。
返回结果:①str1小于str2,返回负值或者-1(VC返回-1);②str1等于str2,返回0;③str1大于str2,返回正值或者1(VC返回1);

- #include <stdio.h>
- #include <iostream>
- #include <assert.h>
- using namespace std;
- /****strcmp原型: int strcmp(const char *str1, const char *str2)*****/
- int strcmp(const char *str1, const char *str2)
- {
- assert((str1 != NULL) && (str2 != NULL));
- while ((*str1 != '\0') && (*str2 != '\0'))
- {
- if (*str1 == *str2)
- {
- str1++;
- str2++;
- }
- else
- {
- if (*str1 > *str2)
- return 1;
- else
- return -1;
- }
- }
- if (*str1 == '\0' && *str2 == '\0')
- return 0;
- else if (*str1 == '\0' && *str2 != '\0')
- return -1;
- else if (*str1 != '\0' && *str2 == '\0')
- return 1;
- }
- int main()
- {
- char *str1 = "78";
- char *str2 = "789";
- int res = strcmp(str1, str2);
- cout << res << endl;
- system("pause");
- return 0;
- }

5.strlen函数
功能:返回字符串的长度。

- #include <stdio.h>
- #include <iostream>
- #include <assert.h>
- using namespace std;
- /********strlen()函数原型为:int strlen(const char *src); 返回字符串的长度*********/
- size_t strlen(const char *str)
- {
- assert(str != NULL);
- int num = 0;
- while(*str != '\0')
- {
- str++;
- num++;
- }
- return num;
- }
- int main()
- {
- char *str = "123456";
- int temp = strlen(str);
- cout << temp << endl;
- return 0;
- }

6.strncpy
功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。
要求:如果n > dest串长度,dest栈空间溢出产生崩溃异常。该函数注意的地方和strcpy类似,但是n值需特别注意。

- #include <iostream>
- #include <stdio.h>
- using namespace std;
- /***string.h,char *strncpy(char *dest, const char *src, size_t n),
- 把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。**/
- char* mystrncpy(char *dest, const char *src, size_t n)
- {
- if (dest == NULL || src == NULL || n < 0)
- return NULL;
- char *res = dest;
- while (n--)
- {
- *dest = *src;
- dest++;
- src++;
- }
- *dest = '\0';
- return res;
- }
- int main()
- {
- char *src = "hello world";
- char c[10];
- char *res = mystrncpy(c, src, 7);
- cout << res << endl;
- system("pause");
- return 0;
- }

7.strstr函数
功能:给出字符串str1, str2,判断str2是否为str1的子字符串,如果是,返回str2在str1中对应的起始地址。

- #include <stdio.h>
- #include <iostream>
- #include <assert.h>
- using namespace std;
- /****
- 函数原型:
- extern char *strstr(const char *str1, const char *str2);
- str1: 被查找目标 string expression to search.
- str2: 要查找对象 The string expression to find.
- 返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。
- ****/
- const char* strstr(const char *str1, const char *str2)
- {
- if (str1== NULL || str2 == NULL)
- return NULL;
- const char *temp = str1;
- const char *res = str2;while (*str1 != '\0')
- {
- temp = str1;
- res = str2;
- while (*temp== *res){
- temp++;
- res++;
- }
- if (*res == '\0')return str1;
- str1++;
- }
- return NULL;
- }
- int main()
- {
- char *src = "1234567";
- char *dest = "345";
- const char *res = strstr(src, dest);
- cout << res<< endl;//cout<<重载了,会直接输出字符串内容而不是地址
- system("pause");
- return 0;
- }

8.printf()
写法一
- #include <stdio.h>
- #include <stdarg.h>
- /*
- * 函数名: myPrintf
- * 函数功能: 打印格式字符串
- * 参数: 1. 包含格式符的字符串地址 2.可变参
- * 返回值: 无
- */
- void myPrintf(char *s, ...)
- {
- int i = ;
- /* 可变参第一步 */
- va_list va_ptr;
- /* 可变参第二部 */
- va_start(va_ptr, s);
- /* 循环打印所有格式字符串 */
- while (s[i] != '\0')
- {
- /* 普通字符正常打印 */
- if (s[i] != '%')
- {
- putchar(s[i++]);
- continue;
- }
- /* 格式字符特殊处理 */
- switch (s[++i]) // i先++是为了取'%'后面的格式字符
- {
- /* 根据格式字符的不同来调用不同的函数 */
- case 'd': printDeci(va_arg(va_ptr,int));
- break;
- case 'o': printOct(va_arg(va_ptr,unsigned int));
- break;
- case 'x': printHex(va_arg(va_ptr,unsigned int));
- break;
- case 'c': putchar(va_arg(va_ptr,int));
- break;
- case 'p': printAddr(va_arg(va_ptr,unsigned long));
- break;
- case 'f': printFloat(va_arg(va_ptr,double));
- break;
- case 's': printStr(va_arg(va_ptr,char *));
- break;
- default : break;
- }
- i++; // 下一个字符
- }
- /* 可变参最后一步 */
- va_end(va_ptr);
- }
写法二、
- /*(转载)
- * A simple printf function. Only support the following format:
- * Code Format
- * %c character
- * %d signed integers
- * %i signed integers
- * %s a string of characters
- * %o octal
- * %x unsigned hexadecimal
- */
- int my_printf( const char* format, ...)
- {
- va_list arg;
- int done = ;
- va_start (arg, format);
- while( *format != '\0')
- {
- if( *format == '%')
- {
- if( *(format+) == 'c' )
- {
- char c = (char)va_arg(arg, int);
- putc(c, stdout);
- } else if( *(format+) == 'd' || *(format+) == 'i')
- {
- char store[];
- int i = va_arg(arg, int);
- char* str = store;
- itoa(i, store, );
- while( *str != '\0') putc(*str++, stdout);
- } else if( *(format+) == 'o')
- {
- char store[];
- int i = va_arg(arg, int);
- char* str = store;
- itoa(i, store, );
- while( *str != '\0') putc(*str++, stdout);
- } else if( *(format+) == 'x')
- {
- char store[];
- int i = va_arg(arg, int);
- char* str = store;
- itoa(i, store, );
- while( *str != '\0') putc(*str++, stdout);
- } else if( *(format+) == 's' )
- {
- char* str = va_arg(arg, char*);
- while( *str != '\0') putc(*str++, stdout);
- }
- // Skip this two characters.
- format += ;
- } else {
- putc(*format++, stdout);
- }
- }
- va_end (arg);
- return done;
- }
- C常用库函数实现
- // ---------- strlen -------------
- int strlen(char *t){
- int length = ;
- if(t == NULL)
- return -;
- while (*t != '\0') {
- t++;
- length++;
- }
- return length;
- }
- size_t strlen(const char *s)
- {
- const char *sc;
- for (sc = s; *sc != '\0'; ++sc);
- return sc - s;
- }
- // ---------- trim -------------
- void ltrim ( char *s )
- {
- char *p;
- p = s;
- while ( *p == ' ' || *p == '\t' ) {p++;}
- strcpy ( s,p );
- }
- void rtrim ( char *s )
- {
- int i;
- i = strlen ( s )-;
- while ( ( s[i] == ' ' || s[i] == '\t' ) && i >= ) {i--;};
- s[i+] = '\0';
- }
- void trim ( char *s )
- {
- ltrim ( s );
- rtrim ( s );
- }
- // ---------- strcpy -------------
- char *strcpy(char *dest, const char *src)
- {
- char *tmp = dest;
- while ((*dest++ = *src++) != '\0');
- return tmp;
- }
- // ---------- strcat -------------
- char *strcat(char *dest, const char *src)
- {
- char *tmp = dest;
- while (*dest)
- dest++;
- while ((*dest++ = *src++) != '\0');
- return tmp;
- }
- // ---------- strstr -------------
- char *strstr(const char *s1, const char *s2)
- {
- int l1, l2;
- l2 = strlen(s2);
- if (!l2)
- return (char *)s1;
- l1 = strlen(s1);
- while (l1 >= l2) {
- l1--;
- if (!memcmp(s1, s2, l2))
- return (char *)s1;
- s1++;
- }
- return NULL;
- }
- // ---------- memcmp -------------
- int memcmp(char *cs, char *ct, size_t count)
- {
- char *su1, *su2;
- int res = ;
- for (su1 = cs, su2 = ct; < count; ++su1, ++su2, count--)
- if ((res = *su1 - *su2) != )
- break;
- return res;
- }
- // ---------- strcmp -------------
- int strcmp(const char *cs, const char *ct)
- {
- unsigned char c1, c2;
- while () {
- c1 = *cs++;
- c2 = *ct++;
- if (c1 != c2)
- return c1 < c2 ? - : ;
- if (!c1)
- break;
- }
- return ;
- }
编程实现C库函数的更多相关文章
- 《Linux及安全》实践2
<Linux及安全>实践2 [edited by 5216lwr] 一.Linux基本内核模块 1.1理解什么是内核模块 linux模块是一些可以作为独立程序来编译的函数和数据类型的集合. ...
- Linux内核装载和启动一个可执行程序
“平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 理解编 ...
- 第五章 HID设备
5.1 HID介绍 为简化USB设备的开发过程,USB提出了设备类的概念.所有设备类都必须支持标准USB描述符和标准USB设备请求.如果有必要,设备类还可以自行定义其专用的描述符和设备请求,这分别被称 ...
- 实验七:Linux内核如何装载和启动一个可执行程序
原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linu ...
- Linux内核如何启动并装载一个可执行程序
2016-04-07 张超<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000#/info 一.理解编译链接的 ...
- 《Linux内核分析》课程第七周学习总结
姓名:何伟钦 学号:20135223 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- LINUX内核分析第七周学习总结——可执行程序的装载
LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...
- Linux内核实验作业七
实验作业:Linux内核如何装载和启动一个可执行程序 20135313吴子怡.北京电子科技学院 [第一部分]理解编译链接的过程和ELF可执行文件格式 1.编译链接的过程 2.ELF可执行文件格式 一个 ...
- Linux内核分析-Linux内核如何装载和启动一个可执行程序
ID:fuchen1994 实验要求: 理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节: 编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态 ...
随机推荐
- Krapo 2
The krpano Viewer is a small and very flexible high-performance viewer for all kind of panoramic ima ...
- 『PyTorch』第五弹_深入理解autograd_中:Variable梯度探究
查看非叶节点梯度的两种方法 在反向传播过程中非叶子节点的导数计算完之后即被清空.若想查看这些变量的梯度,有两种方法: 使用autograd.grad函数 使用hook autograd.grad和ho ...
- HDOJ1008
#include "iostream" using namespace std; int main() { ) { int n; cin >> n; ) break; ...
- PHP:第三章——PHP中返回引用的函数
<?php header("Content-Type:text/html;charset=utf-8"); $i=1; function &F(){ global $ ...
- learning shell built-in variables (1)
Shell built-in variables [Purpose] Learning shell built-in variables, example $0,$1,$2,$3,$#, ...
- IScroll的诞生和缺点
转自http://lhdst-163-com.iteye.com/blog/1239784 iscroll.js是Matteo Spinelli开发的一个js文件,使用原生js编写,不依赖与任何js框 ...
- 关于apicloud ios自定义模块引用第三方framework not found for architecture armv7
1 .自定义模块 新建模块必须是静态库 2.使用的第三方framework 必须要把 .h文件开放出来 3.编译要用 真机模式 (上传模块以后,自定义load要编译,用生成的二维码调试) 4. 添加监 ...
- 1.1 C++布尔类型(bool)
注意: c++ 中 cout << true << endl; 输出为 1: 布尔类型(bool)是C++新增的一种基本数据类型.在标准的C语言中并未定义bool类型,如果需 ...
- 玩转X-CTR100 l STM32F4 l OLED显示-SSD1306无字库
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] OLED显示屏具有自发光特性,不需要背光, ...
- 2019.1.10 L223
Heavy rains that brought additional pollution downstream last year contributed to the first decline ...