目录
本文和大家分享一些C语言中常用的字符串和内存处理函数的使用,以及如何去模拟实现
🎈字符串函数
使用字符串函数需要引用头文件 #include<string.h>
strlen
size_t strlen(const char* str); 求字符串长度
· 字符串以'\0'作为结束标志,strlen返回的是'\0'前面的字符个数(不包括'\0')
· 返回值是无符号整数
使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "hello world";
int ret = strlen(arr); //传入首元素地址
printf("%d\n", ret); //打印11
return 0;
}
模拟实现:
#include<stdio.h>
unsigned_int my_strlen(char* str)
{
int count = 0;
while (*str++ != '\0')
{
count++;
}
return count;
}
int main()
{
char arr[] = "hello world";
int ret = my_strlen(arr); //传入首元素地址
printf("%d\n", ret); //打印11
return 0;
}
strcpy
char* strcpy(char* destination, const char* source); 字符串拷贝函数
· 源字符串必须以'\0'结尾,会将'\0'拷贝到目标空间里
· 目标空间必须足够大
· 目标空间必须可变
使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[10] = "xxxxxxxxxx";
char arr2[] = "wwx";
char* ret = strcpy(arr1, arr2);
//返回目标空间的首元素地址
printf("%s", ret);
return 0;
}
模拟实现:
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++)
{//dest为'\0'时,退出循环
;
}
return ret;//返回目标空间的起始地址
}
int main()
{
char arr1[10] = "xxxxxxxxxx";
char arr2[] = "wwx";
printf("%s", my_strcpy(arr1, arr2));
return 0;
}
strncpy
char* strcpy(char* destination, const char* source, unsigned int count);
与strcpy用法相同,是可以控制长度的字符串拷贝函数
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "To be or not to be";
char str2[40];
char str3[40];
strncpy(str2, str1, sizeof(str2));
strncpy(str3, str2, 5);
str3[5] = '\0'; //复制了前五个后添加终止符号
puts(str1);//To be or not to be
puts(str2);//To be or not to be
puts(str3);//To be
return 0;
}
strcat
char *strcat( char *Destination, const char *Source ); 字符串追加函数
使用:
#include<stdio.h>
#include<string.h>
int main()
{
char a[10] = "ABCDE";//要注意开辟足够的空间
strcat(a, "FGH"); //从最后一个地址开始,源字符串必须要有\0
printf("%s", a); //输出ABCDEFGH 最好不要自己追加自己
return 0;
}
模拟实现:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* source)
{
assert(dest && source);
char* ret = dest;//储存目标空间的起始地址
while (*dest != '\0')
{//使目标指针指向\0
dest++;
}
while (*dest++ = *source++)
{//从\0开始追加,循环跳出说明源字符串'\0'追加完成
;
}
return ret;//返回目标空间的起始地址
}
int main()
{
char arr1[20] = "hello ";
char arr2[6] = "world";
char* ret = my_strcat(arr1, arr2);
printf("%s", ret);
return 0;
}
strncat
char *strncat( char *Dest, const char *Source, size_t count ); 可控长度的追加函数
#include<stdio.h>
#include<string.h>
int main()
{
char a[10] = "ABCDE";//要注意开辟足够的空间
strncat(a, "FGHJKL", 3); //追加三个字符
printf("%s", a); //输出ABCDEFGH
return 0;
}
strcmp
int strcmp( const char *str1, const char *str2 ); 字符串比较函数
· 比较的是相对应字符的ASCII码值
· str1大于str2,返回大于0的值,反之返回小于0的值,相等返回0
使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcf";
char arr2[] = "abcde";
int ret = strcmp(arr1, arr2);
if (ret == 0)
{
printf("arr1==arr2");
}
else if (ret > 0)
{//输出
printf("arr1 > arr2");
}
else
{
printf("arr1 < arr2");
}
return 0;
}
模拟实现:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 != '\0')
{//遍历其中一个字符串
int ret = *str1 - *str2;
//对应的每一个字符相减
if (ret != 0)
{//不为零时直接返回
return ret;
}
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char arr1[] = "abcf";
char arr2[] = "abcde";
int ret = my_strcmp(arr1, arr2);
if (ret == 0)
{
printf("arr1==arr2");
}
else if (ret > 0)
{
printf("arr1 > arr2");
}
else
{
printf("arr1 < arr2");
}
return 0;
}
strncmp
int strncmp( const char *str1, const char *str2, size_t count ); 可控长度的比较
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcf";
char arr2[] = "abcde";
int ret = strncmp(arr1, arr2, 2);
//比较前两个字符
if (ret == 0)
{
printf("arr1==arr2");
}
else if (ret > 0)
{
printf("arr1 > arr2");
}
else
{
printf("arr1 < arr2");
}
return 0;
}
strstr
char *strstr( const char *str, const char *strson ); 在str中寻找子字符串
使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "acdbcdefgh";
char arr2[] = "defgh";
char* ret = strstr(arr1, arr2);
//在arr1中是否能找到arr2
if (ret == NULL)
{//找不到返回NULL
printf("找不到!\n");
}
else
{//找到则返回母串与子串对应的首字符地址
printf("找到了!%s\n", ret);
}
return 0;
}
模拟实现:
#include<stdio.h>
char* my_strstr(const char* str1, const char* str2)
{//模拟实现
const char* s1 = NULL;
const char* s2 = NULL;
const char* cp = str1;
if (*str2 == '\0')
{//str2为空时
return str1;
}
while (cp)
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{//同为\0时,不加以上条件,可能导致越界访问
s1++;
s2++;
}
if (*s2 == '\0')
{//说明\0之前的字符相同
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "acdbcdefgh";
char arr2[] = "defgh";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{//找不到返回NULL
printf("找不到!\n");
}
else
{//找到则返回母串与子串对应的首字符地址
printf("找到了!%s\n", ret);
}
return 0;
}
strtok
char *strtok( char *str, const char *strDelimit ); 字符串切割函数
· 将str以 strDelimit中的分隔符切割开来
使用:
#include<stdio.h>
int main()
{
char arr1[] = "18870251842@163.com";
char p[] = "@.";
//将字符串内得到分隔符放在p内
char arr2[30] = { 0 };
strcpy(arr2, arr1);
//一般会拷贝一个字符串用来切割
char* ret = NULL;
for (ret = strtok(arr2, p); ret != NULL; ret = strtok(NULL, p))
{//使用循环,减少代码冗余
printf("%s\n", ret);
}
//ret = strtok(arr2, p); //18870251842
//会找到第一个分隔符,将其替换为\0,记录位置,返回首字符地址
//ret = strtok(NULL, p); //163
//找到下一个分隔符,将其替换,并记录位置,返回记录位置的下一个位置地址,
//ret = strtok(NULL, p); //com
//同样,遇到\0函数结束,不可以使用\0作为分割字符,返回记录位置的下一个位置地址
return 0;
}
strerror
char *strerror( int errno); 翻译错误信息
使用:
//库函数使用错误时,都会设置错误码
//只要调用库函数发生错误,就会将错误码放到 全局变量 errno 中
#include<stdio.h>
#include<errno.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{//文件打开失败,设置错误码
printf("%s", strerror(errno)); //打印翻译的错误信息
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
部分错误信息表
perror
void perror( const char *string ); 翻译并打印错误信息
字符分类函数
引用头文件 #include<ctype.h>
char a = '1';
int ret = islower(a);
printf("%d\n", ret); //0
字符转换函数
tolower
int tolower( int c ); 转化为小写字符
toupper
int toupper( int c ); 转化为大写字符
char arr[20] = { 0 };
scanf("%s", arr);
int i = 0;
while (arr[i] != '\0')
{
if (isupper(arr[i]) == 1)
{//是大写就转换为小写字符
arr[i] = tolower(arr[i]);
}
printf("%c ", arr[i]);
i++;
}
🎈内存操作函数
需要引用头文件 #include<string.h>
memcpy
void *memcpy( void *dest, const void *src, size_t count ); 内存拷贝函数
· 用来进行不重叠内存的拷贝
使用:
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 40);
//传入目标地址和源地址,拷贝的单位是字节
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
内存重叠时不要使用memcpy函数
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]); //1 2 1 2 1 2 1 8 9 10
//不能保证所有的编译器都可以
}
return 0;
}
模拟实现:
#include<stdio.h>
#include<string.h>
void* my_memcpy(void* dest, const void* sou, int num)
{
void* ret = (char*)dest;
while (num--)
{
*((char*)dest)++ = *((char*)src)++;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 40);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
memmove
void *memmove( void *dest, const void *src, size_t count ); 内存拷贝函数
· 功能与memcpy一样
· 可以处理内存重叠的情况
使用:
#include<stdio.h>
$include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]); // 1 2 1 2 3 4 5 8 9 10
}
return 0;
}
模拟实现:
#include<stdio.h>
void* my_memmove(void* dest, const void* sou, size_t num)
{
void* ret = (char*)dest;
if (dest < sou)
{
while (num--)
{
*((char*)dest)++ = *((char*)src)++;
}
return ret;
}
else
{
while (num--)
{//开始进入循环为20 再-- 进入循环最小值为1,再--
*((char*)dest + num) = *((char*)sou + num);
//使用时num最小为0,最大为19
}
return ret;
}
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1, arr1 + 2, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]); // 1 2 1 2 3 4 5 8 9 10
}
return 0;
}
memcmp
int memcmp( const void *buf1, const void *buf2, size_t count ); 内存比较函数
使用:
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6 };
int arr2[] = { 1,2,3,260,5 };
int ret = memcmp(arr1, arr2, 14); //比较的单位是字节
printf("%d\n", ret); //arr1>arr2,返回1,反之返回-1,相等返回0
return 0;
}
模拟实现:
#include<stdio.h>
int my_memcmp(const void* p1, const void* p2, unsigned int num)
{
while (num--)
{
int ret = *((char*)p1)++ - *((char*)p2)++;
if (ret != 0)
{
return ret;
}
}
return 0;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6 };
int arr2[] = { 1,2,3,260,5 };
int ret = my_memcmp(arr1, arr2, 20);
printf("%d\n", ret);
return 0;
}
memset
void *memset( void *dest, int c, size_t count ); 内存设置函数
· 将从目标地址开始的count个字节设置为c
使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "XXXXXXXXXXXXXXX";
char* ret = memset(arr, 'a', 5);
printf("%s\n", ret);
return 0;
}
模拟实现:
#include<stdio.h>
void* my_memset(void* dest, int c, unsigned int num)
{
void* ret = dest;
while (num--)
{
*((char*)dest)++ = c;
}
return ret;
}
int main()
{
char arr[] = "XXXXXXXXXXXXXXX";
char* ret = my_memset(arr, 'a', 5);
printf("%s\n", ret);
return 0;
}
这里介绍一些常用的函数,如果想要深入了解可以在C/CPP官方网站查看,感谢支持❤️❤️❤️