前言
在实际的编程过程中,有时常常避不开的对字符和字符串的处理,而为了方便的操作字符串和字符,C语言标准库提供了一些列库函数,下面我们就会来讲一下这些函数。
1. 字符分类函数
这些字符函数的使用都需要包含一个头文件<ctype.h>,一般来说,对于这些字符函数,他们的返回值有俩种,当参数符合其所描述时,就返回一个大于0的数(即为真),否则返回0(假)。下面我们就来试试如何使用这些函数,这里以isdigit举例,其他字符函数使用起来非常相似。
打印:
练习:将字符串中的小写字母转为大写,其他不变
2. 字符转换函数
C语言中提供了2个字符转换函数
int tolower ( int c) // 将参数传进去的大写转小写
int toupper (int c) // 将参数传进去的小写转大写
通过这俩个字符转换函数,可以对上述代码进行优化。
运行后,打印结果也是正确的。
3. strlen的使用和模拟实现
strlen的使用需要包含头文件<string.h>,前面讲解指针的时候,已经对strlen有了较深入的了解,这里做一点点小小的补充。
这个代码的打印结果是<还是>呢?
结果是>,这是因为size_t 的计算结果类型仍然是size_t类型, 改进方式为if (strlen("def") - strlen("abcdef") > 0)
接下来是strlen的模拟实现
第一种以计数器的方式
第二种采用递归的形式(不能创建临时变量)
第三中采用指针 - 指针的方式
4. strcpy的使用和模拟实现
strcpy即 string copy
strcpy的使用
打印结果是相同的,因为strcpy的返回值与destination相同。
那么这里有一个疑问,复制过后,arr1 = arr2?
这显然是一个错误的结论,这是因为arr1和arr2都是数组名,表示的是数组首个元素的地址,而地址是对应内存空间的编号,显然是不可能相同的。
我们继续调试这个程序。
此时我们会有一个疑问,'\0'有被拷贝过来吗?继续看下一个代码
由此可以看出,'\0'也是有被拷贝过来的。
关于strcpy有几点我们需要注意:
·源字符串必须以'\0'结尾,且‘\0’也会被拷贝。
·目标空间要足够大,能放得下拷贝过来的数据。
·目标空间必须可修改。
目标空间必须可修改例子:
如果是常量字符串,编译器就会报错。
strlen的模拟实现
这里发现'\0'好像没有拷贝过来,调试再看看
调试结果发现确实没有,这是因为while循环到'\0'就停止了,此时我们再稍作修改
此时的'\0'就被拷贝过来了,这就是strcpy的模拟实现。当然,为严谨起见,也可以加上assert断言。
5. strcat的使用和模拟实现
strcat这个函数用于字符串追加。
strcat的参数和返回类型与strcpy一模一样,所以他们的使用方式也几乎一样。不过strcat的使用需要包含头文件<string.h>
使用时需要注意以下几点:
·源字符串必须以'\0'结尾
·目标字符串也要有'\0',否则不知道从哪里追加
·目标空间必须可修改
下面讲strcat的模拟实现
整体思路和strcpy的模拟实现差不多,不过多了一步是要找到追加目标'\0’的位置。
6. strcmp的使用和模拟实现
这个是字符串比较函数,使用时需要包含头文件<string.h>实际上比的是字符对应ASCII码值的大小。
若第一个字符串大于第二个字符串,则返回一个大于0的数,反之则返回一个小于0的数,如相等,则返回0。
代码实现:
模拟实现:
7. strncpy,strncat,strncmp函数的使用
这三个函数和strcpy,strcat,strcmp都很相似,仅仅是都多了一个n,所以他们在使用时也几乎是一样的,只不过多了一点限制。
strncpy:
拷⻉num个字符从源字符串到⽬标空间。如果源字符串的⻓度⼩于num,则拷⻉完源字符串之后,在⽬标的后边追加0,直到num个。
strncat:
将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字
符。如果source指向的字符串的⻓度⼩于num的时候,只会将字符串中到\0之前的内容追加到destination指向的字符串末尾。
strncmp:
⽐较str1和str2的前num个字符,如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀样,就提前结束,⼤的字符对应的ASCII码值⼤于另外⼀个,则其字符串就大于另外一个字符串。如果num个字符都相等,就是相等返回0。
8. strstr的使用和模拟实现
该函数的返回值是返回str2字符串第一次出现在str1字符串的地址。并且字符串的比较不包含'\0',并以'\0'作为结束标志。
代码演示:
模拟实现:
9. strtok函数的使用
分割字符串:根据delim参数中的指定的分隔符,将输入字符串str拆分成多个子字符串。
修改原始字符串:strtok会直接在原始字符串中插入 '\0',替换分隔符的位置,修改原字符串,所以原字符串不能用const修饰。
参数:
str:首次调用时传入待分割的字符串,后续调用传入NULL,表示继续分割同一个字符串。
delim:包含所有可能分隔符的字符串。
返回值:
成功时返回当前子字符串的地址。
没有更多子字符串返回NULL
使用:
首次调用:传入待分割的字符串和分隔符。
后续调用:传入NULL和相同的分隔符,继续分割。
结束条件:返回NULL时。
当然上述代码为了方便说明,有点冗余,这里可以采用循环的方式,使代码更为简洁:
注意事项:
破坏性操作:strtok会直接修改原字符串,所以要事先拷贝一份。
连续分隔符:多个连续的分隔符会被看作单个分隔符,不会返回空字符串。
空指针处理:如果输入的str为NULL,且没有前序调用,行为未定义。
10. strerror函数的使用
strerror的使用需要包含头文件<string.h>
strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会将对应的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
完~