明白库函数的实现过程,能帮助我们去更好的使用和理解它们。下面就对于字符串函数:strlen(),strcpy(),strcmp(),strstr(),内存函数:memcpy(),memmove(),进行实现~
一、字符串函数
1.求字符串的实际长度:strlen()
库函数中是这样声明的:
代码实现:
#include<stdio.h>
#include<windows.h>
size_t myStrlen(const char* str)
{
//if语句校验合法性
if (str == NULL){
return 0;
}
size_t len = 0;
while (str[len]!= '\0'){
len++;
}
return len;
}
int main()
{
char str[] = "hello world";
printf("%d\n",myStrlen(str));
system("pause");
return 0;
}
运行结果:
注意:
①size_t表示无符号整型
②const修饰的变量一般不能改变,为了防止我们在求字符串的长度过程中,修改了字符串的内容,所以需要const来修饰,确保我们的字符串安然无恙~
③在进行计算长度之前,一定要校验,检验字符串的合法性。
2.字符串拷贝函数:strcpy()
库函数中的声明:
代码实现:
#include<stdio.h>
#include<windows.h>
char* myStrcpy(char* dest, const char* src)
{
//if语句校验合法性
if (dest == NULL || src == NULL){
return NULL;
}
char* pdest = dest;
const char* psrc = src;
while (*psrc != '\0'){
*pdest = *psrc;
pdest++;
psrc++;
}
*pdest = '\0';
return dest;
}
int main()
{
char dest[1024] = "hello";
char src[] = "heihei";
printf("%s\n", myStrcpy(dest, src));
system("pause");
return 0;
}
运行结果:
需要注意的是:除了要进行字符串合法性地检验之外,因为我们在进行拷贝,所以要保证目的地的空间足够
3.字符串比较函数:strcmp()
库函数中的声明:
思路:如果str1<str2则返回小于0的数,如:-1
如果str1=str2则返回0
如果str1>str2则返回大于0的数,如:1
代码实现:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
int myStrcmp(const char*str1, const char* str2)
{
//assert检验字符串的合法性
assert(str1!= NULL&&str2!=NULL);
while (*str1 != '\0'&&*str2 != '\0'){
if (*str1<*str2){
return -1;
}else if (*str1 > *str2){
return 1;
}else{
str1++;
str2++;
}
}
//str1<str2,相减之后得到的是小于0的数
//str1=str2,相减之后得到0
//str1>str2,相减之后得到的是大于0的数
return *str1 - *str2;
}
int main()
{
const char str1[] = "helloapple";
const char str2[] = "helloworld";
printf("%d\n", myStrcmp(str1, str2));
system("pause");
return 0;
}
运行结果:
注意:除了可以使用if语句进行合法性的校验,我们还可以使用assert(),括号内的逻辑如果为0,那么直接中断程序~它的头文件为#include<assert.h>
4.字符串查找子串的起始位置函数:strstr()
库函数中的声明:
思路:
这个函数相对复杂一点,定义三个指针,black指针指向dest的首元素,依次向后遍历,如果遍历到最后还没有找到,那就代表dest中没有和src匹配的子串。定义red指针,指向black,定义psrc指向src的首元素,我们在比较的时候,如果red和psrc不相等,那么black指针往后挪,我们的red还是重新指向black,psrc重新指向src;如果red和psrc相等,那么继续使用red比较是否和src中剩余字符也相等,直到src都遍历完了,那么就说明找到了,返回black所指位置即可。
代码实现:
#include<stdio.h>
#include<windows.h>
char* myStrstr(const char* dest, const char* src)
{
//if语句校验合法性
if (dest == NULL || src == NULL){
return NULL;
}
const char* black= dest;
while (*black != '\0'){
const char* red = black;
const char* psrc = src;
while (*red == *psrc && *red != '\0' && *psrc != '\0'){
red++;
psrc++;
}
if (*psrc == '\0'){
return black;
}
black++;
}
return NULL;
}
int main()
{
char dest[] = "helloworld";
printf("%s\n", myStrstr(dest, "ow"));
system("pause");
return 0;
}
运行结果:
注意校验合法性~
二、内存操作函数
1.内存拷贝函数:memcpy()
库函数中的声明:
在写内存拷贝函数的时候,我想出了一个很傻的问题,不是有字符串拷贝了吗,还要这个干嘛,然后很快意识到,字符串函拷贝只针对字符串,而内存拷贝函数它的返回值为void*,也就代表了它可以拷贝任何类型的数据!!为了能够拷贝任何类型,我们需要一个字节一个字节拷贝,char类型刚好占1个字节,所以在函数中,我们把(void *)强转为(char*)类型的,size_t num是我们要拷贝的字节数。
代码实现:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
void* myMemcpy(void* dest, const void* src,size_t num)
{
//assert校验合法性
assert(dest!= NULL&&src!=NULL);
char* pdest = (char*)dest;
const char* psrc = (char*)src;
for (size_t i = 0; i < num; i++){
*(pdest+i) = *(psrc+i);
}
return dest;
}
int main()
{
int dest1[4] = {1,0,2,4};
const int src1[4] = { 6, 6, 6, 6 };
char dest2[1024] = "hei";
const char src2[1024] = "helloworld";
for (int i = 0; i < (sizeof(dest1) / sizeof(dest1[0])); i++){
printf("%d", dest1[i]);
}
printf("\n%s\n", myMemcpy(dest2, src2, sizeof(src2)));
system("pause");
return 0;
}
运行结果:
注意校验合法性~~
2.内存拷贝函数:memmove()
库函数中的声明:
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。如果源空间和目标空间出现重叠,就得使用memmove函数处理。
如果目标内存块在源内存块中,那么就要反向拷贝(反向拷贝就是将source中的最后一个位置拷贝给destination中的最后一个位置,依次从后往前拷贝,如果不晓得为什么,可以在纸上稍微比划一下),反之呢,就正常地执行上面我们的memcpy就行啦~
代码实现:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
void* myMemcpy(void* dest, const void* src,size_t num)
{
assert(dest!= NULL&&src!=NULL);
char* pdest = (char*)dest;
const char* psrc = (char*)src;
for (size_t i = 0; i < num; i++){
*(pdest+i) = *(psrc+i);
}
return dest;
}
void* myMemmove(void* dest, const void* src, size_t num)
{
assert(dest != NULL&&src != NULL);
char* pdest = (char*)dest;
const char* psrc = (char*)src;
if (pdest>=psrc&&pdest<=psrc){
for (size_t i =num-1; i >= 0; i--){
*(pdest + i) = *(psrc + i);
}
return dest;
}
return myMemcpy(dest, src, num);
}
int main()
{
char str[] = "hello world ni hao shi jie..";
printf("%s\n", myMemmove(str+11,str+12,18));
system("pause");
return 0;
}
运行结果:
注意校验合法性~~~
bye~~~~~~