[C和指针] ch09. 字符串、字符和字节

第九章:字符串、字符和字节

GitHub 链接:ch09. 字符串、字符和字节

本章比较基础,介绍了字符串相关函数,但实现方式却只字未提。毕竟这是一个入门级的书,可以理解。面试过程中,不论是 strlen() 函数还是 memcpy() 函数等等都是面试手写的大热点,这点需要额外注意。

本章总结及注意点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


部分课后习题解答

9.13 问题

  1. 我个人感觉,是缺点。把各种事物混到一起或许效率能够大大提高,但出错几率也随之上升。就现代编程语言看来,语法的孤立性是很重要的。即一件事情就对应一种解决方法就行了,搞太多方法容易混淆、出错。并且很显然,开发一个完整的字符串类型,并不影响传统的字符数组、字符串常量的使用。参考答案:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fv18M9jS-1609067878778)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20201224105942.png)]

  2. 无符号更合适。从定义出发,长度怎么可能是负值呢?且无符号数表示正数范围比有符号大。但是无符号数的算术表达式可能会产生意外结果,而长度的优势在这体现的不明显。仁者见仁智者见智。

  3. 后续的链式操作就能很方便的完成,不需要再次查找字符串结尾标志。

  4. memcpy(y, x, 50);

  5. 不能。当且仅当数组中的最后一个字符已经为 NUL 才为有效字符串。strncpy() 不会为最后添加 NUL

  6. 可移植性更好。

  7. toupper() 函数会进行合法性判断。islower() 是不必要的。

  8. 如果 buffer 中包含一个有效字符串,那么两个都能找到字符串末尾的 NUL,仅是返回值类型不同,前者为有符号类型,而后者为无符号类型。如果不包含一个有效字符串,那么 memchr() 函数将返回一个 NULL 指针,用其来减去 buffer 是没有意义的。而 strlen 则一直向后寻找,最终可能程序崩溃,结果也没有意义。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QceqrfHn-1609067878780)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20201224111808.png)]

9.14 编程练习

  1. 主要使用字符分类函数配合计算器即可。直接复制的答案代码,见 demo01.c

  2. 实现了个寂寞?如果在长度内找到了 '\0',那么直接 strlen() 即可,如果没找到 '\0',那么就返回该长度就行了。那么直接调用 memchr() 函数按字节查找 '\0' 是否出现不就行了?不过按循环来做,确实比较简洁!见 demo02.c

  3. 其实就是 strncpy() 的应用,函数需要传递数组大小,并在最后对字符数组最后一位赋值为 NUL

  4. 也需要传递数组的长度,并计算 dst 的长度,并且在 dst 中不要使用 strlen() 函数来确定其长度,因为不知道里面是否包含有效字符。故可以使用 demo02.c 中的 my_strlen() 函数,在已知数组大小的时候能返回正确的字符串长度。最后使用 strncat() 函数将字符串拼接过来,最终保证数组的最后一位元素是 NUL。在此按理说 strncat() 函数应该是要保证其末尾为 NUL 的。难道是在恰好拼接的情况下就不保证了吗?

  5. 需要先计算 dest 的长度,得到 dest_len 的实际可用长度,并且给 NUL 留出一个空,最后直接调用 strncat() 即可。

  6. 两种实现方式,strlen() 方法和 register 方法均可,其中后者不调用库函数,register 声明使得效率更高。见 demo06.c

  7. 用一个指针记录上次找到的位置即可。见 demo07.c

  8. strchr() 函数的应用,关键在于不能只写 which --,因为如果 which < 0 的话,怎么减也没有用,所以一开始要进行 --which 大于等于 0 的特判。让 which 前置 --,当 which 至少为 1 时,才有意义。见 demo08.c

  9. strpbrk() 函数的应用。其找到第一次在 str 中出现的且在 chars 字符集合中的位置,并返回该位置的字符指针。循环处理即可,令 str 每次找到后往后移一位继续找就行了。见 demo09.c

  10. <ctype.h> 头文件的应用。使用 isalpha()tolower() 函数。能很方便的处理大小写的情况。

  11. strtok() 函数的应用。用其来找到以一个或多个空格结束的字符,strtok() 会将其末尾置为 NUL,循环来做,该函数会保存正在处理的字符串的局部信息,第一个参数传为 NULL 继续处理即可。见 demo11.c

  12. 将整个字符串去重,全部变大写 / 小写,然后由 'A'~'Z' 进行遍历,查找将没有在字符串中出现过的字母插到该字符串后面,注意每次插入后面的位置有 '\0'。见 demo12.c

  13. 映射关系:*data=key[*data - 'a'];,注意检查大小写字母并保留。见 demo13.c

  14. 遍历得到 *data,运用 strchr() 函数找到在 key 中的出现位置,直接对 26 个字母进行下标映射即可。注意大小写字母的映射关系!利用 <ctype.h> 中的字符分类函数进行判断、转换。见 demo14.c

  15. 挺不错的一道模拟题。从前往后依次处理,首先是 '$' 符号,再求出字符串总长度,如果长度大于等于 3,则说明有整数部分,共有 len-2 项个整数,处理三个整数,需要添加一个 ','。整数处理完毕后在后面添加一个 '.'小数部分处理简直绝了,如果 len 小于 2,则说明没有整数部分,小数部分第一项添加 0,否则添加 *src 的倒数第二项。如果 len 小于 1,则说明没有整合素部分,小数部分第二项也为 0,否则添加 *src 的最后一位。最后一定要记得将 *dst = 0,令其成为一个有效字符串。见 demo15.c

  16. 今天处理的是在是太多了。本题考阅读理解,跳过了…

  17. 同上!

随笔

字符串的处理在编程中都是很常见且重要的,本章也比较基础,比较容易理解,还是得多写、多用,才能踩坑,才能掌握。

疑问

  1. strtok() 函数,用来查找标记。这个函数我在学习过程中没遇见过,起初看书的时候感觉很难理解。找标记是很简单的事情,拿集合中的字符进行匹配即可,但是,它找到标记之后会将该标记位置置成 NUL?这还直接修改原字符串了…并且它的第一个参数还能是 NULL?结果最后讲的是它能保存它所处理的函数的局部状态信息,所以不能同时用它来解析两个字符串。那么是不是可以推断得到,其不能出现在同一个代码块中,不能嵌套使用,该 strtok() 函数的作用域中,不能再给其另一个字符串了?我猜应该是这个样子的。

  2. 手撕 memcpy() 函数是非常重要的,秋招面试的时候,都不知道被考了多少回了…注意 memmove() 函数处理内存重叠时的方式。

  3. strncat() 函数不会检查 dst 剩余空间是否足够,就直接从 src 中向后拼接 len 个再加上一个 NUL 字符到 dst 后面。故很有可能会造成数组越界,将后面的位置空间给侵占成拼接字符串了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

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

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

打赏作者

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

抵扣说明:

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

余额充值