字符串看似简单,却在面试中层出不穷。做出来关于字符串的题目简单,能够完全准确的写出来不容易。
究其原因,无非以下几点:
1)边界情况处理
2)异常情况处理
3)指针操作
在网易有道的二面过程中,面试官就曾经出过atoi以及itoa的实现这种题目,当时以最快且无bug的形式写出来,面试官很满意。因此对于相关字符串原型的实现,必须熟记于心,熟练于手。
下面我将总结常见字符串常考知识点:
1、atoi实现(字符串转换为整数)
2、itoa实现(整数转换为字符串)
3、strcmp实现(比较两个字符串大小)
4、strcpy实现(拷贝字符串到指定位置)
5、strlen实现(字符串长度)
6、strstr实现(寻找子串出现的位置)
7、memcpy实现(内存级的复制内容)
8、memmove实现(内存级的复制)
9、reverse实现(反转一个字符串)
10、reverse_sentence(反转一句话中的每一个单词)
下面将从源代码级别对各个题目进行讲解。
一、atoi实现(字符串转换为整数)
atoi的原型为 int atoi(const char* str) 。实现atoi需要注意如下几点:
1:输入指针的合法性
2:字符串前面可能包含空格
3:字符串中可能包含正负号
4:字符串可能包含非数字字符
5:字符串转换为数字的规则
6:转换后的整数有可能溢出
上述6点都必须要注意到,面试官看你写的程序着重会看这6点,缺哪一个都会影响你的面试成绩。
//将字符串转换成整数
//作者:张海波
//时间:2013-12-9
int atoi(const char* str)
{
//判断指针是否为NULL
assert( str != NULL);
//去除字符串前面的空格
while(isspace(*str))
++str;
//判断正负号
int sign = 1;
if(*str == '-')
sign = -1;
if(*str == '-' || *str == '+')
++str;
//开始进行转换,直至第一个非数字的字符
int result = 0;
while(isdigit(*str))
{
result = result*10 + (*str-'0');
//判断是否发生溢出
if((result>>31)&0x1 == 1)
{
if(sign > 0)
return INT_MAX;
else
return INT_MIN;
}
++str;
}
//返回转换后的结果
return result;
}
(二)itoa实现(整数转换为字符串)
itoa函数的原型为char* itoa(int value, char* str, int radix) 其中value是待转换的整数,str是转换后字符串的第一个字符,radix是转换进制。
itoa实现需要注意如下几点:
1:判断指针是否为NULL
2:判断输入的整数是否为0
3:整数是否为负,且正负号转换为字符
4:逆向转换规则
//整数转换为字符串
//作者:张海波
//时间:2013-12-9
char* itoa(int value, char* str, int radix)
{
//判断指针是否为NULL
assert( str != NULL);
//判断value是否为0
char* ret = str;
if(value == 0)
{
*str = 0;
++str;
*str = '\0';
return ret;
}
//判断正负,如果为负,转换为正进行处理
int sign = (value < 0 ? -1 : 1);
int a, b;
b = (sign < 0 ? (-1)*value : value);
//开始逐位进行转换
char* p = str;
while( b != 0)
{
a = b % radix;
b = b / radix;
if(a < 10)
*p = a + '0';
else
*p = a - 10 + 'A';
++p;
}
//将符号压入进去
if(sign == -1)
*p++ = '-';
//反转字符串
*p = '\0';
--p;
while(str < p)
{
*str = *p + *str;
*p = *str - *p;
*str = *str - *p;
++str, --p;
}
return ret;
}
(三)strcmp实现(比较两个字符串的大小)
strcmp实现需要注意如下三点:
1、字符串合法性检查
2、源字符串和目标字符串是否指向同一个字符串
3、判断条件
//比较两个字符串的大小
//作者:张海波
//时间:2013-12-10
int strcmp(const char* src, const char* dst)
{
//判断两个指针的合法性
assert(src != NULL && dst != NULL);
//判断两个指针是否指向同一个字符串
if(src == dst)
return 0;
//对每一个字符逐一进行判断
int ret = 0;
while(!(ret = *(unsigned char*)src - *(unsigned char*)dst)
&& *src && *dst){
++src, ++dst;
}
//判断谁大谁小
if(ret < 0)
ret = -1;
else if(ret > 0)
ret = 1;
return ret;
}
(四)strcpy实现(拷贝字符串)
strcpy的实现需要注意如下几点:
1、输入指针合法性检查
2、目标字符串和源字符串是否相同
3、复制规则
//拷贝指定的字符串
//作者:张海波
//时间:2013-12-10
char* strcpy(char* dest, const char* source)
{
//判断两个指针的合法性
assert(dest != NULL && source != NULL);
//判断源字符串和目标字符串是否重合
if(dest == source)
return dest;
//保存目标字符串首地址,并且一一进行复制
char* ret = dest;
while((*dest++ = *source++) != '\0');
return ret;
}