C语言常见字符函数,字符串函数,内存函数的用法及模拟
前言
本篇介绍了C语言的一些常见字符函数,字符串函数,内存函数的用法及模拟,掌握这些函数的用法可以帮助你更方便的解决一些字符(串)问题和内存问题(不多),而对这些函数的模拟用法可以让你对指针的理解更加深刻,并提升对C语言的理解!
字符函数
1.字符分类函数
想必大家在初学C语言时肯定刷了很多关于字符的题吧,大家在完成这些题的时候是不是使用ASCLL值呢?那样其实显得过于复杂了,我们其实可以一些函数去达到你想要的效果,接下来我来向你们介绍一下哦!
如果函数的参数符合以下条件就返回真
1.1 iscntrl
任何控制字符
1.2 isdigit
十进制数字‘0’ ~‘9’字符
1.3 islower
小写字母a~z
1.4 isupper
大写字母A~Z
1.5 isalpha
字母a ~ z,字母A ~ Z;
1.6 isalnum
字母或者数字
2.字符转换函数
2.1 tolower(int c)
大写字母转小写字母
2.2 toupper(int c)
小写字母转大写
字符串函数
3.strlen的使用和模拟实现
3.1strlen的使用
- 字符串以‘\0’作为结束标志,strlen函数返回的是在字符串中‘\0"前面出现的字符个数(不含‘\0’)
- 参数指向的字符串必须要以‘\0’结束
- 注意函数的返回值为size_t,是无符号的
- 头文件<string.h>
大家尤为注意的是加了黄色的部分
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcde";
char arr2[] = "sdgj";
if (strlen(arr2) - strlen(arr1) < 0)
{
printf("arr2小\n");
}
else
{
printf("arr1小\n");
}
return 0;
}

大家是不是觉得很意外,明明arr1中的字符个数多,怎么是arr1小呢?
上文说了,size_t是无符号整型,size_t与size_t的计算结果也是无符号整型,是大于等于0的,故出现这个结果。
那么,我们该如何计算两者大小呢?
if(strlen(arr1)>strlen(arr2))
{
printf("arr1大\n");
}
直接比较strlen不就行了🌹
3.2strlen的模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t my_strlen(char* arr)
{
assert(arr);//确保不为空集
size_t r = 0;
while (*arr)
{
arr++;
r++;
}
return r;
}
int main()
{
char arr1[] = "abcde";
char arr2[] = "sdgj";
if (my_strlen(arr2) < my_strlen(arr1))
{
printf("arr2有%zu个字符\n", my_strlen(arr2));
printf("arr2小\n");
}
else
{
printf("arr1小\n");
}
return 0;
}

想必大家应该很容易理解,这里不过多解释了。
4.strcpy的用法和模拟实现
4.1strcpy的使用
char*strcpy(char*destination,const char*source);
destination是目标空间,source是源字符串(这里只说一遍哈,后面的也是这个)
作用:将sourse里的值拷贝到destination中,并返回destination的初始地址
- 源字符串必须以‘\0’结束
- 会将源字符串的‘\0’拷贝到目标空间
- 目标空间必须足够大,以确保能存放源字符串
- 目标空间必须可修改
- 头文件<string.h>
#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
char arr1[10] = { 0 };
char arr2[] = "sdgj";
strcpy(arr1, arr2);
char* p = strcpy(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", p);
return 0;
}

4.2strcpy的模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcpy(char* att, const char* arr)
{
assert(att && arr);
char* ret = att;
while (*ret++ = *arr++)
{
;
}
return att;
}
int main()
{
char arr[] = "abcdef";
char att[20] = "xxxxxxxxxxxxxxxxxxxx";
my_strcpy(att, arr);
char* a = my_strcpy(att, arr);
printf("%s\n", att);
printf("%s\n", a);
return 0;
}
5.strcat的使用和模拟实现
char*strcat(char*destination,const char*source);
5.1strcat的使用
功能:字符串追加,把source指向的原字符串中的所有字符都追加到destination
- 源字符串必须以‘\0‘结束
- 目标字符串中也得有\0,否者不知道在哪追加
- 目标空间足够大
- 目标空间必可修改
- 末尾追加
#include<stdio.h>
#include<string.h>
int main()
{
char str1[20] = "abcdsf";
char str2[] = "his dog";
char* p = strcat(str1, str2);
printf("%s\n", p);
printf("%s\n", str1);
return 0;
}

5.2strcat的模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
void my_strcat(char* arr, char* att)
{
assert(arr && att);
while (*arr)
{
*arr++;
}
while (*att)
{
*arr++ = *att++;
}
*arr = *att;
}
int main()
{
char arr[20] = "abcdef";
char att[7] = "abcdeh";
my_strcat(arr, att);
printf("%s\n", arr);
return 0;
}
结果:
6.strcmp的使用和模拟实现
6.1strcmp的使用
int strcmp(char*destination,const char*source);
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
- 比较的是两个字符串上对应字符的ASCLL码值的大小,从左向右
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "asdf";
char str2[] = "asdh";
printf("%d", strcmp(str1, str2));
return 0;
}

6.2strcmp的模拟实现
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* att, const char* arr)
{
assert(att && arr);
while (*att == *arr)
{
if (*att == '\0')
return 0;
*att++;
*arr++;
}
return *att - *arr;
}
int main()
{
char arr[7] = "abcdef";
char att[7] = "abcdeh";
if (my_strcmp(att, arr) == 0)
{
printf("两者相同\n");
}
else if (my_strcmp(att, arr) > 0)
{
printf("前者大\n");
}
else
{
printf("后者大\n");
}
return 0;
}
想必大家都了解了strcpy,strcat,strcmp的用法了,接下来,给大家介绍一下这几个函数的进阶版(笔者自称)!
7.strncpy,strncat,strncmp
给大家分别写下这些库函数如何表示
char *strncpy(char *destination,const char *source,size_t num);
char *strncat(char *destination,const char *source,size_t num);
int strncpy(char *destination,const char *source,size_t num);
对于以上函数,无非增加了size_t类型的num,代表将要复制,追加,比较大小的比特个数(1字节8比特)。
和上方函数是一个用法,但是还是有些微小差别
7.1strncpy
- 如果源字符串的长度小于num,则拷贝完字符串之后,在目标的后面追加0直至num个
- 如果大于num,则不保证末尾有\0,需手动添加
7.2strncat
- 源字符串中不一定要\0了,因为函数会自动补\0(不管是否已有0)
7.2strncmp
这里强调一下,strncmp与strcmp均不忽略大小写
8.strstr的使用和模拟实现
char*strstr(const char* str1,const char*str2)
8.1strstr的使用
功能:在一个字符串中找另一个字符串第一次出现的位置
- 函数返回str2在字符串str1中第一次出现的位置,无则返回NULL
- 字符串的比较匹配不包含\0,以\0作为结束标志
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "asdfghjkl";
char str2[] = "ghjkl";
char* p = strstr(str1, str2);
printf("%s\n", str1);
printf("%s\n", p);
return 0;
}

8.2strstr的模拟实现
#include<stdio.h>
#include<string.h>
char* my_strstr(const char* str1,const char* str2)
{
char* cp = str1;
char* s1;
char *s2;
if (!*str2)
{
return cp;
}
while (*cp)
{
char* s1 = cp;
char* s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
if (!*s2)
{
return cp;
}
}
cp++;
}
return (NULL);
}
int main()
{
char str[] = "This is a simple string";
char* pch;
pch = my_strstr(str,"simple");
strncpy(pch, "sample", 6);
printf("%s\n", str);
return 0;
}
内存函数
9.memcpy的使用和模拟实现
void * memcpy(void*destination,const void*source,size_t num);
9.1memcpy的使用
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置
- 这个函数在遇到‘\0’不会停止下来
- 如果source和destination有任何的重叠,复制的结果都是未定义的
#include<stdio.h>
#include<string.h>
int main()
{
char arr[20] = "chen zhao nan";
memcpy(arr, arr + 5, 5);
printf("%s\n", arr);
return 0;
}

9.2memcpy的模拟使用
#include<stdio.h>
#include<string.h>
#include<assert.h>
void *my_memcpy(void* arr2, const void* arr1, size_t n)
{
assert(arr1 && arr2);
void* ret = arr2;
while (n--)
{
*(char*)arr2 = *(char*)arr1;
arr2 = (char*)arr2 + 1;
arr1 = (char*)arr1 + 1;
}
return(ret);
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9 };
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
前文说了,如果source和destination有任何的重叠,复制的结果都是未定义的!那么,是否有函数可以让两者可以重叠呢?
有的有的😄
10.memmove的使用和模拟实现
void * memmove(void*destination,const void*source,size_t num);
- 与memcpy差不多,但可重叠
- 若重叠,就得用memmove
10.1memmove的使用
#include<stdio.h>
#include<string.h>
int main()
{
char arr[50] = "chen zhao nan is a handsome boy";
memmove(arr, arr + 5, 10);
printf("%s\n", arr);
return 0;
}

10.2memmove的模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dst, const void* src, size_t n)
{
void* ret = dst;//int 类型,需强制转换为char类型才能加减size_t类型
if (dst <= src || ((char*)dst >= ((char*)src + n)))
{
while (n--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst+1;
src = (char*)src + 1;
}
}
else
{
dst = (char*)dst + n-1;
src = (char*)src + n-1;
while (n--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;//可不可以dst++;
src = (char*)src - 1;
}
}
return(ret);
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
11.memset,memcmp函数的使用
11.1memset的使用
void * memset(void *ptr,int value,size_t num)
这个函数很好用哈
功能:将ptr的值以字节为单位设置成想要的内容
#include<stdio.h>
#include<string.h>
int main()
{
char arr[10] = "aaaaaaaaa";
memset(arr, 'x', 5);
printf("%s\n", arr);
return 0;
}

11.2memcmp的使用
int memcmp(const void *ptr1,const void*ptr2,size_t num);
这个函数和strncmp差不多,但这里还是说一下区别
- memcmp可比较多种类型,strncmp专与字符串
- strncmp遇\0结束,memcmp则强制比较num每个字节
字符函数,字符串函数,内存函数就介绍到这里,欢迎大家讨论😄
更多推荐



所有评论(0)