目录
一. 字符串
在c语言中,没有字符串类型,但是在程序中有经常会对字符串进行处理,所以一般使用字符数组类型存储字符串或使用字符指针类型指向一块字符常量区。
char a[] = “abcdefg”; // 存储在栈区
char* p = “abcdefg”; // 存储在字符常量区
//以上两种定义方式都会在字符穿的末尾自动补全‘\0’表示字符串的结束
在c语言中的库函数中,包含了大量对字符串的处理函数,在这篇文章中我们主要实现常用的字符串操作函数。
二. 库函数的实现
1. 字符串长度函数strlen()
功能:计算传入字符串长度,\0
表示字符串结束
返回值:传入字符串长度
库函数原型
size_t strlen(const char* str);
代码实现
// 通过计数器进行统计
size_t my_strlen(const char* string)
{
assert(string != NULL);
int count = 0;
while (*string != '\0')
{
count++;
*string++;
}
return count;
}
// 通过指针距离计算
// 指针-指针=元素个数
size_t my_strlen2(const char* string)
{
assert(string != NULL);
char* pstr = string;
while (*string != '\0')
{
*string++;
}
return string - pstr;
}
2. 字符串拷贝函数strcpy()和strncpy()
- strcpy()
功能:将源串拷贝至目标串,目标串空间要足够可以存储源串,并且会将源串\0
拷贝至目标串空间。
返回值:目标串首地址
库函数原型:
char* strcpy(char* destination, const char* source);
代码实现
char* my_strcpy(char* strDest, const char* strSrc)
{
assert(strDest != NULL && strSrc != NULL);
char* pstrDest = strDest;
const char* pstrSrc = strSrc;
while (*pstrSrc != '\0')
{
*pstrDest++ = *pstrSrc++;
}
*pstrDest = '\0';
return strDest;
}
- strncpy()
功能:拷贝指定个数的字符从源字符串到目标串空间,如果源字符串长度小于指定长度,则再拷贝完源串之后,在目标末尾加\0
,直到够指定长度。
返回值:目标串首地址
库函数原型:
char* strncpy(char* destination, const char* source, size_t num);
代码实现
char* my_strncpy(char* destination, const char* source, size_t num)
{
assert(destination != NULL && source != NULL);
char* tmpDest = destination;
const char* tmpSrc = source;
while (num-- > 0)
{
if (*tmpSrc == '\0')
{
*tmpDest++ = *tmpSrc;
while (num-- > 0)
{
*tmpDest++ = '\0';
}
break;
}
*tmpDest++ = *tmpSrc++;
}
return destination;
}
2.字符串连接函数strcat()和strncat()
- strcat()
功能:在目标串尾部追加源串,目标串空间必须足够容纳源串。
返回值:目标串首地址
库函数原型:
char* strcat(char* destination, const char* source);
代码实现
char* my_strcat(char* strDest, const char* strSrc)
{
//参数有效性检测
assert(strDest != NULL && strSrc != NULL);
//保护参数
char* ptmpDest = strDest;
const char* ptmpSrc = strSrc;
//查找Dest的末尾
while (*ptmpDest != '\0')
ptmpDest++;
while (*ptmpSrc != '\0')
{
*ptmpDest++ = *ptmpSrc++;
}
*ptmpDest = '\0';
return strDest;
}
- strncat()
功能:在目标串尾部追加指定个数的源串,目标串空间必须足够容纳源串。
返回值:目标串首地址
库函数原型:
char* strncat(char* destination, const char* source, size_t num);
代码实现
char* my_strncat(char* destination, const char* source, size_t num)
{
assert(destination != NULL && source != NULL);
char* tmpDest = destination;
const char* tmpSrc = source;
while (*tmpDest != '\0')
{
tmpDest++;
}
while (num > 0 && tmpSrc != '\0')
{
*tmpDest++ = *tmpSrc++;
num--;
}
*tmpDest = '\0';
return destination;
}
3.字符串比较函数strcmp()和strncmp()
- strcmp()
功能:逐个比较两个字符串中的字符,若第一个大于第二个字符串,返回大于0的数,相等返回0,小于返回小于0的数。
库函数原型:
int strcmp(const char* str1, const char* str2);
代码实现
int my_strcmp(char* strDest, const char* strSrc)
{
assert(strDest != NULL && strSrc != NULL);
int ret;
while (*strDest != '\0' || *strSrc != '\0')
{
ret = *strDest - *strSrc;
if (0 != ret)
{
break;
}
*strDest++;
*strSrc++;
}
return ret;
}
- strncmp()
功能:比较字符串中指定个数的字符大小,返回值与上述相同
库函数原型:
int strncmp(const char* str1, const char* str2, size_t num);
代码实现
int my_strncmp(char* strDest, const char* strSrc, size_t num)
{
assert(strDest != NULL && strSrc != NULL);
int ret;
while ((*strDest != '\0' || *strSrc != '\0') && num-- > 0)
{
ret = *strDest - *strSrc;
if (0 != ret)
{
break;
}
*strDest++;
*strSrc++;
}
return ret;
}
4. 字符串查找函数strstr()
功能:在第一个字符串中查找第二个字符串,如果找到则返回查找到位置的首地址,如果没有找到则返回空
库函数原型:
char* strstr(const char* str1, const char* str2);
代码实现(使用bf算法实现,kmp在上一篇文章中以做详细解释)
char* my_strstr(const char* str, const char* modstr)
{
assert(str != NULL && modstr != NULL);
const char* tmpstr = str;
const char* tmpmodstr = modstr;
int i = 0;
int j = 0;
while (tmpstr[i] != '\0' && tmpmodstr[j] != '\0')
{
if (tmpstr[i] == tmpmodstr[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
}
//说明已经到达模式串尾,匹配完成
if (tmpmodstr[j] == '\0')
{
return tmpstr + i - j;
}
return NULL;
}