C/C++面试常见的几个库函数详解(strcpy,memcpy,memset,atoi...)
2016-03-04 14:44
671 查看
前言
在面试中,常常会被问到几个库函数的实现,虽然代码很短,涉及的细节却特别多,因此特别受面试官青睐,所以要把他们熟记于心,方能应对自如。strcpy()
原型声明:char strcpy(char dest, const char *src);功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
[code]#include <assert.h> char *strcpy(char* dest, const char *src) //point1: 源字符串不改变,需要加const保证 { assert(NULL != dest && NULL != src); //point2:保证指针有效 char * temp = dest; //point3:下面涉及到指针的移动,而我们需要返回dest的头指针,所以dest保留,而使用temp来移动 while ((*temp++ = *src++) != '\0'); /* point4:末尾的'\0'也要复制过来 * 上面先执行 *temp++ = *src++ ,再判断 *src 是否等于'\0' * 所以保证了'\0'先复制后判断 */ return dest; //point5:返回dest头指针,支持链式表达式 }
链式的例子:
[code]int length = strlen(strcpy(strA, strB));
strncpy()
strcpy()是一个高危函数,因为没有指定复制的大小,当dest的空间比src小时,就会出错,而我们没法进行控制。于是有了比较安全的strncpy():[code]//把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。 #include <assert.h> char *strncpy(char* dest, const char *src, unsigned int n) { assert(NULL != dest && NULL != src); char * temp = dest; while (n-- > 0 && (*temp++ = *src++) != '\0'); /* 上面语句两种终止情况: * 1. n = 0,此时下面的语句也不执行,如果未达到src末尾 * 不会自动在dest末尾添加'\0'的,所以需要使用者自己添加 * 2. n > 0 但是src已经到达末尾,那么执行下面语句,将 * dest填充'\0'达到长度n(ANSI C规定) */ while (n-- > 0) *temp++ = '\0'; return dest; }
strcmp()
比较两个字符串设这两个字符串为str1,str2,
若str1==str2,则返回零;
若str1>str2,则返回正数;
若str1
[code]#include <assert.h> int strcmp(const char *str1, const char *str2) { assert(NULL != str1 && NULL != str2); /*不可用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’)。[code]char *strcat(char *dest,const char *src) { assert(NULL != dest && NULL != src); char *temp = dest; while ('\0' != *temp) //自增放在循环里,才可以覆盖'\0' ++temp; while ((*temp++ = *src++) != '\0'); return dest; }
strlen()
功能:计算给定字符串的(unsigned int型)长度,不包括’\0’在内说明:返回s的长度,不包括结束符NULL。
[code]unsigned int strlen(const char *s) { assert(NULL != s); unsigned int len = 0; while (*s++ != '\0') ++len; return len; }
memset()
[code]void *memset(void *s, int ch, size_t n);
函数解释:将s中前n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。
注意,memset是以【字节】为单位进行赋值的,因此下面用法将导致错误:
[code]int arr[5]; memset(array,1,sizeof(arr));
arr指向5个字节的空间,每个都用ASCII为1的字符去填充,转为二进制后,1就是00000001,占一个字节。一个INT元素是4字节,合一起就是00000001000000010000000100000001,就等于16843009,就完成了对一个INT元素的赋值了。所以上面结果不是1而是16843009!
[code]void *memset(void *s,int c,unsigned int n) //point1:s指针类型未知,另外,n为字节数! { assert(NULL != s); void *temp = s; while (n--) { *(char *temp) = (char)c; //point2:转化为字符(1字节) temp = (char *)temp + 1; //point3:不能自增,因为不知道指针类型 } return s; }
memcpy()
内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。[code]void *memcpy(void *dest, const void *src, size_t n) { assert(NULL != dest && NULL != src); int i = 0; void *temp = dest; while (i < n) { *((char *)temp + i) = *((char *)src + i); //未知类型,不能自增 ++i; } return dest; }
atoi()
这个函数就比较经典了,面试常常出现,因为可以考察各种特殊情况:空指针、空串、正负号、非法字符、溢出等等。最大的int:0x7FFF FFFF;
最小的int:0x8000 0000;
[code]enum = {Invalid = 0, Valid}; bool errno = Invalid; int atoi(const char * str) { long long num = 0; //point1:可能溢出,所以用long long存 errno = Invalid; if (NULL != str && *str != '\0') //point2 { bool minus = false; if (*str == '+') { ++str; } else if (*str == '-') { ++str; minus = true; } if ('\0' != *str) //只有符号,Invalid atoiCore(str, minus, num); } return (int)num; //已经检查过溢出,保证了num在int范围内 } void atoiCore(const char *str, bool minus, long long &num) { while ('\0' != *str) { if (*str >= '0' && *str <= '9') { num = num*10 + (*str) - '0'; ++str; if ((!minus && num > 0x7FFFFFFF)||(minus && (-num) < (signed int)0x80000000)) { errno = Invalid; num = 0; return; } } else { errno = Invalid; num = 0; return; } } if (minus) num = -num; errno = Valid; }
最后强调一遍,面试技术岗的,这几个函数一定要熟,一定要熟,一定要熟!!!
相关文章推荐
- leetcode - Create Maximum Number
- 双向链表中基本函数的实现
- 根据c语言程序转换成汇编程序
- MFC编写图形化的c++程序(基于对话框的图形界面程序)
- 谈一谈C++类的“浅复制”和“深复制”
- C++四种强制转换
- c# 调用 C++ dll 传入传出 字符串
- 【C语言】文件定位读取
- 利用第三方软件打包C++程序,其中包含了大量第三方库
- c++ STL string类仿写
- 校门外的树
- 在 .h 和 cpp 中查找 :grep consume ~/test/2016/AMQP-CPP/**/*.cpp ~/test/2016/AMQP-CPP/**/*.h -r
- c语言L->length与L.length
- 8.9 编写函数打开文件用于输入,将文件内容读入 string 类型的 vector 容器,每一行存储为该容器对象 的一个元素。8.10 重写上面的程序,把文件中的每个单词存储为 容器的一个元素
- C语言实现非循环双链表节点的删除(带头结点尾结点)
- C++中的四种转型操作符
- 博客怎么写
- C++下的命名空间
- 求带环的单链表入口位置处的节点
- 仿照CIFAR-10数据集格式,制作自己的数据集