谈谈String.h头文件里面定义的字符串以及内存函数谈谈String.h头文件中定义的字符串以及内存函数 字符串相关函
谈谈String.h头文件中定义的字符串以及内存函数
字符串相关函数
strlen(求字符串长度)
size_t strlen(const char* str)
- '\0'作为结束标志, 返回'\0‘之前的字符个数
- 返回值类型size_t 是无符号整数(size_t在32位平台下为4个字节,64位平台下为8个字节), 注意如果是返回值直接参与运算的话,不能将size_t类型直接当成整型进行运算,否则可能会出现溢出的情况
#include <stdio.h>
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;
}
最终的输出结果是 str2>str1 因为表达式strlen(str2)-strlen(str1)的结果是一个负数,但在这里要表达为一个无符号整数, 所以结果是一个很大的整数, 那么就会出现结果错误的情况
strcpy(拷贝字符串)
char* strcpy(char * destination, const char * source );
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。(这样才能标志一个字符串)
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。(才能够完成拷贝操作)
- 是对目标空间的内存进行覆盖操作
strcat(追加字符串)
char * strcat ( char * destination, const char * source );
- 源字符串必须以 '\0' 结束。(不然无法判断字符串末尾 也就是追加的位置)
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改
注意: 如果字符串自己给自己追加 那么结尾的'\0‘会被覆盖掉,陷入死循环,最好不要自己给自己追加
strcmp(字符串比较)
int strcmp ( const char * str1, const char * str2 )
判断大小规则: 一个个字符对应着比较ACSII码值
- 第一个字符串大于第二个字符串,则返回大于0的数字 一般返回1
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字 一般返回-1
strncpy(字符串拷贝,指定拷贝num个字符)
char * strncpy ( char * destination, const char * source, size_t num );
- 只拷贝num个字符, 如果source没有那么多个字符, 就直接补'\0',直到num个
strncat(追加指定n个字符)
char * strncat ( char * destination, const char * source, size_t num );
追加完加上'\0‘标志新字符串的结束
strncmp(指定n个字符的比较)
int strncmp ( const char * str1, const char * str2, size_t num );
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
strstr(在字符串里找子串)
char * my_strstr(const char*str1,const char*str2)
{
char *s1 = str1;
char *cp = str1;
char *s2 = str2;
while(*cp)
{
s1 = cp;
s2 = str2;
while (*s1&&*s2&&*s1==*s2)
{
s1++;
s2++;
}
if(*s2 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
s1指向母字符串 s2指向子字符串, cp指向母字符串标志此时检验位置
s1从cp(当前检验位置)开始, 逐个移动, s2也同步逐个移动, 如果有不一样的就退出, cp移动到下一个位置, 再次进行检验 s1指向cp s2重新指向str2
strtok(分割字符串)
char * strtok ( char * str, const char * sep );
192.168.110.23 拿出每一段字符 192 168 110 23 类似于Java的spilt 不同的是可以有多个分隔符 sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
- strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。 如果字符串中不存在更多的标记,则返回 NULL 指针。
调用过程大致如下:
#include <stdio.h>
#include <string.h>
int main()
{
char *p = "1067367579@github.com";
const char *sep = ".@";
char arr[30];
char *str = NULL;
strcpy(arr, p); // 将数据拷贝一份,处理arr数组的内容
//第一次要传入目的字符串的起始地址 之后就传入NULL即可 有记忆功能 每次找到下一个分隔符 然后替换为'\0'
for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
}
strerrno(找到错误码对应提示信息的字符串)
char * strerror ( int errnum );
库函数在执行的时候 发生了错误 会错误码存储到一个变量当中 全局变量 然后根据错误码返回相对应的错误信息字符串 变量名为errno, errno每次发生错误的时候都会覆盖
字符分类函数
内存相关函数(只关注内存中每个字节)
memcpy(指定字节数内存拷贝)
void * memcpy ( void * destination, const void * source, size_t num );
-
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
-
如果source和destination有任何的重叠,复制的结果都是未定义的(例如 1 2 3 4 5 6 7 8 9 10 如果将前五个元素拷贝到第三个到第七个元素的位置 使用memcpy函数最后结果为1 2 1 2 1 2 1 8 9 10) 原因是拷贝是原地拷贝,在拷贝的过程中如果两个指定的内存范围重叠,那么拷贝的过程中待拷贝的字节也会被拷贝的结果覆盖
memcpy使用void* 类型进行传参 void * 可以接受任意类型的指针
函数内部转化为(char*)类型 这样字节访问与指针运算有效 单位为1个字节 进行操作
//模拟实现memcpy
//memcpy只考虑了对应内存空间没有重叠的情况
void* my_memcpy(void*dest,void*src,size_t num)
{
while(num--)
{
*((char*)dest+num) = *((char*)src+num);
}
return dest;
}
memmove(指定字节数内存拷贝,考虑内存重叠)
void * memmove ( void * destination, const void * source, size_t num );
如何实现可能发生重叠的情况下内存拷贝?
改变拷贝的顺序即可 从前向后拷贝 从后向前拷贝
往右移 从后向前拷贝
往左移 从前向后拷贝
dest在src左边 就是向左移
dest在src右边 就是向右移
这个是指指定范围内存有重叠的情况
如果都不存在重叠 那么什么顺序拷贝都可
if dest>src:
从后向前拷贝
else
从前向后拷贝
dest大于src且存在内存重叠的情况
dest小于src且存在内存重叠的情况
实现:
//模拟实现memmove 需要考虑对应内存区域出现重叠的情况
void* my_memmove(void*dest,void*src,size_t num)
{
assert(dest&&src);
//需要判断dest和src的位置关系
//如果有重叠的区域
//dest在前面 src在后面 那么需要从前往后拷贝
//dest在后面 src在前面 那么需要从后往前拷贝
//为的就是避免src拷贝到后面发现元素已经被之前拷贝移动过去的元素覆盖
//如果没有重叠区域 那么采取哪种拷贝方式都可以
if(dest>src)
{
//从后往前拷贝
while(num--)
{
*((char*)dest+num) = *((char*)src+num);
}
}
else
{
int i=0;
while(i<num)
{
//从前往后拷贝
*((char*)dest+i) = *((char*)src+i);
}
}
return dest;
}
memcmp(指定内存字节比较)
int memcmp ( const void * ptr1,const void * ptr2,size_t num );
就是在内存里面比较每个字节的大小
memset(设定指定字节的内容)
void* memset(void* ptr, int value, size_t num)
ptr前num个字节都设置为value (以字节为单位进行设置)
转载自:https://juejin.cn/post/7401403660246220854