目录
0. 前言
1、求字符串长度函数
1.1、strlen
模拟实现
2.长度不受限制的字符串函数
2.1 strcpy
模拟实现
2.2strcat
模拟实现
2.3strcmp
模拟实现
3.长度受限制的字符串函数
3.1strncpy
3.2strncat
3.3strncmp
4、字符串查找函数
4.1strstr
模拟实现
3.2strtok
实现自动分割字符串
4、错误信息报告函数
4.1、strerror
4.2、perror
5.内存操作函数
5.1、memcpy
模拟实现
5.2、memmove
模拟实现
5.3、memset
5.4、memcmp
0. 前言
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组中。 字符串常量适用于那些对它不做修改的字符串函数
1、求字符串长度函数
1.1、strlen
- 1.strlen用于求字符串长度。
- 2.包含头文件<string.h>。
- 3.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
- 4.参数指向的字符串必须要以 '\0' 结束。
注意:
- 函数的返回值为size_t,是无符号的( 易错 )
这里输出的应该是大于,为什么呢,就是这里的strlen函数的返回的是无符号类型的,所以-3会被当作无符号数来看待,
- 由于
strlen
返回的是size_t
类型,所以在输出时应该使用对应的格式说明符,如%zu
。因为strlen返回的是 '\0' 前面的字符个数,如果字符串中间本身就一个'\0',那么返回的值就会返回字符串中的'\0'之前的字符个数。
例如:"abc\0def" 这个字符串,使用strlen函数会返回3
易错提醒
请问ret的值是多少?
int ret = strlen("abc") - strlen("abcdef");
答案是3,因为函数的返回值为size_t,是无符号的整型。
strlen
函数是C语言中的一个库函数,用于计算字符串的长度(不包括字符串末尾的空字符\0
)。它位于<string.h>
头文件中。
strlen
函数的原型如下:
size_t strlen(const char *str);
const char *str
:指向要计算长度的字符串的指针。
strlen
函数会从指定的字符串地址开始遍历,直到遇到字符串结束标记\0
为止,统计期间遇到的字符数量,然后返回计数结果。
下面是一个示例代码,展示了如何使用strlen
函数来计算字符串的长度:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
size_t len = strlen(str);
printf("The length of the string is: %zu\n", len);
return 0;
}
输出结果为:
The length of the string is: 13
在上面的例子中,strlen
函数被用来计算字符串str
的长度,并将结果存储在len
变量中,然后通过printf
函数进行输出。
模拟实现
int my_strlen(char* str)
{
int count = 0;
while (*arr != '\0')
{
count++;
arr++;
}
return count;
}
方法二、
size_t my_strlen(const char* str) { const char* end = str; while (*end) { ++end; } return end - str; }
指针-指针的方式实现先把初始地址给end,然后end向后走直到遇到\0,最后返回初始地址和结束地址的差值就是中间的字符个数。
2.长度不受限制的字符串函数
2.1 strcpy
`strcpy`函数是C语言中用于字符串复制的函数,其原型为:
char* strcpy(char* destination, const char* source);
`strcpy`函数将源字符串 `source` 复制到目标字符串 `destination` 中,包括字符串结束符 `'\0'`。复制的过程会覆盖原来 `destination` 中的内容。
`strcpy`函数的工作原理是从源字符串 `source` 的第一个字符开始,逐个将字符复制到目标字符串 `destination` 中,直到遇到字符串结束符 `'\0'` 为止。复制完成后,目标字符串 `destination` 会成为与源字符串 `source` 相同的副本。
需要注意的是,为了避免内存溢出,目标字符串 `destination` 的空间应该足够大,至少能够容纳源字符串 `source` 和字符串结束符 `'\0'`。
`strcpy`函数的返回值是目标字符串 `destination` 的指针,即函数执行完后,返回指向目标字符串的指针。
下面是一个简单的示例代码,演示了 strcpy
函数的使用:
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Hello, World!";
char destination[20];
strcpy(destination, source);
printf("Copied string: %s\n", destination);
return 0;
}
上述代码会输出:Copied string: Hello, World!
。
注意事项:
- strcpy用于拷贝字符串,将字符串2拷贝到字符串1当中。
- 包含头文件<string.h>。
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
验证确实是拷贝了\0
源字符串必须以\0结尾
目标空间必须可变化 这里就没法完成复制了,因为arr1是一个常量字符串没有办法被修改
模拟实现
char* my_strcpy(char* dest,const char* src) { char* ret = dest; while (*dest = *src) { dest++; src++; } return ret; }
2.2strcat
cat
是 concatenate
(连接)的缩写。
strcat
函数是C语言中用于字符串拼接的函数,其原型为:
char* strcat(char* destination, const char* source);
效果
:strcat
函数将源字符串source
追加到目标字符串destination
的末尾,拼接的结果会改变目标字符串destination
。
工作原理:strcat
函数的工作原理是首先定位到目标字符串destination
的结束符'\0'
的位置,然后从源字符串source
的第一个字符开始,逐个将字符复制到目标字符串的结束符之前,直到遇到源字符串的结束符'\0'
为止。完成拼接后,目标字符串destination
会包含原有内容和源字符串source
的内容。
需要注意的是,为了避免内存溢出,目标字符串
destination
的空间应该足够大,以容纳源字符串source
的内容及拼接后的结果。源字符串必须以 '\0' 结束(保证找得到目标空间的末尾),在拷贝时会把源字符串的 '\0 '也拷贝过去
不能字符串自己追加自己,因为当自己追加自己的时候,追加的过程中会将目标字符串的 '\0' 覆盖掉,(因为自己追加自己两个指针指向的是同一块空间)而有因为此时目标字符串就是源字符串,就会导致源字符没有 '\0' ,将会一直拼接下去导致死循环。
虽然有些环境中该函数可以完成自己拼接自己,但是C语言的标准中并未规定strcat可以自己拼接自己,所以这个函数最好不要使用在自己拼接自己的情况下。如果真有自己追加自己的场景,建议使用strncat函数
返回值:strcat
函数的返回值是目标字符串destination
的指针,即函数执行完后,返回指向目标字符串的指针。
模拟实现
1.先找到目标空间的\0
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
//1. 找目标空间中的\0
while (*dest)
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
问题:字符能不能自己给自己追加?
不能
源头和目标都是一块空间了,当src把h替代了\0,之后src就没有办法遇到\0了,因为追加第一个的时候就修改掉了\0
2.3strcmp
strcmp
函数用于比较两个字符串,它返回一个整数值,表示两个字符串的大小关系。
函数原型如下:
int strcmp(const char* str1, const char* str2);
参数 str1
和 str2
是需要比较的两个字符串。
- 如果
str1
和str2
相等,strcmp
返回值为 0。 - 如果
str1
大于str2
,strcmp
返回值大于 0。 - 如果
str1
小于str2
,strcmp
返回值小于 0。
下面是一个示例代码,演示了 strcmp
函数的用法:
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "apple";
char str2[] = "banana";
int result = strcmp(str1, str2);
if(result == 0) {
printf("str1 和 str2 相等\n");
} else if(result > 0) {
printf("str1 大于 str2\n");
} else {
printf("str1 小于 str2\n");
}
return 0;
}
输出结果为:
str1 小于 str2
上述示例中,strcmp
函数比较了两个字符串 "apple"
和 "banana"
,并根据比较结果输出相应的信息。由于字母 "a" 的 ASCII 值小于字母 "b",因此 str1
小于 str2
。
易错:strcmp不是比较字符串长度的,而是比较对应位置上字符的大小(ASCII)
模拟实现
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);
}
//VS
//> 1
//= 0
//< -1
//
int main()
{
int ret = my_strcmp("bbq", "bcq");
if (ret>0)
printf(">\n");
printf("%d\n", ret);
return 0;
}
先排除相等的部分,剩下不相等的部分才进行比较,第一个while循环中*str1==‘\0’判读是不是读完了
3.长度受限制的字符串函数
3.1strncpy
函数介绍:
strncpy
函数是一个用于复制字符串的函数。它的原型如下:
char *strncpy(char *dest, const char *src, size_t n);
strncpy
函数将从源字符串src
复制最多n
个字符到目标字符串dest
中。如果
src
的长度小于n
,则复制完src
中的所有字符后,将剩余部分用空字符\0
填充直到n。如果
src
的长度大于等于n
,则仅复制前n
个字符,不会添加额外的空字符。
需要注意的是,
strncpy
函数没有在目标字符串dest
的末尾自动添加终止符\0
的能力。因此,在使用strncpy
复制字符串后,需要手动在dest
的最后一个元素添加\0
,以确保目标字符串正确终止。
相比较于strcpy函数多了一个参数 n。
下面是一个示例代码,展示了如何使用 strncpy
函数:
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[20];
strncpy(dest, src, sizeof(dest));
dest[sizeof(dest) - 1] = '\0';
printf("Source: %s\n", src);
printf("Destination: %s\n", dest);
return 0;
}
输出结果:
Source: Hello, World!
Destination: Hello, World!
在这个示例中,我们将源字符串 "Hello, World!" 复制到了目标字符串
dest
中,并保证了目标字符串的正确终止。由于dest
的大小为 20,所以在复制后,目标字符串中的剩余部分将被空字符\0
填充。
3.2strncat
- 区别也仅与strcat差一个参数,记录要操作的个数。
- 使用strncat追加,当结束追加时,就算没到\0,也会在末尾追加一个\0。
- 如果源字符串的长度小于num,则追加完源字符串之后,会自动停止追加。注意此处与strncpy的区别。
- 包含头文件<string.h>。
下面是示例代码:
#include <stdio.h>
#include <string.h>
int main() {
char s1[20] = "Hello ";
char s2[] = "world!";
strcat(s1, s2);
printf("Result of strcat: %s\n", s1);
char s3[20] = "Hello ";
char s4[] = "world!";
strncat(s3, s4, 5);
printf("Result of strncat: %s\n", s3);
return 0;
}
输出结果为:
Result of strcat: Hello world! Result of strncat: Hello world
可以看到,在使用
strncat
函数时,只拼接了源字符串的前5个字符。
3.3strncmp
- 区别也仅与strcmp差一个参数,记录要操作的个数。
- 包含头文件<string.h>。
下面是一个使用strncmp函数比较两个字符串的示例代码:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "Hello";
char str2[] = "World";
int result = strncmp(str1, str2, 3); // 只比较前3个字符
if (result == 0)
{
printf("str1和str2的前3个字符完全相同\n");
}
else if (result < 0)
{
printf("str1小于str2\n");
}
else
{
printf("str1大于str2\n");
}
return 0;
}
以上代码输出结果为"str1小于str2",因为在比较前3个字符时,'H'的ASCII值为72,'W'的ASCII值为87,72小于87。
4、字符串查找函数
4.1strstr
strstr函数是一个C语言字符串处理函数,用于在一个字符串中查找另一个字符串的第一次出现位置。
函数原型如下:
char* strstr(const char* str1, const char* str2);
函数接受两个参数:str1和str2。str1是源字符串,在该字符串中进行查找操作。str2是要查找的目标字符串。
函数的返回值是一个指向第一次在str1中出现str2的位置的指针。如果未找到str2,函数返回NULL。
strstr函数的工作原理是基于字符串匹配算法,通常使用的是KMP算法或Boyer-Moore算法等。它会从str1的第一个字符开始比较,如果找到了一个匹配的字符,就会继续比较下一个字符。如果完全匹配,就返回匹配位置的指针。如果未能找到匹配,就继续在剩余的str2中继续查找。
int main()
{
char arr1[] = "abcdefghidef"; //def出现了两次
char arr2[] = "def";
char* ret = strstr(arr1, arr2);
if (ret == NULL)
printf("找不到\n");
else
printf("%s\n", ret);
return 0;
}
结果是defghidef
模拟实现
char* my_strstr(char *str1, char* str2)
{
char* cp = str1;
char* s1 = cp;
char* s2 = str2;
if (*str2 == '\0')
return str1;
while (*cp)
{
//开始匹配
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return cp;
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret != NULL)
printf("%s\n", ret);
else
printf("找不到\n");
return 0;
}
Cp最开始指向起始位置,cp赋给s1
*cp不等于\0,因为等于\0说明检查完了,就返回NULL
S1和s2来遍历字符串
没有匹配完全的话,跳出第二个while
循环,然后cp++,改变开始匹配的位置,然后把cp赋给s1,重新赋值给s1是因为要找到开始匹配的正确位置,每次cp都像后面移动一位
应该返回cp因为只有*s1==*s2才会进入循环,这个时候cp里面是第一次出现位置的指针。
只有*s2为\0才是才是在str1中匹配到了str2
最前面是特殊情况是str2是空字符串
3.2strtok
strtok函数是C语言中的一个字符串分割函数,其原型为:
char *strtok(char *str, const char *delim);
该函数的作用是将字符串str按照指定的分割符delim进行分割,并返回分割后的第一个子字符串。同时,该函数会静态地记录当前的分割位置,便于下一次调用时继续分割剩余的字符串。
函数的使用步骤如下:
- 在第一次调用时,需要将待分割的字符串str传入,之后的调用中将传入NULL。strtok函数会将其修改,将分割出的子字符串以'\0'结尾,并返回该子字符串的指针。
- 在第一次调用时,需要将分割符delim传入。之后的调用中,delim可以传入NULL。如果传入NULL,则将沿用上一次调用时的分割符。
- 使用返回的子字符串指针进行处理操作,之后再次调用strtok函数可以获取下一个分割出的子字符串指针。直到返回NULL,表示没有更多的子字符串可供分割。
-
delimiters参数是个字符串,定义了用作分隔符的字符集合。
第一个参数指定一个字符串,它包含了0个或者多个由delimiters字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针
下面是一个简单的示例代码,展示了如何使用strtok函数分割一个字符串:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello,World!How,are,you?";
char *token;
// 第一次调用strtok函数
token = strtok(str, ",!");
printf("%s\n", token); // 输出"Hello"
// 之后的调用
while ((token = strtok(NULL, ",!")) != NULL) {
printf("%s\n", token);
}
return 0;
}
该代码首先将字符串"Hello,World!How,are,you?"传给strtok函数进行第一次调用。由于传入的分割符为",!",所以它会将字符串分割成"Hello"、"World"、"How"、"are"和"you?"五个子字符串。然后,通过循环调用strtok函数,我们可以依次输出这五个子字符串。
第一次调用把,改为\0然后返回H的地址,第二次函数已经记住了第一次标记的位置,然后向后访问直到找到下一个标记然后改为\0,再传回来W的地址。
实现自动分割字符串
char* ret = NULL; for (ret = strtok(copy, sep); ret != NULL; ret=strtok(NULL, sep)) { printf("%s\n", ret); }
初始部分就是第一次调用strtok函数,判断部分是判断
调整部分是传空指针直到切割完了。
循环中的判断部分
ret != NULL
是用来判断strtok
函数返回的切割结果是否为NULL
,如果是NULL
,则意味着没有更多的切割结果了,循环就会结束。换句话说,当strtok
函数切割完所有的子字符串之后,它会返回NULL
,这时循环就会终止。
4、错误信息报告函数
4.1、strerror
strerror
函数是一个 C 标准库中的函数,它可以根据给定的错误码返回对应的错误消息字符串。
strerror
函数的原型如下:
#include <string.h>
char *strerror(int errnum);
其中,
errnum
是一个整数类型的参数,表示错误码。函数会根据errnum
找到对应的错误消息字符串,并返回该字符串的指针。使用
strerror
函数,我们可以根据系统函数返回的错误码获取相应的错误信息,从而更好地了解问题所在,方便进行调试和错误处理。
- strerror函数是将错误码翻译成错误信息,返回错误信息的字符串起始地址。
- 包含头文件<string.h>。
- C语言中使用库函数的时候,如果发生错误,就会将错误码放在errno的变量中,errno是一个 全局变量,可以直接使用。
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d: %s\n", i, strerror(i));//
}
return 0;
}
每一个错误码都对应一个错误信息。
【使用方式】
以打开文件为例子,fopen以读的形式打开文件,当文件存在时打开成功,文件不存在时打开失败,并返回空指针。可以利用这个来设置一个打开失败时的错误信息告知。
【使用方法】
int main()
{
FILE* pf = fopen("add.txt", "r"); //当前文件路径中并没有add.txt文件,打开失败
if (pf == NULL)
{
printf("打开文件失败,原因是:%s\n", strerror(errno));
return 1;
}
else
{
printf("打开文件成功\n");
}
return 0;
}
fopen
是 C 语言标准库中的一个函数,用于打开一个文件。函数声明如下:FILE *fopen(const char *filename, const char *mode);
fopen
函数接受两个参数,第一个参数filename
是一个字符串,表示文件的路径或名称;第二个参数mode
是一个字符串,表示文件的打开模式,可以是以下几种之一:
"r"
:以只读方式打开文件。"w"
:以写入方式创建文件,如果文件已存在则清空文件内容。"a"
:以写入方式打开文件,如果文件不存在则创建文件,新增的内容会被追加到文件末尾。"rb"
:以二进制只读方式打开文件。"wb"
:以二进制写入方式创建文件,如果文件已存在则清空文件内容。"ab"
:以二进制写入方式打开文件,如果文件不存在则创建文件,新增的内容会被追加到文件末尾。
fopen
函数返回一个FILE*
类型的指针,如果打开文件成功,则返回指向该文件的指针;如果打开文件失败,则返回NULL
。
4.2、perror
perror
是 C 语言标准库中的一个函数,用于打印与当前错误代码相对应的错误信息到标准错误文件stderr
中。函数声明如下:
void perror(const char *s);
perror
函数接受一个参数s
,表示要输出的错误信息前缀。它会根据全局变量errno
的值,在标准错误文件上输出一个相应的错误信息,形如s: 错误信息
。
perror也是用于翻译错误信息 ,但与strerror不同的是,perror会直接打印错误码所对应的错误信息。而perror中传递的字符串参数就是自定义显示信息的部分,打印的结果就是 自定义显示信息:错误信息
包含头文件<stdlib.h>
可以简单理解为:perror = printf + strerror 即翻译又打印
5.内存操作函数
为了满足各种数据都可以使用的情况而不只是字符串,我们要从内存入手。下面我们来学习一下内存操作函数。
5.1、memcpy
memcpy()
函数是 C 语言中的一个标准库函数,它用于将内存块的内容从源地址复制到目标地址。它的函数原型如下:
void *memcpy(void *dest, const void *src, size_t n);
dest
:目标地址,即复制后的数据将存储的位置。src
:源地址,即要被复制的数据的起始位置。n
:要复制的字节数。- 拷贝结束之后返回目标空间的起始地址
memcpy()
函数会将src
地址开始的n
个字节的内容复制到dest
地址开始的内存区域。需要注意的是,复制过程中不会考虑字符的含义,只是简单地复制二进制数据。函数memcpy从source的位置开始向后拷贝num个字节的数据到destination的内存位置。
包含头文件<string.h>
这个函数在遇到 '\0' 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。
因为C语言标准中并未规定memcpy能适用于重叠内存的拷贝,因此不重叠内存的拷贝才使用memcpy,而重叠内存的拷贝使用接下来讲解的memmove函数。
下面是一个使用 memcpy()
函数的示例:
#include <stdio.h>
#include <string.h>
int main() {
const char src[] = "Hello, World!";
char dest[100];
memcpy(dest, src, strlen(src) + 1);
printf("Copied string: %s\n", dest);
return 0;
}
在这个示例中,我们首先定义了一个源字符串 src
,然后创建了一个足够大的目标字符串 dest
来存储复制后的内容。然后,memcpy()
函数将 src
字符串的内容复制到 dest
字符串,并通过 printf
函数打印出复制结果。
模拟实现
函数拷贝结束后,返回目标空间的起始地址
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(src && dest);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, 21);
int i = 0;
for (i = 0; i < 20; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
写成(char*)dest++是不能实现指针先后走一个bit的,因为这里强制转换是临时的,++的时候已经没用了。
如果拷贝有重叠的空间会怎么样呢
比如传参为arr+2和arr1
void* my_memcpy(void* dest, const void* src, size_t num) { void* ret = dest; assert(src && dest); while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; // 1 2 1 2 3 4 5 8 9 10 my_memcpy(arr1+2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
结果不是我们想要的那样1 21 2 3 4 5 8 9 10
因为空间上有重叠的地方
把34拷贝为12之后想要把56拷贝为34就没有办法实现了因为34已经被改成12了。
memcpy函数是用来处理不重叠的内存的拷贝的,处理有重叠的内存的拷贝的使用memmove函数
5.2、memmove
原来出现的错误的原因是因为拷贝给后面的空间的时候前
想办法不被覆盖。到着来拷贝可以解决问题先把5拷贝到7的位置,4拷贝到6的位置,
但是不能一劳永逸。比如如果我把src和des调换就出错了
dest在src前面就要倒着拷贝,dest在src后面就要
一次性解决:
如果dest落在src前面那就是从前向后拷贝就是说先把src的第一个位置拷贝到dest依次往后
如果dest落在src到末尾之间的位置,那就是从后向前面拷贝
指针可以比较大小
模拟实现
void* my_memmove(void* dest, const void* src, size_t num) { void* ret = dest; assert(dest && src); if (dest < src) { //前->后 while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { //后->前 while (num--)//20 { *((char*)dest + num) = *((char*)src + num); } } return ret; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; // 1 2 1 2 3 4 5 8 9 10 my_memmove(arr1, arr1+2, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
后向前拷贝要先找到src+num的位置,这个是第一个要拷贝的。
5.3、memset
memset()
函数用于将一块内存区域的每个字节都设置为特定的值。其函数原型如下:
void *memset(void *ptr, int value, size_t num);
ptr
:指向要设置值的内存区域的指针。value
:要设置的值,它的类型是int
,但会被转换成unsigned char
。num
:要被设置的字节数。- 将ptr所指向空间的前num个字节设置为指定值value。
- 包含头文件<string.h>
memset()
函数在初始化内存块、清零内存块、以及将内存块中的特定字节设置为某个值时非常有用。例如:
#include <stdio.h>
#include <string.h>
int main() {
char str[50];
strcpy(str, "Hello");
printf("Before memset: %s\n", str);
memset(str, '$', 3);
printf("After memset: %s\n", str);
return 0;
}
输出结果为:
Before memset: Hello
After memset: $$$lo
在上述示例中,memset()
函数将字符串str
的前3个字节设置为'$'
,修改了字符串的一部分内容。
5.4、memcmp
memcmp()
函数用于比较两个内存区域的内容是否相同。其函数原型如下:
int memcmp(const void *ptr1, const void *ptr2, size_t num);
ptr1
:指向要比较的第一个内存区域的指针。ptr2
:指向要比较的第二个内存区域的指针。num
:要比较的字节数。
memcmp()
函数将比较两个内存区域中的字节内容,并返回一个整数结果,表示比较结果的大小关系:
- 如果
ptr1
和ptr2
指向的内存区域完全相同,则返回值为0。- 如果
ptr1
指向的内存区域小于ptr2
指向的内存区域,则返回值小于0。- 如果
ptr1
指向的内存区域大于ptr2
指向的内存区域,则返回值大于0。下面是一个使用
memcmp()
函数的示例:
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "Hello";
char str2[] = "World";
int result = memcmp(str1, str2, 5);
if (result == 0) {
printf("str1 and str2 are equal.\n");
} else if (result < 0) {
printf("str1 is less than str2.\n");
} else {
printf("str1 is greater than str2.\n");
}
return 0;
}
输出结果为:
str1 is less than str2.
在上述示例中,
memcmp()
函数比较了两个字符串str1
和str2
的前5个字节内容,发现str1
小于str2
,因此打印出相应的结果。