目录
前言
🌏一、字符串函数
🍯1.strlen
//1.strlen模拟实现
int my_strlen(char* p)
{
assert(p);
int count = 0;
while (*p)
{
count++;
p++;
}
return count;
}
int main()
{
char arr[] = { "abcdef" };
int sz = my_strlen(arr);
printf("sz=%d\n", sz);
return 0;
}
🍯2.strcpy
🍤该函数用于拷贝字符串,将arr2里的内容拷贝到arr1里
//2.strcpy模拟实现,拷贝
char* my_strcpy(char* a2, const char* a1)
{
char* dest = a2;
assert(a1 && a2);
do
{
*a2++ = *a1;
} while (*a1++);
return dest;
}
int main()
{
char arr1[] = { "abcdef" };
char arr2[15]="xxxxxxxxx";
my_strcpy(arr2, arr1);
puts(arr2);
return 0;
}
🍤源字符串必须以‘\0'结束
🍤会将源字符串中的'\0'拷贝到目标空间。
🍤目标空间必须足够大,以确保能存放源字符串。🍤目标空间必须可修改
🍯3.strcat
🍤strcat函数用于追加字符串,简单来说就是把两个字符串接在一起
🍤源字符串必须以'\0'结束。
🍤目标空间必须有足够的大,能容纳下源字符串的内容。目标空间必须可修改。
🍤注意,使用strcat函数的时候不能自己追加自己,程序会死循环
//3,strcat函数
char* my_strcat(char* dest, const char* sour)
{
assert(dest && sour);
char* ptr = dest;
while (*dest)
{
dest++;
}
do
{
*dest++ = *sour;
} while (*sour++);
return ptr;
}
int main()
{
char arr1[10] = "hello";
char arr2[] = "bit";
my_strcat(arr1, arr2);
puts(arr1);
return 0;
}
🍯4.strcmp
🍤该函数在比较字符串的时候,实际上是一个字符一个字符地比较的
🍤第一个字符串大于第二个字符串,则返回大于0的数字
🍤第一个字符串等于第二个字符串,则返回0
🍤第一个字符串小于第二个字符串,则返回小于0的数字
//4.strcmp函数
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while(*str1 == *str2)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char arr1[] = { "abcdef" };
char arr2[] = { "abcd" };
printf("%d\n",my_strcmp(arr2, arr1));
return 0;
}
🍯5.strncpy/strncat/strncmp
🍤和之前的函数不一样,这些函数最后还有一个一个字符数量的问题
🍯6.strstr
🍤在字符串s1里面查找是否有字符串s2
🍤如果有,返回字符串s2在字符串s1里的起始地址
🍤如果没有,返回NULL
//5.strstr 判断str1里面有没有str2
//如果有,返回str1里str2的起始地址
//如果str1不包含str2,返回null
char* my_strstr(const char* str1, const char* str2)
{
const char* s1 = str1;
const char* s2 = str2;
const char* cur = str1;
assert(str1 && str2);
if (*str2 == '\0')
{
return (char*)str1;
}
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return (char*)cur;
cur++;
}
return NULL;
}
int main()
{
char arr1[15] = { "helloworld" };
char arr2[] = { "owo" };
char* p=strstr(arr1, arr2);
if (p == NULL)
{
printf("找不到\n");
}
else
{
printf("%s\n", p);
}
return 0;
}
🍯7.strtok
🍤该函数用于查找一个字符串中的分隔符
char * strtok ( char * str, const char * sep );
🍤sep参数是个字符串,定义了用作分隔符的字符集合
🍤第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
🍤strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针🍤strtok函数会改变被操作的字符串(把分隔符改为0),所以在使用strtok函数切分的字符串一般都是临时拷贝的内容,并且可修改
🍤strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
🍤strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
🍤如果字符串中不存在更多的标记,则返回NULL指针
🍤我们可以往strtok函数里传入buf,也可以直接传入NULL,因为传入NULL的时候该函数会在上一次操作的字符串里继续查找分隔符
int main()
{
const char* p = "@.";
char arr[] = "zpengwei@yeah.net";
char buf[50] = { 0 };//"zpengwei@yeah.net"
strcpy(buf, arr);
char* str = NULL;
for (str = strtok(buf, p); str != NULL; str=strtok(NULL, p))
{
printf("%s\n", str);
}
return 0;
}
🍤 for循环的第一个表达式只会执行一次,让str=strtok第一次查找的返回值
🍤如果该返回值为空(没找到更多的分隔符),停止循环
🍤如果该返回值不为空,就让str=strtok(NULL,p),继续查找并打印下一部分
🍯8.strerror
char * strerror ( int errnum );
🍤errno是C语言提供的一个全局变量,可以直接使用,放在errno.h文件中
🍤当库函数使用发生错误时,会把errno这个全局的错误变量设置为本次执行库函数产生的错误码
🍤这时候可以用strerror函数将errno错误码翻译成错误信息
#include <errno.h>//需要调用errno.h头文件printf("%s\n", strerror(errno));
🌏二、内存函数
🍯1.memcpy
🍤这个函数的作用也是拷贝内容,和strcpy不同,memcpy可以拷贝任意类型
🍤函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置该🍤函数在遇到‘\0’的时候并不会停下来
🍤如果source和destination有任何的重叠,复制的结果都是未定义的
void * memcpy ( void * destination, const void * source, size_t num );
🍤要注意的是我们不能直接对void*指针进行++,而要将其强制类型转换成char*指针后+1
1.memcpy模拟实现void* my_memcpy(void* dest, const void* sour, int num)
{
assert(dest && sour);
void* ptr = dest;
while (num--)
{
*(char*)dest = *(char*)sour;
dest = (char*)dest + 1;
sour = (char*)sour + 1;
}
return ptr;
}
int main()
{
int arr1[10] = { 1,2,4,5,9,7,8 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 5 * sizeof(int));
for (int i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
🍯2.memmove
🍤这个函数和memcpy的功能基本一致,只有一点不同
🍤memmove在考贝的时候,源地址和目的地可以重叠
void * memmove ( void * destination, const void * source, size_t num );
🍤如果我们的目的地在源地址的后面,就应该从后向前拷贝,避免数据被改写
🍤如果我们的目的地在源地址的前面,就应该从前向后拷贝
🍤这里的前/后都是指有重叠的情况,如果没有重叠,从前往后/从后往前都不影响
void* my_memmove(void* dest, const void* sour, int num)
{
assert(dest && sour);
void* ptr = dest;
if (dest < sour)
{
while (num--)
{
*(char*)dest = *(char*)sour;
dest = (char*)dest + 1;
sour = (char*)sour + 1;
}
}
else
{
while (num--)
{
*((char*)dest+num) = *((char*)sour+num);
}
}
return ptr;
}
int main()
{
int arr1[10] = { 1,2,4,5,9,7,8,3,0,6};
//1 2 4 1 2 4 5 9 0 6
my_memmove(&arr1[3], arr1, 5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
🍯3.memcmp
🍤以字节为单位进行比较
int memcmp ( const void * ptr1,
const void * ptr2,
size_t num );
int my_memcmp(const void* ptr1, const void* ptr2, int num)
{
assert(ptr1 && ptr2);
while (num--)
{
if (*(char*)ptr1 == *(char*)ptr2)
{
ptr1 = (char*)ptr1 + 1;
ptr2 = (char*)ptr2 + 1;
}
else
{
return *(char*)ptr1 - *(char*)ptr2;
}
}
return 0;
}
int main()
{
int arr1[5] = { 1,3,5,6,8 };
int arr2[5] = { 2,4,7,9,0 };
int arr3[5] = { 1,3,4,7,9 };
int ret1 = my_memcmp(arr1, arr3, 9);
int ret2 = memcmp(arr1, arr3, 9);
printf("my_memcmp:%d\n", ret1);
printf("memcmp:%d\n", ret2);
return 0;
}
🍯4.memset
🍤这个函数的作用是把内存中
ptr
所在位置的num个字节的内容改为value
void * memset ( void * ptr, int value, size_t num );
🌏总结
🍤孰能生巧,就当作面试题去对待