目录
一.修炼必备
二.字符串操作的常用函数
2.1 strlen()函数
2.2 strcpy()函数
2.3 strcat()函数
2.4 strcmp()函数
2.5 strstr()函数
2.6 strtok()函数
2.7 strerror()函数
三.内存操作的常用函数
3.1 memcpy()函数
3.2 memmove()函数
3.3 memcmp()函数
结语
一.修炼必备
1.入门必备:VS2019社区版,下载地址:Visual Studio 较旧的下载 - 2019、2017、2015 和以前的版本 (microsoft.com)
2.趁手武器:印象笔记/有道云笔记
3.修炼秘籍:牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网 (nowcoder.com)
4.雷劫必备:leetcode 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
注:遇到瓶颈怎么办?百度百科_全球领先的中文百科全书 (baidu.com)
二.字符串操作的常用函数
2.1 strlen()函数
1.函数作用
——求解字符串'\0'之前的字符个数
2.函数原型
size_t strlen(const char* str);
3.strlen函数的细节说明
1) strlen函数返回的是'\0'之前的字符个数,不包含'\0'
2) strlen所求的字符串必须以'\0'结束,若不以'\0'结束,不知道什么遇到'\0',即字符串大小无法判断
3) strlen函数的返回值是无符号整型【易错】
4.代码解释
代码1:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//6
printf("%d\n", sizeof(arr));//7(包含'\0')
return 0;
}
注:
1)sizeof计算的数组的大小,包含'\0'字符的;strlen函数是计算字符串长度,不包含'\0'
2)sizeof是操作符,strlen是函数
代码2:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abcdefg\0ghij";
printf("%d\n", strlen(arr));//7
return 0;
}
注:strlen计算的是字符串中最先遇到'\0'之前字符的字符个数
代码3:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdefg";
if (strlen(arr1) - strlen(arr2) > 0)//6 - 7
{
printf("strlen(arr1) > strlen(arr2)\n");
//输出strlen(arr1) > strlen(arr2)
}
else
{
printf("strlen(arr1) < strlen(arr2)\n");
}
return 0;
}
注:strlen函数返回的值是无符号整型的,无符号整型之间相减的结果若是小于0的,这个小于0的数也会被转成无符号数,即大于0的数
5.模拟实现strlen函数
1)法一:计数器
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
assert(str);//防止str是空指针
int count = 0;//计数器
while (*str++ != '\0')
count++;
return count;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
2)法二:指针 - 指针
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
char* start = str;
assert(str);//防止str是空指针
while (*str != '\0')
str++;
//指针-指针
return str - start;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
注:指针 - 指针在指向同一块内存空间的情况下,相减得到的该空间的元素之差
3)法三:递归
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
assert(str);
if (*str == '\0')
return 0;
//长度+1且指向下一个字符的地址
return 1 + my_strlen(str + 1);
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
2.2 strcpy()函数
1.函数作用
—— 字符串拷贝,把一个字符串拷贝给另外一个字符串
2.函数原型
char* strcpy(char* dest, const char* src);
3.strcpy函数的细节说明
1)源字符串必须以'\0'结束
2)strcpy函数在进行拷贝的时候,会把源字符串的'\0'拷贝到目标空间中
3)目标空间需要足够大,能放下整个源字符串的内容
4)目标空间必须可修改
4.代码解释
1)代码1:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "abcdef";
char arr2[5] = { 'a','b','c','d','f' };
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
注:以上代码会崩溃,源字符串必须以'\0'结束,但是在arr2字符串,并没有以'\0'结束
代码2:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = { 0 };
char arr2[5] = "abcd";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
调试查看:
代码3:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[5] = { 0 };
char arr2[] = "abcdefg";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
注:以上代码崩溃,因为目标空间的大小没有源字符串空间的大小大;
在使用strcpy函数的时候需要保证:目标空间 > 源字符串空间
运行结果如图:
代码4:
#include <stdio.h>
#include <string.h>
int main()
{
const char arr1[] = "abcdefh";
char arr2[] = "abcdef";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
注:以上代码能通过,但是不建议这样做,我们使用const修饰arr1后,这个arr1中的值不能被修改,但是strcpy确强制性的把他赋值进去了,这样不可取
5.模拟实现strcpy函数
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);//防止空指针
char* start = dest;
//循环遍历进行赋值
while (*dest++ = *src++);
return start;
}
int main()
{
char arr1[10] = { 0 };
char arr2[] = "abcdefg";
char* ret = my_strcpy(arr1, arr2);
printf("%s\n", ret);
return 0;
}
6.strncpy函数
1)函数作用
——拷贝源字符串的num个字符到目标空间中去
2)函数原型
char* strncpy ( char* dest, const char* src, size_t num);
3)注:若是拷贝的源字符串的长度小于num,则拷贝完源字符串后补0,直到num个
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = { 0 };
char arr2[5] = "abcd";
strncpy(arr1, arr2, 8);
printf("%s\n", arr1);
return 0;
}
调试后的结果:
2.3 strcat()函数
1.函数作用
——字符串连接函数,把源字符串连接到目标字符串的后面
2.函数原型
char* strcat(char* dest, const char* src);
3.strcat函数的细节说明
1)源字符串必须以'\0'结束
2)目标空间必须足够大,能够容纳下源字符串的内容
3)目标空间必须可修改
4.代码解释
1)代码1:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[6] = { 'a','b','c','d','e','f' };
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
注:以上代码会崩溃,因为源字符串没有以'\0'结尾,我们调试看看。
调试照片:
代码2:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[6] = "abcde";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
调试照片如下:
代码3:
#include <stdio.h>
#include <string.h>
int main()
{
const char arr1[20] = { 0 };
char arr2[6] = "abcde";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
以上代码会如愿的得到结果,但是我们使用的目标空间应该可以修改,但是使用const后导致目标空间不可修改,这样不可取
5.模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);//判断空指针
char* start = dest;
//让dest先到尾部
while (*dest != '\0')
dest++;
//在dest的后面连接src
while (*dest++ = *src++);
return start;
}
int main()
{
char arr1[10] = "abc";
char arr2[5] = "efgh";
char* ret = my_strcat(arr1, arr2);
printf("%s\n", ret);
return 0;
}
6.strncat函数
1)函数作用
——连接num个源字符串的字符到目标空间中
2)函数原型
char * strncat ( char * destination, const char * source, size_t num );
3)细节说明
1> 添加num个源字符串的字符到目标空间的时候,添加完会在后面添加'\0'
2> 若是num的长度大于源字符串的长度,那么不足的地方补'\0'
4)代码解释
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[15] = "abcde";
char arr2[5] = "oxyz";
strncat(arr1, arr2, 6);
printf("%s\n", arr1);
return 0;
}
2.4 strcmp()函数
1.函数作用
—— 字符串比较函数,两个字符串相等的话返回0
2.函数原型
int strcmp(const char* str1, const char* str2);
3.strcmp函数的细节说明
1)strcmp函数的返回值
a. < 0:说明字符串1小于字符串2
b. > 0:说明字符串1大于字符串2
c. = 0:说明字符串1等于字符串2
2)strcmp函数的比较规则:每个字符都相等则两个字符串就相等【达到'\0'结束】,一旦有一个字符不相等,就返回
4.代码解释
代码1:
#include <stdio.h>
int main()
{
char* p = "abcdef";
if ("abcdef" == (*p))
{
printf("true\n");
}
else
{
printf("false\n");//false
}
return 0;
}
注:== 比较的是值是否相等,若是比较地址的话,判断两个地址的首地址是否相等
代码2:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "acdefg";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);//-1
return 0;
}
注:在VS中,字符串进行比较,一旦比较出了结果:
1)字符串1 > 字符串2,VS会返回一个1;
2)字符串1 < 字符2,VS会返回一个-1;
3)字符串1 = 字符串2,VS会返回一个0【Linux的gbd环境下返回的是两者的字符差】
5.模拟实现strcmp函数
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1)
{
//判断是否相等
if (*str1 == *str2)
{
str1++;
str2++;
}
else
{
//不相等就跳出循环
break;
}
}
return *str1 - *str2;//返回值
}
int main()
{
char arr1[] = "abc";
char arr2[] = "ab";
int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
6.strncmp函数
1)函数作用
——比较前num个字符,判断是否相等
2)函数原型
int strncmp ( const char * str1, const char * str2, size_t num );
3)该函数和strcmp函数的作用一样,除了strncmp比较的是num个字节的字符
2.5 strstr()函数
1.函数作用
——在字符串1中找字符串2是否存在
2.函数原型
char* strstr(const char* str1, const char* str2);
3.strstr函数的细节说明
1)strstr在查找字符串的时,若找到了,返回的是找到的起始地址,一直到字符串结束
2)若是没有找到,则返回一个空指针NULL
4.代码解释
代码1:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdeeeefghijk";
char arr2[] = "efg";
char* ret = strstr(arr1, arr2);
printf("%s\n", ret);
return 0;
}
调试图片如下:
代码2:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdeeehijk";
char arr2[] = "efg";
char* ret = strstr(arr1, arr2);
printf("%s\n", ret);
return 0;
}
调试图片如下:
5.模拟实现strstr函数
#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
char* s1 = NULL;
char* s2 = NULL;
char* ret = (char*)str1;//强制类型转化防止const的警告
while (*ret)
{
s1 = (char*)ret;//到下一个字符的地址
s2 = (char*)str2;//回溯
//判断是否相等
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
//s2到了末尾
if (*s2 == '\0')
return s1;
ret++;
}
return NULL;
}
int main()
{
char arr1[] = "oppqqqrst";
char arr2[] = "ppq";
char* ret = my_strstr(arr1, arr2);
printf("%s\n", ret);
return 0;
}
2.6 strtok()函数
1.函数作用
—— 分隔字符串,使用标记分隔字符串
2.函数原型
char* strtok(char* str, const char* sep);
3.strtok函数的细节说明
1)字符串sep作为分隔字符串的分隔符号【注:sep是一个不可变的字符串】
2)strtok函数是有记忆的,会记住分隔后的地址
3)函数解释:strtok函数的第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记;strtok函数的第二个参数指定一个字符串,该字符串由用于分隔标记的字符组成,这些字符可以是任意数量,但是它们必须是单个字符。strtok函数将从str中查找这些分隔符,并将它们用 \0 结尾,返回一个指向标记的指针。strtok函数在每次调用时都会改变被操作的字符串,因此在使用strtok函数切分字符串时,一般都是使用临时拷贝的内容,这样可以避免改变原字符串中的内容。strtok函数还有一个可选参数,该参数可以用于指定strtok函数的行为,其中有两种可能的值:STRTOK_RETURN_DELIMS 和 STRTOK_SKIP_EMPTY,如果指定了 STRTOK_RETURN_DELIMS,则strtok函数返回的指针将指向分隔符;如果指定了 STRTOK_SKIP_EMPTY,则strtok函数将跳过空格,返回指向下一个有效标记的指针。总之,strtok函数是一个用于将字符串分隔成标记的函数,它可以指定分隔符,并可以指定strtok函数的行为,从而达到分割字符串的目的。
4.代码解释
代码1:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "972606225@qq.com";
char* sep = "@.";//分隔符号
char* ret = strtok(arr, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
return 0;
}
运行结果如图:
思考以下代码会输出什么?
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "972,606,225+@qq.com";
char* sep = ",+";//分隔符号
char* ret = strtok(arr, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
return 0;
}
代码2:循环使用strtok函数
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "972606225@qq.com";
char* sep = "@.";
char* ret = NULL;
for (ret = strtok(arr, sep); ret != NULL; ret = strtok(NULL, sep))
{
printf("%s\n", ret);
}
return 0;
}
2.7 strerror()函数
1.函数作用
—— 返回错误码所对应的错误的信息
2.函数原型
char* strerror(int errnum);
3.strerror函数细节说明
1)strerror函数接受一个errno值作为参数,并返回一个指向错误消息字符串的指针。这个字符串可以用于在程序中显示错误消息,
2)strerror函数会查找errno值,并返回一个指向错误消息字符串的指针,这个字符串可以用来描述错误。
4.代码解释
代码1:
#include <stdio.h>
#include <string.h>
int main()
{
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
printf("%s\n", strerror(4));
printf("%s\n", strerror(5));
return 0;
}
所对应的错误码信息如下:
代码2:在程序中的正确使用
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
FILE* pf = fopen("abc.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
}
//释放空间
free(pf);
pf = NULL;
return 0;
}
运行结果如下:
三.内存操作的常用函数
3.1 memcpy()函数
1.函数作用
——从源地址拷贝num个字节的数据到目标地址空间中
2.函数原型
void* memcpy(void* dest, const void* source, size_t num);
3.memcpy函数的细节说明
1)memcpy函数从src的位置开始向后复制num个字节的数据到dest的内存位置
2)这个函数不能和strcpy函数混淆,这个函数遇到'\0'不能停止
3)如果src和dest有任何的重叠,复制的结果都是未定义的
4.代码解释
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10] = { 0 };
int arr2[5] = { 1,2,3,4,5 };
//从arr2复制16个字节的数据到arr1中
memcpy(arr1, arr2, 16);
return 0;
}
调试代码如图:
5.模拟实现memcpy函数
#include <stdio.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* start = dest;//起始地址
//复制num个字节
while (num--)
{
*(char*)dest = *(char*)src;//赋值
dest = (char*)dest + 1;//指向下一个空间
src = (char*)src + 1;
}
return start;
}
int main()
{
int arr1[10] = { 0 };
int arr2[5] = { 6,7,8,9,10 };
void* ret = my_memcpy(arr1, arr2, 16);
for (int i = 0; i < 4; i++)
printf("%d ", *((int*)ret + i));
return 0;
}
3.2 memmove()函数
1.函数作用
——函数作用和memcpy函数是一样的
2.函数原型
void* memmove(void* dest, const void* src, size_t num);
3.memmove函数的细节说明
1)函数的功能和memcpy函数的功能一致:也是内存拷贝
2)memmove函数区别于memcpy的地方:memmove函数可以处理内存重叠的空间
4.代码解释
#include <stdio.h>
#include <string.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//把arr的20个字节的空间拷贝到arr+2的空间上
memmove(arr + 2, arr, 20);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
运行结果如图:
5.模拟实现memmove函数
#include <stdio.h>
#include <assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
//判断大小然后考虑拷贝的方式
if (src > dest)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
void* ret = my_memmove(arr, arr + 4, 20);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
printf("%d ", *((int*)ret + i));
return 0;
}
3.3 memcmp()函数
1.函数作用
——内存比较,将内存中的数据拿出来一个一个的进行比较
2.函数原型
int memcmp(const void* ptr1, const void* ptr2, size_t num);
3.memcmp函数的细节说明
memcmp函数是比较两个内存块中num个字节的数据大小
1)若memcmp函数返回0,则说明比较的num个字节是相等的
2)若memcmp函数返回值
3)若memcmp函数返回值>0,则说明内存块1大于内存块2
4.代码解释
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 1,2,3,4,6 };
int ret = memcmp(arr1, arr2, 16);//比较16个字节的数据
printf("%d\n", ret);//0
return 0;
}
5.模拟实现memcmp函数文章来源:https://www.toymoban.com/news/detail-401079.html
#include <stdio.h>
#include <assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
assert(ptr1 && ptr2);
while (num)
{
//不相等则跳出
if ((*(char*)ptr1) != (*(char*)ptr2))
break;
ptr1 = (char*)ptr1 + 1;
ptr2 = (char*)ptr2 + 1;
num--;
}
//判断是不是循环到了最后一个
if (num == 0)
{
return 0;
}
//不是最后一个
return *(char*) ptr1 - *(char*)ptr2;
}
int main()
{
int arr1[5] = { 1,2,3,4,6 };
int arr2[5] = { 1,2,3,4,5 };
int ret = my_memcmp(arr1, arr2, 20);
printf("%d\n", ret);
return 0;
}
结语
少年,修行不易;未来就在前方,要相信自己能达到你所期望的高度。少年,加油!!!文章来源地址https://www.toymoban.com/news/detail-401079.html
到了这里,关于金丹三层 —— 内存函数和字符串操作函数详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!