!!!教你如何搞懂字符串函数(详细,后期会讲函数栈帧)

  • 求字符串长度

  • strlen

  • 长度不受限制的字符串函数

  • strcpy

  • strcat 

  • trcmp

  • 长度受限制的字符串函数介绍

  • strncpy

  • strncat

  • strncmp

  • 字符串查找

  • strstr

  • strtok

  • 错误信息报告

  • strerror

  • 不幸的gets函数和升级版的fgets函数

  • puts函数和fputs函数

  • 缓冲区

  • 结束键盘,文件,流输入

首先我们先来学习一下strlen函数

  • strlen

  • 1.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。

  • 2.参数指向的字符串必须要以 '\0' 结束。所以如果我们没有遇到\0,strlen会一直检索直到遇到\0 

  • 上述我们看到计算的值为60,是因为我们strlen函数在计算arr数组时没有遇到\0,所以产生了随机值60,那么我们看下内存是否存放了\0

  • 3.注意函数的返回值为size_t,是无符号的( 易错

  • 我们看看上述答案是多少呢,是第一个选择还是第二个选择呢?

      答案是第二个选项

  • 4.学会strlen函数的模拟实现(下图是模拟实现思路)

strcpy

 

1.源字符串必须以 '\0' 结束。

 想一想为什么出现这种现象(非法访问?)

 答案是因为这个函数的实现就必须是用'\0'结束,这里arr2的空间里不  知  道'\0'在哪,所以在拷贝的时候会出现bug,具体我们看下面的模拟 实现内容就明白了。

2.会将源字符串中的 '\0' 拷贝到目标空间。

   我们看看是否strcpy函数会把'\0'拷贝到目标空间???

   

 

 

 

3.目标空间必须足够大,以确保能存放源字符串。

因为超过的话会越界导致栈溢出

4. 目标空间必须可变。

为什么会出现非法访问? 

因为"hello"是个常量字符串,我们不能对他赋值和修改

5.学会模拟实现

strcat

 1.源字符串必须以 '\0' 结束。(类似,就不描述了)

 2.目标空间必须有足够的大,能容纳下源字符串的内容。(类似,就不描述了)

 3.目标空间必须可修改。(类似,就不描述了)

 4.字符串自己给自己追加,如何?

    我们试一下

     

 但是为什么vs2019的库里可以,因为每个编译器封装的函数不一样,底层实现不一样

 5.学会模拟实现

 strcmp

切记,字符串比较的话不是比较长度而是比较两两字符的大小,有一个大或小于或者等于就返回

学会模拟实现

strncpy

 1.拷贝num个字符从源字符串到目标空间。

 2. 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个

     想一想strncpy与strncp有什么优缺点?

     strncpy相较于strcpy,在拷贝字符的时候更加精确,且不容易出错

     但是他在一些特定场合时的执行效率比较低,因为封装的函数的代码更加复杂

     导致效率会降低;

strncat

 思考一下strncat与strcat有什么区别

1.

 2.strncat相较于strcat追加的字符可以控制,也就说更加精确,但是执 行 效率相较于strcat低了。

3.学会模拟实现

 strncmp

 1.思考一下strncmp与strcmp有什么区别

strncmp相较于strcmp,在拷贝字符的时候更加精确,且不容易出错但是他在一些特定场合时的执行效率比较低,因为封装的函数的代码更加复杂

 2.学会模拟实现

 3.利用字符串比较可以查找对应字符

 strstr

 1.字符串查找

 2.学会模拟实现

 strtok

char * strtok ( char * str, const char * sep );

sep参数是个字符串,定义了用作分隔符的字符集合

第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。

strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。

strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。

strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。

如果字符串中不存在更多的标记,则返回 NULL 指针。

那么我们来实现一下看看。

 strtok函数的第一个参数不为 NULL ,函数将找到arr中第一个标记,strtok函数将保存它在字符串 中的位置。

 为什么这里要置为空指针,因为置为空指针后,strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。

 但是仔细想想我们这样切割是不是太麻烦了 

 

 

strerror

返回错误码,所对应的错误信息

 那么我们的错误码有什么用呢,主要是为了检查错误

那怎么用呢?

我们先介绍他的错误信息

 举一些例子

gets

在读取字符串时,scanf()和转换说明%s只能读取一个单词。可是在程序中经常要读取一整行输入,而不仅仅是一个单词。许多年前,gets()函数就用于处理这种情况。gets()函数简单易用,它读取整行输入,直至遇到换行符,然后丢弃换行符,存储其余字符,并在这些字符的末尾添加一个空字符使其成为一个C字符串。它经常和puts()函数配对使用,该函数用于显示字符串,并在末尾添加换行符。

但是gets()函数有缺陷

 

  缓冲区溢出

 这是为什么呢?

 因为,gets()函数只知道数组的开始处,并不知道数组中有多少个元素。

 如果溢出过多,可能会改写其他内存的数据,导致bug

所以有了下面的fgets()函数

fgets

fgets函数相较于gets可以读取到\n,不会丢弃

并且可以控制读取字符个数,更加精确,虽然效率会低一点,但是比较安全

 

 fgets()函数的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets()将读入n-1个字符,或者读到遇到的第一个换行符为止。

puts

puts是个输出函数,但是这个与printf有什么不同呢?

puts在输出的时候会在字符串的末尾自动加'\n'——换行符 

printfprintf函数从左往右读取,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的.所我们看见的结果是,从右边开始处理的.

 puts函数也会读取,但是他会在末尾加一个换行符

 

 不过printf相较于puts虽然效率低,但是他的格式变换多,而puts比较单一,一般用printf函数更好

fputs

fputs函数相较于puts不会自动在输出的末尾加\n-换行符

缓冲区

为什么要有缓冲区?首先,把若干字符作为一个块进行传输比逐个发送这些字符节约时间。其次,如果用户打错字符,可以直接通过键盘修正错误。当最后按下Enter键时,传输的是正确的输入。

 虽然缓冲输入好处很多,但是某些交互式程序也需要无缓冲输入。例如,在游戏中,你希望按下一个键就执行相应的指令。因此,缓冲输入和无缓冲输入都有用武之地。

缓冲分为两类:完全缓冲I/O和行缓冲I/O。完全缓冲输入指的是当缓冲区被填满时才刷新缓冲区(内容被发送至目的地),通常出现在文件输入中。缓冲区的大小取决于系统,常见的大小是512字节和4096字节。行缓冲I/O指的是在出现换行符时刷新缓冲区。键盘输入通常是行缓冲输入,所以在按下Enter键后才刷新缓冲区。

  • 24
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乖的小肥羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值