文章目录
- 一、字符串函数的介绍
-
- 前言
- 1.strlen函数的介绍及模拟实现
- (1)strlen函数的使用
- (2)strlen函数功能
- (3)strlen的模拟实现
- (4)易错点
- 2.strcpy函数的介绍及模拟实现
- (1)strcpy函数的使用
- (2)strcpy函数功能
- (3)strcpy 函数的模拟实现
- 3.strcat函数的介绍及模拟实现
- (1)strcat函数的使用
- (2)strcat函数功能及使用
- (3)strcat字符追加函数的模拟实现
- (4)字符串能否给自己追加本身?
- 4.strcmp函数的介绍及模拟实现
- (1)strcmp函数的使用
- (2)strcmp函数功能
- (3)strcmp函数的模拟实现
- 5.长度受限制的字符串函数的使用
- (1)strncpy函数的介绍
- (2)strncat函数的介绍
- (3) strncmp函数的介绍
- 6.strstr函数的介绍和模拟实现
- (1)strstr函数的使用
- (2)strstr函数的功能
- (3)strstr函数的模拟实现
- 7.strtok函数的介绍
- 8.strerror函数的介绍
- 9.字符操作函数
- (1)字符分类函数
- (2)字符转换函数
- 二、内存操作函数介绍
-
- 1.memcpy函数的介绍和模拟实现
- (1)memcpy函数的功能
- (2)memcpy函数的使用
- (3) memcpy函数的模拟实现
- (4)memcpy函数的缺点
- 2.memmove函数的介绍和模拟实现
- (1)memmove函数的功能
- (2)memmove函数的模拟实现
- 3.memcmp函数的介绍
- (1)memcmp函数的功能
- (2)memcmp函数的使用
- 4.memset函数的介绍
- (1)memset函数功能
- (2)memset函数的使用
- 未完待续!!
一、字符串函数的介绍 前言 ??C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串或者字符数组中。字符串常量适用于那些对他不做修改的字符串函数。
1.strlen函数的介绍及模拟实现
(1)strlen函数的使用
#include
#include
int main()
{
//字符串函数的实现
//字符串函数的功能
char a[6] = "abcde";
int len = strlen(a);
printf("%d\n", len);
return 0;
}
执行效果如下:
文章图片
(2)strlen函数功能 通过msdn函数功能查找得知strlen具体使用情况如下
文章图片
文章图片
??strlen的功能是获取字符串的长度,函数内部传的参数类型是 char *,返回的类型是size_t类型。返回值是字符串中字符出现的个数。
文章图片
(3)strlen的模拟实现
size_t my_strlen(const char* p)
{
int count = 0;
while (*p)
{
count++;
p++;
}
return count;
}
(4)易错点 注意:
#include
#include
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
??如果按照我们平时的理解,我们所算的strlen(str1)=6,strlen(str2)=3,strlen(str2)—strlen(str1)<0,会打印str1>str2。但是实际上打印的结果却并不是我们想的那样。
文章图片
??打印结果为str2>str1.那么我们想是strlen(str2)— strlen(str1)>0吗?并不是的,还记得我们说的strlen的返回类型是size_t 无符号数,是不存在负数的,减到小于0是会成为一个很大很大的数字,此时结果还是大于0,所以会出现上述打印的结果,这点很容易出现错误。牢记strlen的返回类型是无符号整型。
2.strcpy函数的介绍及模拟实现
(1)strcpy函数的使用
#include
#include int main()
{
char arr1[30] = "*********************";
char arr2[] = "hello world";
/*strcpy(arr1,arr2);
*/
printf("%s\n", strcpy(arr1, arr2));
return 0;
}
执行代码效果如下:
文章图片
(2)strcpy函数功能 通过msdn函数功能查找得知strlen具体使用情况如下
文章图片
文章图片
??我们得知,strcpy是字符串拷贝函数,他的功能就是拷贝字符串,函数内部的参数:第一个参数是目标字符串,第二个参数是 char* str Source (起始字符串),最后将起始字符串拷贝到目标字符串中,达到最终效果。函数返回类型是 char*。返回值是目标字符串的起始地址处。
文章图片
(3)strcpy 函数的模拟实现
#include
#include
#include char * my_strcpy(char *dest,const char *src)
{
char * p = dest;
assert(dest && src );
while (*src)
{
*dest=*src;
dest++;
src++;
}
*dest=*src;
return p;
}int main()
{
char arr1[30] = "*********************";
char arr2[] = "hello world";
/*strcpy(arr1,arr2);
*/
printf("%s\n", strcpy(arr1, arr2));
return 0;
}
??这里的模拟实现中有一点需要注意的,我们将源字符串拷贝到目标字符串后,函数要返回目标字符串的起始指针的地址处,但是dest已经++,所以在一开始我们要将dest的初始值保存起来,char *p=dest,最后返回p。
3.strcat函数的介绍及模拟实现
(1)strcat函数的使用
int main()
{
char arr1[20] = "hello ";
char arr2[20] = "world";
/*my_strcat(arr1, arr1)*/
printf("%s\n", strcat(arr1, arr2));
return 0;
}
代码实现效果:
文章图片
(2)strcat函数功能及使用 通过msdn函数功能查找得知strlen具体使用情况如下
文章图片
文章图片
??该函数的功能是追加一个字符串,函数内部的参数:第一个参数是char*str Destination(目标字符串),第二个参数是 起始字符串,将源字符串追加到目标字符串后。返回类型是char *。返回的是目标字符串的起始地址处。
文章图片
(3)strcat字符追加函数的模拟实现 ??首先我们问一个问题,如何实现字符追加,首先第一步先要找到目标字符串的’\0 ‘,然后将目标函数的’ \0 ‘改为源字符串的初始指针,再将src赋给dest直到*src=https://www.it610.com/article/’/0’,返回目标字符串的初始指针的地址处。
代码实现:
#include
#include
#include char*my_strcat(char*dest, const char*src)
{
assert(dest && src);
char *ret = dest;
//1.找到目标空间的\0
while (*dest)
{
dest++;
}
//2.追加
while ( *src)
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
return ret;
}int main()
{
char arr1[20] = "hello ";
char arr2[20] = "world";
/*strcat(arr1, arr2)*/
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
(4)字符串能否给自己追加本身? ??关于字符追加函数能否给本身的字符串追加本身,我们可以根据上面的strcat模拟实现的函数进行分析。
回顾strcat字符追加函数的过程:
以下列代码举例
#include
#include
int main()
{
char arr="abc";
strcat(arr,arr);
return 0;
}
文章图片
4.strcmp函数的介绍及模拟实现
(1)strcmp函数的使用 注意:
??strcmp函数比较的不是字符串的长度,而是字符串对应字符的ASCII码值
#include
#include int main()
{
char arr1[]="abcdef";
chararr2[]="abc";
if(strcmp(arr1,arr2)<0)
printf("arr1);
else if(strcmp(arr1,arr2)>0)
printf("arr1>arr2\n");
else if(strcmp(arr1,arr2)==0)
printf("arr1=arr2");
return 0;
}
代码显示效果:
文章图片
(2)strcmp函数功能
文章图片
文章图片
??strcmp函数的函数功能是比较两个字符串,那么如何进行比较呢?strcmp函数比较的是字符串对应的字符的ASCII码值,返回值是int类型的,分别向函数内部传入两个字符串s1、s2。
文章图片
(3)strcmp函数的模拟实现
int my_strcmp(const char *s1, const char *s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
if (*s1 > *s2)
return 1;
else if (*s1 < *s2)
return -1;
// return *s1 - *s2;
//}
注意:
??在模拟过程中我们可以定义 小于时返回-1,大于时返回1,相等时返回0。也可以直接返回*s1-*s2,字符串比较的效果一样。
5.长度受限制的字符串函数的使用
(1)strncpy函数的介绍
文章图片
文章图片
功能介绍:
1.拷贝count个字符从源字符串到目标空间。
2.如果源字符串的长度小于count,则拷贝完源字符串之后,在目标的后边追加0,直到count个。
(2)strncat函数的介绍
文章图片
文章图片
功能介绍:
1.将source的num个字符追加到destination
2.如果source中的字符串长度小于num,则只复制到结束空字符之前的内容。
实现效果如下:
文章图片
(3) strncmp函数的介绍
文章图片
文章图片
功能介绍:
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
6.strstr函数的介绍和模拟实现
(1)strstr函数的使用
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "bcde";
char * ret = strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到字串\n");
}
else
printf("%s\n",ret );
return 0;
}
代码实现效果:
文章图片
(2)strstr函数的功能 通过msdn函数功能查找得知strlen具体使用情况如下
文章图片
文章图片
??我们可得知strstr函数的功能是查找一个字串,或者截取一个字串。第一个参数传一个字符串,第二个参数传一个要查找的字符串。返回类型是char *,如果查找到了,那么返回字符串中查找到的那个字符的指针,直到\0结束。如果未查找到,那么就返回NULL。
(3)strstr函数的模拟实现
#include
#include
#include char * my_strstr(char * s1, char * s2)
{
assert(s1&&s2);
if (*s2 == '\0')
return s1;
char * cp = s1;
while (*s1 != '\0')
{
char *p2 = s2;
char *p1 = cp;
while (*p1 == *p2)
{
p1++;
p2++;
}
if (*p2 == '\0')
{
return cp;
}
cp++;
} return NULL;
}
7.strtok函数的介绍 strtok是一个用来分隔字符串的函数。
文章图片
文章图片
下面给一个例子来演示strtok的具体功能
#include
#include int main()
{
char arr1[] = "crq@2745131427qq.com";
char arr2[30] = { 0 };
char p[] = "@.#";
//分隔符的集合的字符串
strcpy(arr2, arr1);
printf("%s\n", strtok(arr1, p));
printf("%s\n", strtok(NULL, p));
printf("%s\n", strtok(NULL, p));
return 0;
}
代码显示效果:
文章图片
好了,那么strtok函数,我们应该怎样使用呢?
对于第一、二条规则,我们用一个字符串来记录分隔符的集合。(以分隔符为标记,从而进行分割字符串操作)strtok操作会对字符串进行修改,所以我们要拷贝内容到另一个字符串中。
以上面的例子代码为例,strtok 的第一个参数不为NULL,我们进行 strtok(arr1,p),将第一个分隔符@,改为\0。同时函数保存了第一个分隔符的位置。
第二次传参为NULL,我们进行 strtok(NULL,p),此时的NULL虽然传了一个空指针,但是指向了上一次保存的分隔符的位置。从这个位置开始,将下一个分隔符.,改为\0。同时函数保存此位置。
依次进行该操作…??可能有同学会问了:函数内部的变量出函数不是销毁了么,函数怎么保存一个地址变量呢?
我们猜测:在C语言关键字的学习中,我们学到了一个static 的关键字,出了函数也能保存下来。可能这个函数的实现过程中存在一个static关键字,所以每次的标记位置得以保存…??但是我们如果不知道字符串内部有多少分隔符,而且strtok(NULL,p)的操作重复多次,显得冗余,如何进行简化呢?
给出的解决冗余方案:
#include
#include int main()
{
char arr1[] = "crq@2745131427qq.com";
char arr2[30] = { 0 };
char p[] = "@.#";
//分隔符的集合的字符串
strcpy(arr2, arr1);
char *ret = NULL;
for (ret = strtok(arr1, p);
ret != NULL;
ret = strtok(NULL, p))
{
printf("%s\n",ret);
}
/*printf("%s\n", strtok(arr1, p));
*/
//printf("%s\n", strtok(NULL, p));
//printf("%s\n", strtok(NULL, p));
return 0;
}
8.strerror函数的介绍
文章图片
该函数相关信息如下:
文章图片
功能介绍:
错误报告函数,把错误码转换为对应的错误信息,返回错误信息对应的字符串的起始地址。
那么我们平时如何使用呢?
首先引入头文件
#include
#include int main()
{
FILE *pf=fopen("test.txt","r");
if(pf==NULL)
printf("fopen%s\n",strerror(error));
return0;
}
实现效果:
文章图片
9.字符操作函数
(1)字符分类函数
文章图片
(2)字符转换函数
文章图片
文章图片
文章图片
具体这里就不做更多介绍…
二、内存操作函数介绍 ??上述函数都是字符串或字符操作函数,那么如果我们想要拷贝一个整形数组,或者其他类型的数据,我们不能用字符串操作函数时,我们应该怎样拷贝呢?
??在这里,我们引入内存操作函数的概念,我们直接对数据的内存进行操作。
1.memcpy函数的介绍和模拟实现
(1)memcpy函数的功能
文章图片
文章图片
memcpy函数的作用:在两个内存缓冲区进行拷贝数据
返回dest的起始地址处
我们发现memcpy函数的前两个参数都是void * 类型的,第三个参数是拷贝的字节数。
文章图片
(2)memcpy函数的使用
#include
#include int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, sizeof(arr1));
int i = 0;
for (i = 0;
i < 10;
i++)
{
printf("%d", arr2[i]);
}
return 0;
}
代码实现效果:
文章图片
(3) memcpy函数的模拟实现
void * my_memcpy(void * dest, void * src, int num)
{
char*ret = (char *)dest;
while (num--)
{
*(char *)dest = *(char *)src;
++(char *)dest;
++(char *)src;
}
return ret;
}
结构体数据的拷贝过程如下:
struct S
{
char name[20] ;
int age;
};
void * my_memcpy(void * dest, void * src, int num)
{
char*ret = (char *)dest;
while (num--)
{
*(char *)dest = *(char *)src;
++(char *)dest;
++(char *)src;
}
return ret;
}int main()
{
struct S arr1[] = { { "chen", 11 }, {"hai",20} };
struct S arr2[10] ;
my_memcpy(arr2, arr1, sizeof(arr1));
int i = 0;
for (i = 0;
i < 2;
i++)
{
printf("%s %d ", arr2[i].name,arr2[i].age);
}
return 0;
}
【c语言|C语言进阶(五)——字符串+内存函数的介绍】实现效果如下
文章图片
(4)memcpy函数的缺点 现在有一个要求:
文章图片
文章图片
??所以,我们并不能按照我们的要求打印,内存相互重叠的情况下,内存的数字会发生改变。而在memmove 函数中则完美的解决了这个问题(内存重叠)。
2.memmove函数的介绍和模拟实现
(1)memmove函数的功能 ??memmove和memcopy 功能 和 函数的参数 都大部分相同
文章图片
区别的是:
文章图片
(2)memmove函数的模拟实现 首先我们要明确怎样拷贝不影响内存重叠
文章图片
将 2,3,4,5 拷贝到 4,5,6,7。
这种情况下 src
这种情况下 src>dest,我们将src中的数据从前向后进行拷贝,可以避免内存重叠的影响。
我们模拟实现时,考虑如何从后向前拷贝,如何从前向后拷贝。
#include
void* my_memmove(void * dest, void *src, int num)
{
char * ret = (char*)dest;
assert(dest&&src);
if (src > dest)
{
//从前向后
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
}
else if (src < dest)
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
} return ret;
}
代码实现效果:
文章图片
避免了内存重叠,成功实现!!
3.memcmp函数的介绍
文章图片
文章图片
(1)memcmp函数的功能 对各种类型进行比较
(2)memcmp函数的使用 例:整形数据的比较
int main()
{ int arr1[] = { 1, 5, 6, 7, 8, 9 };
int arr2[] = { 1, 2, 3, 4, 5, 6 };
int ret=memcmp(arr1, arr2, 8);
printf("%d\n", ret);
return 0;
}
文章图片
4.memset函数的介绍
文章图片
文章图片
(1)memset函数功能 ??函数的三个参数(目标的起始指针处,设置的字符,设置修改字符的字节),将目标的字符串或者其他数据改为设置的字符或其他类型。
(2)memset函数的使用
int main()
{
char arr[] = "###########";
memset(arr, '*', 5);
printf("%s\n", arr);
}
文章图片
好了,内存+字符串函数的说明就介绍到这里,希望大家多多练习,谢谢欣赏!!
未完待续!!
C语言进阶(六)——自定义类型详解(结构体+枚举+联合)已更新
推荐阅读
- c语言|C语言中,C进阶中字符函数、字符串函数、内存函数详解。
- 笔记|面试官让我写strlen函数(|详解字符串函数与内存函数【C语言/进阶】)
- c语言|C语言进阶学习日志(字符串和内存函数(一))
- C语言篇|【C语言学习】字符函数和字符串函数【进阶详解篇15】
- 算法|【算法】【C语言进阶】C语言字符串操作宝藏级别汇总 strtok函数 strstr函数该怎么用(【超详细的使用解释和模拟实现】)
- C语言编程学习|【C语言进阶学习笔记】三、字符串函数+内存函数详解(2)
- C语言笔记|C语言进阶笔记(六) | 详解内存函数及其模拟
- 排序算法|常见的排序算法(上)
- 数据结构|LeetCode每日一刷 --- 拿捏顺序表经典面试题