目录
[0. 前言](#0. 前言)
[2.1 strcpy](#2.1 strcpy)
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
易错提醒
cpp
请问ret的值是多少?
int ret = strlen("abc") - strlen("abcdef");
答案是3,因为函数的返回值为size_t,是无符号的整型。
strlen
函数是C语言中的一个库函数,用于计算字符串的长度(不包括字符串末尾的空字符\0
)。它位于<string.h>
头文件中。
strlen
函数的原型如下:
cpp
size_t strlen(const char *str);
const char *str
:指向要计算长度的字符串的指针。
strlen
函数会从指定的字符串地址开始遍历,直到遇到字符串结束标记\0为止 ,统计期间遇到的字符数量,然后返回计数结果。
下面是一个示例代码,展示了如何使用strlen
函数来计算字符串的长度:
cpp
#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;
}
输出结果为:
cpp
The length of the string is: 13
在上面的例子中,strlen
函数被用来计算字符串str
的长度,并将结果存储在len
变量中,然后通过printf
函数进行输出。
模拟实现
cpp
int my_strlen(char* str)
{
int count = 0;
while (*arr != '\0')
{
count++;
arr++;
}
return count;
}
方法二、
cppsize_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语言中用于字符串复制的函数,其原型为:
cpp
char* strcpy(char* destination, const char* source);
`strcpy`函数将源字符串 `source` 复制到目标字符串 `destination` 中,包括字符串结束符 `'\0'` 。复制的过程会覆盖原来 `destination` 中的内容。
`strcpy`函数的工作原理是从源字符串 `source` 的第一个字符开始,逐个将字符复制到目标字符串 `destination` 中,直到遇到字符串结束符 `'\0'` 为止。复制完成后,目标字符串 `destination` 会成为与源字符串 `source` 相同的副本。
需要注意的是,为了避免内存溢出,目标字符串 `destination` 的空间应该足够大,至少能够容纳源字符串 `source` 和字符串结束符 `'\0'`。
`strcpy`函数的返回值是目标字符串 `destination` 的指针,即函数执行完后,返回指向目标字符串的指针。
下面是一个简单的示例代码,演示了 strcpy
函数的使用:
cpp
#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是一个常量字符串没有办法被修改
模拟实现
cppchar* 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
cpp
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
函数用于比较两个字符串,它返回一个整数值,表示两个字符串的大小关系。
函数原型如下:
cpp
int strcmp(const char* str1, const char* str2);
参数 str1
和 str2
是需要比较的两个字符串。
- 如果
str1
和str2
相等,strcmp
返回值为 0。 - 如果
str1
大于str2
,strcmp
返回值大于 0。 - 如果
str1
小于str2
,strcmp
返回值小于 0。
下面是一个示例代码,演示了 strcmp
函数的用法:
cpp
#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;
}
输出结果为:
cpp
str1 小于 str2
上述示例中,strcmp
函数比较了两个字符串 "apple"
和 "banana"
,并根据比较结果输出相应的信息。由于字母 "a" 的 ASCII 值小于字母 "b",因此 str1
小于 str2
。
易错:strcmp不是比较字符串长度的,而是比较对应位置上字符的大小(ASCII)
模拟实现
cpp
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
函数是一个用于复制字符串的函数。它的原型如下:
cpp
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
函数:
cpp
#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;
}
输出结果:
cpp
Source: Hello, World!
Destination: Hello, World!
在这个示例中,我们将源字符串 "Hello, World!" 复制到了目标字符串
dest
中,并保证了目标字符串的正确终止。由于dest
的大小为 20,所以在复制后,目标字符串中的剩余部分将被空字符\0
填充。
3.2strncat
- 区别也仅与strcat差一个参数,记录要操作的个数。
- 使用strncat追加,当结束追加时,就算没到\0,也会在末尾追加一个\0。
- 如果源字符串的长度小于num ,则追加完源字符串之后,会自动停止追加。注意此处与strncpy的区别。
- 包含头文件**<string.h>。**
下面是示例代码:
cpp
#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;
}
输出结果为:
cppResult of strcat: Hello world! Result of strncat: Hello world
可以看到,在使用
strncat
函数时,只拼接了源字符串的前5个字符。
3.3strncmp
- 区别也仅与strcmp差一个参数,记录要操作的个数。
- 包含头文件**<string.h>。**
下面是一个使用strncmp函数比较两个字符串的示例代码:
cpp
#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语言字符串处理函数,用于在一个字符串中查找另一个字符串的第一次出现位置。
函数原型如下:
cpp
char* strstr(const char* str1, const char* str2);
函数接受两个参数:str1和str2。str1是源字符串,在该字符串中进行查找操作。str2是要查找的目标字符串。
函数的返回值是一个指向第一次在str1中出现str2的位置的指针。如果未找到str2,函数返回NULL。
strstr函数的工作原理是基于字符串匹配算法,通常使用的是KMP算法或Boyer-Moore算法等。它会从str1的第一个字符开始比较,如果找到了一个匹配的字符,就会继续比较下一个字符。如果完全匹配,就返回匹配位置的指针。如果未能找到匹配,就继续在剩余的str2中继续查找。
cpp
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
模拟实现
cs
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语言中的一个字符串分割函数,其原型为:
cpp
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函数分割一个字符串:
cpp
#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的地址。
实现自动分割字符串
cppchar* 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
函数的原型如下:
cpp
#include <string.h>
char *strerror(int errnum);
其中,
errnum
是一个整数类型的参数,表示错误码。函数会根据errnum
找到对应的错误消息字符串,并返回该字符串的指针。使用
strerror
函数,我们可以根据系统函数返回的错误码获取相应的错误信息,从而更好地了解问题所在,方便进行调试和错误处理。
- strerror函数是将错误码翻译成错误信息,返回错误信息的字符串起始地址。
- 包含头文件**<string.h>。**
- C语言中使用库函数的时候,如果发生错误,就会将错误码放在errno的变量中,errno是一个 全局变量,可以直接使用。
cpp
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d: %s\n", i, strerror(i));//
}
return 0;
}
每一个错误码都对应一个错误信息。
【使用方式】
以打开文件为例子,fopen以读的形式打开文件,当文件存在时打开成功,文件不存在时打开失败,并返回空指针。可以利用这个来设置一个打开失败时的错误信息告知。
【使用方法】
cpp
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 语言中的一个标准库函数,它用于将内存块的内容从源地址复制到目标地址。它的函数原型如下:
cpp
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()
函数的示例:
cpp
#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
函数打印出复制结果。
模拟实现
cpp
函数拷贝结束后,返回目标空间的起始地址
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
cppvoid* 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到末尾之间的位置,那就是从后向前面拷贝
指针可以比较大小
模拟实现
cppvoid* 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()
函数在初始化内存块、清零内存块、以及将内存块中的特定字节设置为某个值时非常有用。例如:
cpp
#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;
}
输出结果为:
cpp
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()
函数的示例:
cpp
#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
,因此打印出相应的结果。