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结尾处的'\0')。

说明: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库函数的更多相关文章

  1. 《Linux及安全》实践2

    <Linux及安全>实践2 [edited by 5216lwr] 一.Linux基本内核模块 1.1理解什么是内核模块 linux模块是一些可以作为独立程序来编译的函数和数据类型的集合. ...

  2. Linux内核装载和启动一个可执行程序

    “平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 理解编 ...

  3. 第五章 HID设备

    5.1 HID介绍 为简化USB设备的开发过程,USB提出了设备类的概念.所有设备类都必须支持标准USB描述符和标准USB设备请求.如果有必要,设备类还可以自行定义其专用的描述符和设备请求,这分别被称 ...

  4. 实验七:Linux内核如何装载和启动一个可执行程序

    原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linu ...

  5. Linux内核如何启动并装载一个可执行程序

    2016-04-07 张超<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000#/info 一.理解编译链接的 ...

  6. 《Linux内核分析》课程第七周学习总结

    姓名:何伟钦 学号:20135223 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  7. LINUX内核分析第七周学习总结——可执行程序的装载

    LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  8. Linux内核实验作业七

    实验作业:Linux内核如何装载和启动一个可执行程序 20135313吴子怡.北京电子科技学院 [第一部分]理解编译链接的过程和ELF可执行文件格式 1.编译链接的过程 2.ELF可执行文件格式 一个 ...

  9. Linux内核分析-Linux内核如何装载和启动一个可执行程序

    ID:fuchen1994 实验要求: 理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节: 编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态 ...

随机推荐

  1. java回收算法

    两个最基本的java回收算法:复制算法和标记清理算法                 复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B.此为新生代最常用的算法              ...

  2. OC 类的本质和分类

    一.分类 (一)分类的基本知识  概念:Category  分类是OC特有的语言,依赖于类. 分类的作用:在不改变原来的类内容的基础上,为类增加一些方法. 添加一个分类: 文件结构图: 在分类中添加一 ...

  3. DB2性能调优

    1.更新统计信息 --更新数据库所有表统计信息 --连接到数据库(-v选项,表示要回显命令,以下同) db2 -v connect to DB_NAME --查看是否收集过统计信息,什么时候更新的   ...

  4. js中JSON.stringify用于自定义的类

    参考:http://stackoverflow.com/questions/7356694/how-to-json-stringify-a-user-defined-class-in-javascri ...

  5. js数组的方法小结

    js中数组是一种非常常用数据结构,而且很容易模拟其他的一些数据结构,比如栈和队列.数组的原型Array.prototype内置了很多方法,下面就来小小总结一下这些方法. 检测数组就不用多说了,使用EC ...

  6. 关于PermGen space内存溢出错误解决方法

    1.参考: http://blog.csdn.net/fox009/article/details/5633007 http://hi.baidu.com/like_dark/blog/item/19 ...

  7. Prism 4 文档 ---第11章 部署Prism应用程序

        要成功移动Prism应用到生产中,需要对部署计划为应用程序的设计过程的一部分.本章介绍了注意事项和你需要采取的准备以部署应用程序,以及你要在用户手中获得部署程序所需要采取的行动.     Si ...

  8. start with...connect by子句的浅用

    start with的用法,其基本语法如下: select … from tablename start with 条件1connect by 条件2where 条件3; 但是我在pl/sql中写入以 ...

  9. 基于Dlib、OpenCV开发人脸识别程序的开发建议

    前言 在去年十月的时候参加了一个小比赛,做了一个人脸识别程序并很意外地获得省里面的一等奖,视频演示链接在这里,有同学想要做这方面的毕业设计or课程设计,发一篇博客来分享一下当时的开发过程. 视频演示链 ...

  10. 使用OpenSSL生成证书并配置Https

    1.密钥.证书请求.证书概要说明 在证书申请签发过程中,客户端涉及到密钥.证书请求.证书这几个概念.我们以申请证书的流程说明三者的关系.客户端(相对于CA)在申请证书的时候,大体上有三个步骤: 第一步 ...