写在前面:
各位小伙伴还在为C语言的学习而苦恼嘛?
还在为没有知识体系而烦心嘛?
别急。因为~~~~
接下来的时间里,我会持续推出C语言的有关知识内容。
都是满满的干货,从零基础开始哦~,循序渐进,直至将C中知识基本全部学完。
欢迎关注我♥,订阅专栏 0基础C语言保姆教学,
就可以持续读到我的文章啦~~~~
本文为第十节——字符串函数(文末附前9章的链接呦)
关于字符串是什么,字符串与数组、指针之间的关系,笔者可能到数据结构再讲,也可能就不讲了,看笔者心情(开玩笑的啦~~主要是因为这一部分很简单,没有讲解的价值和必要)
我们本节主要来探讨string.h里的字符串函数
目录
1、*strlen
2、*strcpy
3、*strcat
4、*strcmp
5、strncpy
6、strncat
7、*strstr
8、strtok
9、*memcpy
10、*memmove
11、memcmp
*表示我们会进行模拟实现
我们借助MSDN来辅助学习
清晰、简单明了。
作用是:获得一个字符串的长度。
函数模型:
size_t strlen( const char *string );
返回类型:size_t,参数类型:const char*
需要注意以下这么几点:
1、字符串已经'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')。
2、参数指向的字符串必须要以'\0'结束。
3、注意函数的返回值为size_t,是无符号的。(unsigned int)
对于strlen的模拟实现,方法有很多。
我们介绍三种:
第一种:
//计数器方式
size_t my_strlen(const char * str)
{
size_t count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
第二种:
//不能创建临时变量计数器
size_t my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1 + my_strlen(str+1);
}
第三种:
//指针-指针的方式size_t my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
其实这三种方法都易于接收。还是比较简单的。
注意以下几点:
- 源字符串必须以'\0'结束。
- 会将源字符串中的'\0'拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
举个例子,比如:
char* strcpy(char* s1, const char*s2);
意思就是把s2拷贝到s1里去。然后返回s1。
以下是一个例子:
模拟实现:
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
使用时注意以下几点:
- 源字符串必须以'\0'结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
模拟实现:
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{ ; }
return ret;
}
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
int my_strcmp(const char* src, const char* dst)
{
int ret = 0;
assert(src != NULL);
assert(dst != NULL);
while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
{
++src;
++dst;
}
if (ret < 0)
ret = -1;
else if (ret > 0)
ret = 1;
return ret;
}
很简单,很好理解。
我们很容易发现,strcpy和strncpy就有一点不一样。那就是strncpy多了一个参数count。也可以就理解为就是n。也就是说n就是其要拷贝的个数。
其他的,和strcpy一样。如下图:
使用时注意:
- 拷贝count个字符从源字符串到目标空间。
- 如果源字符串的长度小于count,则拷贝完源字符串之后,在目标的后边追加0,直到count个。
和strcat也是差不多的。
需要注意的是,当strlen(strSource)+1 还是很简单的。 这个函数它没有那么单纯。 它 的目的主要是用来切割字符串的。 而切割的标准就是依照参数 strDelimit 几点描述: 什么意思具体来说? 我们通过一个例子来 说明 在字符串 “,.- This, a sample string.”里,它会找到下一个 strDelimit中的字符。 第一个是“, 。- ”,第二个是“,”,那么其会标记上一个strDelimit中的后一个字符,即T,然后将","换成"\0",所以,运行完 pch = strtok (str," ,.-"); pch指向的是T,字符串为“,.- This\0 a sample string.”(后面的空格并不会去修改) 然后,进入while循环。strtok的第一个参数是NULL,那么其会从上一个标记处(就是上一次的分隔符号的位置)开始寻找,然后去找strDelimit里的分隔符号。直到找到,将其变为\0。 如果第一个参数为NULL并且找不到分隔符号的时候,就会返回空指针。 一般情况下,src都是0,如果不是0,用的如果 不恰当会引起“麻烦”,我们以后再说。 先来说这个函数的用法: 用法其实很简单: 需要注意的是: 如图,将myname复制到person.name里面 将person结构体复制到person_copy里面 后面第三个元素表示的是复制的字节数。 模拟实现: 注意,如果是结构体类型这种方法应该是不可以的。在这里我们只做简单的模拟实现。到了C++中我们会用类来去实现。 它和memcpy的区别就是, memcpy的src和dest不可以有空间上的重叠。 但是memmove是可以有的。 我们在模拟实现的时候只需要加上一个条件就可以了。 这个很简单,类比于strcmp,主要是在后面有一个参数,它会从第count的位置开始比较。 strerror等略(不属于string.h里,本节不讲) 行了行了,下班了。。。。。 欢迎各位看官关注我@jxwd,订阅专栏,就能持续看到我的文章啦 0基础C语言自学教程——第九节 从底层汇编的角度简单理解函数栈帧的创建和销毁_jxwd的博客-CSDN博客 0基础C语言自学教程——第八节 函数指针数组的各种关系_jxwd的博客-CSDN博客 0基础C语言自学教程——第七节 初始指针_jxwd的博客-CSDN博客 0基础C语言保姆教程——第六节 操作符、表达式和语句_jxwd的博客-CSDN博客 0基础C语言保姆教学——第五节 数组_jxwd的博客-CSDN博客 0基础C语言保姆教程——第4节 函数_jxwd的博客-CSDN博客 0基础C语言自学教程——第三节 分支与循环_jxwd的博客-CSDN博客 0基础C保姆自学 第二节——初步认识C语言的全部知识框架_jxwd的博客-CSDN博客_c语言全部框架 C语言自学保姆教程——第一节--编译准备与第一个C程序_jxwd的博客-CSDN博客7、*strstr
char* strstr(const char* str1, const char* str2)
{
char* cp = (char*)str1;
char* s1, * s2;
if (!*str2)
return((char*)str1);
while (*cp)
{
s1 = cp;
s2 = (char*)str2;
while (*s1 && *s2 && !(*s1 - *s2))
{
s1++;
s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
}
8、strtok
9、*memcpy
10、*memmove
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;
}
}
return(ret);
}
11、memcmp