前言
库函数的模拟,看似多此一举,实则汲取精华。
1.字符串函数
1.1字符串控制函数
1.1.1 strlen的模拟
求字符串长度
实现逻辑:
遍历字符串直到 ‘\0’,期间计数
--------------------------------------
size_t strlen( const char *string );
--------------------------------------
//返回值用 int / size_t 各有好处
int MyStrlen(const char* str)
{
assert(str);
int cnt = 0;
while (*str != '\0')
{
str++;
cnt++;
}
return cnt;
}
int main()
{
char arr[] = "bacon";
printf("%d\n", MyStrlen(arr));
return 0;
}
1.1.2 str(n)cpy的模拟
拷贝字符串
实现逻辑:
逐个字符拷贝,直到’\0’
-------------------------------------
char* strcpy(char* dest, const char* src)
-------------------------------------
char* MyStrcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++);
return ret;
}
int main()
{
char str1[30] = "Bacon";
char str2[] = " is your friend.";
MyStrcpy(str1 + 5, str2);
printf("%s\n", str1);
return 0;
}
Bacon is your friend.
------------------------------------------------------------
char* strcpy(char* dest, const char* src, size_t num)
---------------------------------------------------------------
char* MyStrncpy(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* ret = dest;
while (num--)
{
*dest++ = *src++;
}
return ret;
}
int main()
{
char str1[20] = { 0 };
char str2[] = "bacon";
printf("%s\n", MyStrncpy(str1, str2, 4));
return 0;
}
baco
1.1.3 str(n)cmp的模拟
逐个比较字符串中的字符
实现逻辑:
逐个字符比较,如果不等或者比较到了’\0’就跳出,而后判断使循环跳出的两个字符
-----------------------------------------------
int strcmp(const char* str1, const char* str2)
-----------------------------------------------
int MyStrcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 != '\0' && *str2 != '\0' && *str1 == *str2)
{
str1++;
str2++;
}
if (*str1 == *str2)
return 0;
else if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
char str1[] = "abcdef";
char str2[] = "abcdfe";
printf("%d\n", MyStrcmp(str1, str2));
return 0;
}
-1
-----------------------------------------------------
int strncmp(const char* str1, const char* str2, size_t num)
---------------------------------------------------------
int MyStrncmp(const char* str1, const char* str1, size_t num)
{
assert(dest && src);
while (num--)
{
if (*str1!= *str2)
{
if (*str1> *str2)
return 1;
else
return -1;
}
str1++;
str2++;
}
return 0;
}
int main()
{
char str1[] = "abcdef";
char str2[] = "abcdfe";
printf("%d\n", MyStrncmp(str1, str2, 5));
return 0;
}
1.1.3 str(n)cat的模拟
字符串追加
实现逻辑:
先找到dest字符串的结尾,再模拟strcpy
----------------------------------------------
char* strcat(char* dest, const chat* src)
----------------------------------------------
char* MyStrcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
//找到字符串结尾
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++);
return ret;
}
int main()
{
char str1[20] = "bacon";
char str2[] = " king";
printf("%s\n", MyStrcat(str1 , str2));
return 0;
}
bacon king
----------------------------------------------------------
char* strncat(char* dest, const char* src, size_t num);
----------------------------------------------------------
char* MyStrncat(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* ret = dest;
while(*dest != '\0')
{
dest++;
}
while (num--)
{
*dest++ = *src++;
}
return ret;
}
int main()
{
char str1[30] = "Bacon";
char str2[] = " is your friend";
printf("%s\n", MyStrncat(str1, str2, 8));
return 0;
}
Bacon is your
1.1.4 strstr的模拟
查找子串
实现逻辑:
给一个指针p来保存开始匹配的位置并遍历str1,给两个指针 s1、s2 来不断尝试匹配
:如果不另给一个指针p,而且尝试匹配失败了,那就找不回原来的位置重新尝试匹配了
------------------------------------------------
char* strstr(const char* str1, const char* str2)
--------------------------------------------------
char* MyStrstr(const char* str1, const char* str2)
{
assert(str1 && str2);
char* p = str1;
char* s1 = str1;
char* s2 = str2;
while (*p)//str1走完就可以跳出了
{
//找到可能匹配的位置
while (*s1 != *s2)
{
s1++;
}
p = s1;
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return p;
}
else
{
s1 = p + 1;
s2 = str2;
p = s1;
}
}
return NULL;
}
int main()
{
char str1[] = "abbbcdef";
char str2[] = "bbc";
printf("%s\n", MyStrstr(str1, str2));
return 0;
}
1.1.5 strtok的使用
切分字符串:根据给定的分隔符,把分隔符置 ‘\0’ ,并保存当前位置(存在静态区)
- 传 非NULL : 从当前位置开始strtok
- 传 NULL : 从上次保存的位置开始strtok
比较奇怪的函数,此处仅示范使用方法
---------------------------------------------
char* strtok(char* str , const char* sep)
---------------------------------------------
由函数定义:我们需要多次切分的时候——第一次传字符串地址,之后传NULL
int main()
{
char* p = "SiDiuPiDe233@icloud.com";
char sep[] = "@.";
char arr[30];
strcpy(arr, p);
char* i = NULL;
for (i = strtok(arr, sep); i != NULL; i = strtok(NULL, sep))
{
printf("%s\n", i);
}
return 0;
}
SiDiuPiDe
icloud
com
1.1.6 strerror的使用
打印错误码对应的信息
在C语言中设置了一个 名为 “errno” 的全局变量,来保存错误码(不同运行错误的编号)
---------------------------------
char* strerror(int errnum);
-----------------------------------
int main()
{
FILE* p = fopen("test.txt", "r");
if (NULL == p)
printf("%s\n", strerror(errno));
return 0;
}
No such file or directory
1.2 字符串分类函数 和 字符串转换函数
函数 | 说明 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’ |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z或A~Z |
isalnum | 字母或者数字,az,AZ,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
如果他的参数符合下列条件就返回真
汲取:
- 指针使用前 assert
- 用const保护不需要修改的数据
- 比较字符串的时候要加上’\0’的判断,不然结果全看命
- 对于while中的指针的加减需要留心
while(*dest1++)
和
while(*dest2) { dest2++; }
dest1跳出循环后是野指针
dest2跳出循环后指向’\0’
本期分享就到这啦,不足之处望请斧正
培根的blog,和你共同进步!