题目要求

  1.strcpy/memcpy/memmove;

  2.memset函数;

  3.字符串处理函数。

题目分析  

  1.接口定义:

    char * strcpy(char * dest, const char * src);
    void *memcpy(void *memTo, const void *memFrom, size_t size);
    void *memmove(void *dst,const void *src,size_t n);

    函数区别:

    -->strcpy 和 memcpy主要有以下三方面的区别:
      i)复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符串、整型、结构体、类等。
      ii)复制的方法不同。strcpy不需要指定长度,它遇到被复制字符串的结束符"\0”才结束,所以容易溢出。memcpy则是根据第3个参数决定复制的长度。
      iii)用途不同。通常在复制字符串时用strcpy,而需要复制其它类型的数据是用memcpy。

    -->memcpy和memmove区别:当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。

  

代码实现

char * strcpy(char * dest, const char * src) // 实现src到dest的复制
{
if ((src == NULL) || (dest == NULL)) //判断参数src和dest的有效性
{
return NULL;
}
char *strdest = dest; //保存目标字符串的首地址
while ((*strDest++ = *strSrc++)!='\0'); //把src字符串的内容复制到dest下
return strdest;
}
void *memcpy(void *memTo, const void *memFrom, size_t size)
{
if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必须有效
return NULL;
char *tempTo = (char *)memTo; //保存memTo首地址
while(size -- > 0) //循环size次,复制memFrom的值到memTo中
*tempTo++ = * memFrom ++ ;
return memTo;
}
void *memmove(void *dst,const void *src,size_t n)
{
char *dp = (char *)dst;
char *sp = (char *)src;
if(dst==NULL || src==NULL)return NULL;
//非重叠
//dp < sp
//dp > (sp+n)
if(sp>dp||(sp+n)<dp)
{
while(n--)
*(dp++) = *(sp++);
}
else if(sp<dp)//重叠 (此时条件 sp<dp<(sp+n))如果sp==dp则快速的返回
{//反向拷贝
sp += n;
dp += n;
while(n--)
*(--dp) = *(--sp);
}
return dst;
}
void * myMemset(void *ptr,int c,size_t count)
{
void * start = ptr;
if(ptr==NULL)
return NULL;
while(count--)
{
*( char *)ptr = (char )c;
ptr = ( char *)ptr + ; //不转换的话,加1就不清楚就加多少了
}
return start;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> int mystrlen(const char *str); int main(void)
{
char *b = "hellp"; printf("%d\n",mystrlen(b));
return ;
}
int mystrlen(const char *str)
{
int len;
assert(str != NULL);
len = ;
while (*str ++ != '\0')
++ len;
return len;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> char *mystrcat(char *strDes, const char *strSrc); int main(void)
{
char *b = "hellp";
char *a = (char *)malloc(sizeof(char)*);
strcpy(a,"haha"); printf("%s\n",mystrcat(a,b));
return ;
}
char *mystrcat(char *strDes, const char *strSrc)
{
char *address;
assert((strDes != NULL) && (strSrc != NULL));
address = strDes;
while (*strDes != '\0')
++strDes;
while ((*strDes++ = *strSrc++) != '\0');
return address;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> int mystrcmp(const char *s, const char *t); int main(void )
{
char a[],c[];
char *b = "hellp" ,*d = "help"; printf( "%d\n",mystrcmp(b,d));
return ;
}
int mystrcmp(const char *s, const char *t)
{
assert(s != NULL && t != NULL);
while (*s && *t && *s == *t)
{
++ s;
++ t;
}
return (*s - *t);
}
//查找字符串s 中首次出现字符c 的位置
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> char *strchr(const char *str, int c); int main(void )
{
char a[],c[];
char *b = "hellp" ; printf( "%c\n",*(strchr(b,'l' )));
return ;
}
char *strchr(const char *str, int c)
{
assert(str != NULL);
for (; *str != (char )c; ++ str)
if (*str == '\0' )
return NULL;
return str;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> char *mystrncpy(char *strDes, const char *strSrc, unsigned int count); int main(void )
{
char a[],c[];
char *b = "hellp" ; printf( "%s\n",mystrncpy(a,b,));
printf( "%s\n",mystrncpy(c,mystrncpy(a,b,),));
return ;
}
char *mystrncpy(char *strDes, const char *strSrc, unsigned int count)
{
char *address;
assert(strDes != NULL && strSrc != NULL);
address = strDes;
while (count-- && *strSrc != '\0' )
*strDes++ = *strSrc++;
*strDes = '\0';
return address;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> char *myStrCopy(char *strDest,const char *strSrc); int main(void )
{
char a[],c[];
char *b = "hellp" ; printf( "%s\n",myStrCopy(a,b));
printf( "%s\n",myStrCopy(c,myStrCopy(a,b)));
return ;
}
//有返回值是为了链式操作
//源字符串用const,是在接口保证不会改变 strSrc里的值
char *myStrCopy(char *strDest,const char *strSrc)
{
char *start = strDest;
if(strDest==strSrc)// 源和目的重叠
return strDest;
assert(strDest!=NULL || strSrc!=NULL); //判断是否为空
while((*start++ = *strSrc++) != '\0' );
return strDest;
}
#include <stdio.h>

const char *my_strstr(const char *str, const char *sub_str)
{
if(str==NULL || sub_str==NULL)
return NULL;
for(int i = ; str[i] != '\0'; i++)
{
int tem = i; //tem 保留主串中的起始判断下标位置
int j = ;
while(str[tem++] == sub_str[j++])
{
if(sub_str[j] == '\0' )
{
return &str[i];
}
}
} return NULL;
} int main()
{
char *s = "1233345hello" ;
char *sub = "" ;
printf( "%s\n", my_strstr(s, sub));
return ;
}

  

C语言库函数实现 【微软面试100题 第八十三题】的更多相关文章

  1. 栈的push、pop序列 【微软面试100题 第二十九题】

    题目要求: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1.2.3.4.5是某栈的压栈序列,序列4.5.3.2.1是该压栈 ...

  2. 输出1到最大的N位数 【微软面试100题 第六十五题】

    题目要求: 输入数字n,按顺序输出从1到最大的n位10进制数. 例如,输入3,则输出1.2.3....999(最大的3位数). 参考资料:剑指offer第12题. 题目分析: 如果我们在数字前面补0的 ...

  3. 在O(1)时间内删除链表结点 【微软面试100题 第六十题】

    题目要求: 给定链表的头指针和一个结点指针,在O(1)时间删除该结点. 参考资料:剑指offer第13题. 题目分析: 有几种情况: 1.删除的结点是头结点,且链表不止一个结点: 2.删除的结点是头结 ...

  4. C++异常安全的赋值运算符重载 【微软面试100题 第五十五题】

    题目要求: 类CMyString的声明如下: class CMyString { public: CMyString(char *pData=NULL); CMyString(const CMyStr ...

  5. 和为n连续正数序列 【微软面试100题 第五十一题】

    题目要求: 输入一个正数n,输出所有和为n连续正数序列(至少两个). 例如输入15,由于1+2+3+4+5 = 4+5+6 = 7+8 = 15.所以输出3个连续序列1~5,4~6,7~8. 参考资料 ...

  6. 和为s的两个数字 【微软面试100题 第十四题】

    题目要求: 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s.如果有多对数字的和等于s,输出任意一对即可. 例如输入数组{1,2,4,7,11,15}和数字15.由于4+1 ...

  7. 链表中倒数第k个结点 【微软面试100题 第十三题】

    题目要求: 输入一个链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针. 参考资料:剑指offer第15题 题目分析: 1.两个指针,第一个先走k步,然后两个指针同时走,直到第一个走 ...

  8. 求1+2+...+n 【微软面试100题 第十二题】

    题目要求: 要求不能使用乘除法,for/while/if/else/switch/case等关键字以及条件判断语句(A?B:C). 参考资料:剑指offer第46题 题目分析: 方法1:利用类的静态成 ...

  9. 查找最小的k个元素 【微软面试100题 第五题】

    题目要求: 输入n个整数,输出其中最小的k个. 例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4. 参考资料:剑指offer第30题. 题目分析: 解法一: 用快排 ...

随机推荐

  1. 在西雅图华盛顿大学 (University of Washington) 就读是怎样一番体验?

    http://www.zhihu.com/question/20811431   先说学校.优点: 如果你是个文青/装逼犯,你来对地方了.连绵不断的雨水会一下子让写诗的感觉将你充满. 美丽的校园.尤其 ...

  2. 洛谷 P1509 找啊找啊找GF

    题目背景 "找啊找啊找GF,找到一个好GF,吃顿饭啊拉拉手,你是我的好GF.再见." "诶,别再见啊..." 七夕...七夕...七夕这个日子,对于sqybi这 ...

  3. 金庸的武侠世界和SAP的江湖

    2018年10月30日晚,成都地铁一号线,Jerry手机app上突然弹出来一条金庸去世的新闻. Jerry识字很早,小学一年级就开始蹭我父亲的<射雕英雄传>看了.小时候,我爸工作的车间里有 ...

  4. 用批处理设置 wifi 热点,复制保存成 bat 以管理员身份运行即可

    @echo offtitle Wifi 热点控制echo #注意:本文件需以管理员身份运行!# :Beginecho ========================echo 请选择操作:echo 1 ...

  5. Uva 11235 RMQ问题

    RMQ: 有一个不变的数组,不停的求一个区间的最小值. 使用倍增的思想优化到logN; d(i,j) 表示从 i 开始的,长度为2j的一段元素中的最小值. 那么状态转移方程: d(i,j) = min ...

  6. redux详解

    redux介绍 学习文档:英文文档,中文文档,Github redux是什么 redux是一个独立专门用于做状态管理的JS库(不是react插件库),它可以用在react, angular, vue等 ...

  7. MyBatis中解决字段名与实体类属性名不相同的冲突

    一: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致,这样就可以表的字段名和实体类的属性名一一对应上了,这种方式是通过在sql语句中定义别名来解决字段名和属性名的映射关系 ...

  8. war和war exploded的区别

    是选择war还是war exploded 这里首先看一下他们两个的区别: (1)war模式这种可以称之为是发布模式,看名字也知道,这是先打成war包,再发布: (2)war exploded模式是直接 ...

  9. iOS内存区域部分内容

    目前参考这里: https://www.zhihu.com/question/263823072/answer/273452932 以后整理相关的代码问题. 更多参考资料: https://stack ...

  10. Kettle报表自动化

    来自我们牛逼哄哄的东哥的笔记 1.   2. 3. 选择数据库链接 贴报表SQL 4. 文件名:选择路径,excel文件由kettle自动创建,自己只需输入创建文件的名称. 拓展名:后缀写上 5. 此 ...