要注意的是,要使用下边所讲的函数要包含头文件<string.h>
文章目录
- strlen
- strcpy
- strncpy
- strcat
- strncat
- strcmp
- strncmp
- strstr
- strtok
- strerror
- 字符串大小写转换
- strupr
- strlwr
- memcpy
- memmove
- memcmp
strlen
求字符串的长度
- 函数参数:字符串指针
- 函数功能:传入字符串指针,字符串是以\0为结束标志,返回的类型size_t其实就是unsigned int,函数返回的是字符串中**‘\0’前边字符的个数**,传入字符串指针用const修饰*str,防止函数意外修改传入的字符串。
- 返回值类型:无符号整形,即结束标志前字符数量
函数功能演示
查找到’\0’就结束演示
模拟实现
根据函数的功能,返回值来编写
unsigned int _strlen(const char *arr)
{
int count = 0;//计数
while (*arr)
{
count++;
arr++;//字符指针向后走
}
}
strcpy
- 函数参数:一个是目的地,另一个是源头。
- 函数功能:将源头字符串拷贝到目标空间。
- 返回值:返回拷贝完成后第一个字符串的地址。
注意:
1,源字符串必须以’\0’结尾。不能这样搞
char arr[4]={'a','b','c','d'}
如果第二个参数是这样一个没有结束标志’\0’的字符串,那么函数在实现时就会一直往后找,就会越界访问产生错误。
2,函数会将源字符串的结束标志’\0’也会拷贝过去。
可以调试观察
在打印时,遇到’\0’就结束,不要误以为该函数清空了原来的内容。
模拟实现(记得包含头文件assert.h)
char* _strcpy(char* dest, const char* src)
{
char* ret = dest;//保存dest的首地址
assert(dest != NULL);
assert(src != NULL);
while (*src!='\0')//\0之前全部OK
{
*dest = *src;
dest++;
src++;
}
*dest = *src;//\0也搞过来
return ret;
}
strncpy
和strcpy不同的是,多了一个参数。
拷贝num个字节过去,如果源字符串已经没有元素了,就将dst后边的字节变成零。
函数功能展示:
strcat
- 参数:这个函数的参数和strcpy一模一样。
- 功能:strcpy在目标字符串的开头拷贝源字符串,但strcat是在目标字符串的末尾,即结束标志’\0’位置开始将源字符串拷贝到目标字符串。
- 返回值:和strcpy一样,返回目标字符串的指针。
功能呈现:
函数模拟实现:
char* _strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}//找到目标字符串的末尾
while (*dest++ = *src++)
{
;
}
return ret;
}
strncat
和前边strcpy和strncpy的区别一样。
函数功能演示:
strcmp
字符串比较函数
- 参数:两个,他们两个之间的比较
- 功能:以两个字符串的每个字符以ASCII码值逐个比较
- 第一个字符串如果大于第二个字符串,就返回大于零的数字。
- 第一个字符串等于第二个字符串,就返回0。
- 第一个字符串小于第二个字符串,就返回小于零的数字。
- 返回值:上边已经说明。
函数功能呈现
f的ASCII在‘\0’之前。大于返回1(大于0的数)
如果等于返回零。
小于返回-1(小于0的数)
函数模拟实现
int _strcmp(const char* src, const char* dest)
{
int ret = 0;
assert(src != NULL);
assert(dest != NULL);
while (!(ret = *(unsigned char*)src - *(unsigned char*)dest) && *dest)
{
++src;
++dest;
}
if (ret < 0)
{
return -1;
}
else if (ret > 0)
{
return 1;
}
else
{
return 0;
}
}
strncmp
不再是从头比较到尾,而是比较num个字符。
函数功能演示:
strstr
- 参数:传入两个字符指针。
- 功能:在str1中找到str2第一次出现的位置。
- 返回值:返回找到该位置的指针。如果没有找到,就返回NULL。
函数功能呈现
函数模拟实现
char* _strstr(const char* str1, const char* str2)
{
char* cp = str1;
char* s1, * s2;
if (!*str2)
{
return str1;//如果str2为空,返回str1
}
while (*cp)
{
s1 = cp;
s2 = str2;//传入参数不可以修改
while (*s1 && *s2 && !(*s1 - *s2))
{
s1++;
s2++;
}
if (!*s2)//如果跳出循环且s2已经是'\0’了。
{
return cp;
}
cp++;
}
return NULL;
}
strtok
- 参数:第一个参数为目标字符串,第二个参数为分隔符集合
- 函数功能:第一个参数即目标字符串是包含0个或者多个由分隔符分割而成的字符串。
strtok会找到str中的一个标记,并将这个标记更改为\0,返回一个指向这个标记的指针(strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符创一般都是临时拷贝的内容且允许修改)。
strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存他在字符串中的位置。
如果函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。 - 返回值:如果目标字符串中不存在标记的分割字符,就返回NULL指针,如果找到,将该标记设置为结束标志\0。
函数功能展示
调试动图展示,会让你更加清晰了解函数的功能
上边是作者滴QQ,欢迎大家一起学习交流,嘿嘿。
strerror
要使用这个函数,需要包含头文件<errno.h>
- 函数参数:errnum–错误号,通常是errno
- 函数功能:返回一个指向错误字符串的指针,该错误字符串描述了错误errnum。
- 函数解释:这个函数会从内部搜索错误号,返回一个指向该错误信息字符串的指针,即错误消息字符在头文件中,程序运行时若有错误,strerror会捕获错误类型并返回一个指针,这个指针指向错误消息字符。
函数功能演示:
由于当前文件内并没有heihei这个文件,以只读的方式打开搜索该文件是找不到的,所以返回的错误信息就是没有相关文件或者相关文件已经被销毁。
这里文件相关操作有遗忘的小伙伴可以移步文件超消息讲解来回顾回顾。
字符串大小写转换
strupr
- 语法格式如下:
strupr(字符串);(要注意,新的编译器规定使用该函数式要加上_) - 函数功能:将字符串中的小写字符转换成大写字母,其他字母不变。
函数功能实现:
strlwr
格式相同,功能相反
演示如下:
memcpy
- 函数参数:目标字符串,源字符串,数量(unsigned int),void类型可以适配多种类型。
- 函数功能:函数功能和strncpy很相似,只是memcpy可以操作的类型更加丰富,从源字符串首元素位置开始,向后拷贝num个字节的数据到目标字符串的位置,这个函数遇到’\0’不会停下来,且如果源字符串和目标字符串有重叠时,拷贝结果是未定义的。
例如,需要拷贝四个字节字符。而源字符串在目标字符串前3个子节的位置。
本意是将1,2,3,4全部拷贝过去,然而在第一次拷贝时,元素1已经把元素4覆盖。
这与背后函数的实现有关,没有做重叠时的处理。
函数模拟实现如下:
void* _memcpy(void* dst, const void* src, size_t count)
{
void* ret = dst;//记录目标数组的地址
assert(dst);
assert(src);
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
return ret;
}
memmove
函数memcpy存在重叠问题的话,memmove就是用来解决这个问题的,如果源空间和目标空间存在重叠的话,就得使用memmove函数处理。
函数格式和作用和momcpy一模一样。
函数功能呈现:
模拟实现:
void* _memmove(void* dst, const void* src, size_t count)
{
void* ret = dst;
if (dst <= src || (char*)dst >= ((char*)src + count))
{
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
}
else//从后往前拷贝
{
dst = (char*)dst + count - 1;
src = (char*)src + count - 1;
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;
src = (char*)src - 1;
}
}
}
memcmp
- 两个数组(可以是字符数组,也可以是其他类型)相比,num个字节,void*可以适配多种类型。
- 函数功能和strcmp一样,可以适配的类型更多了而已。
函数功能呈现:
整型四个字节,两个数组前两个元素相等,故返回值0。
更改为12个字节,返回值就变为-1了。