一.字符分类函数
C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。这些函数的使用都需要包含一个头文件是ctype.h。
如图:
这些函数的使用方法非常类似,我们就讲解一个函数的事情,其他的非常类似:
1 int islower ( int c);
islower 是能够判断参数部分的c是否是小写字母的。通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。
来看练习:
练习:写一个代码,将字符串中的小写字母转大写,其他字符不变。
二.字符转换函数
C语言提供了2个字符转换函数:
1 int tolower ( int c ); //将参数传进去的大写字母转小写
2 int toupper ( int c ); //将参数传进去的小写字母转大写
来看相关例子:
返回值是int,**返回的是转化成对应字符的ASCII值,**不要忘了包含头文件ctype.h。
关于上面我们举的例子,将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用toupper函数。
三.strlen的使用和模拟实现
1 size_t strlen ( const char * str );
strlen函数的相关要求:
字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’10’)。
参数指向的字符串必须要以’\0’结束。
注意函数的返回值为size_t,是无符号的(易错)
strlen的使用需要包含头文件
该函数使用举例:
strlen函数工作原理:从给定的起始位置开始,向后统计\0之前的字符个数。
我们来看一个小知识点
为什么会打印出这样的结果?
因为strlen函数返回值是size_t类型的,两个size_t类型的值相减得到的值-3也是size_t类型的,size_t类型是无符号的整型,它的补码最高位1不会被当成符号位,所以-3就变成了特别大的正数值。
所以我们如果这样写代码就是坑了自己,我们可以直接相比来得到我们想要的。
或者强制类型转换一下
strlen函数的模拟实现
关于strlen函数的模拟实现有三种方式:
1.计数器
2.指针 - 指针
3.递归的方式
我们来写代码实现这三种方法
四.strcpy的使用和模拟实现
1 char* strcpy(char * destination, const char * source );
strcpy函数的相关要求:
Copies the C string pointed by source into the array pointed by destination, including the terminating null
character (and stopping at that point).
源字符串必须以’\0’结束。
会将源字符串中的’\0’拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可修改。
举例:
该函数也会把要拷贝的字符串中的\0拷贝到目标函数中,我们来调试看:
我们要知道使用该函数拷贝字符串,源头字符串中必须要有\0,否则没办法拷贝。
拷贝的时候没有\0就不知道什么时候停下来,造成越界访问。所以该函数用于拷贝字符串,字符串中有\0结束标志。
还有就是我们要拷贝到的目标空间要足够大
拷贝到的目标空间不够大,造成越界访问,程序崩掉了。
目标空间必须可修改
我们这样写代码程序也会崩掉,p指向的空间里面存放的是常量字符串,它是不能被修改的。
我们来看strcpy的模拟实现:
优化一下
我们将表达式放到while循环判断的地方的时候,既可以赋值,赋值产生的结果又可以判断,这样的话\0也可以被拷贝过去了,又作为赋值结果结束条件。
strcpy函数的返回值类型是char*,strcpy返回的是目标空间的起始地址。我们再来改改模拟实现的strcpy函数。
五.strcat的使用和模拟实现
strcat函数的相关要求:
Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string
formed by the concatenation of both in destination.
源字符串必须以’\0’结束。
目标字符串中也得有,否则没办法知道追加从哪里开始。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
简单来说:strcat函数是实现字符串的链接或追加。
举例:
通过上面的例子,可知strcat函数追加方式是:找到目标空间中的第一个\0,然后从这个\0的位置开始追加源头字符串,源头字符串的内容,包括\0都会追加到目标空间。
strcat函数的模拟实现
还有一个问题要注意一下:当我们用该函数自己给自己追加的时候,会造成死循环的问题。
六.strcmp的使用和模拟实现
strcmp函数的相关要求:
This function starts comparing the first character of each string. If they are equal to each other, it
continues with the following pairs until the characters differ or until a terminating null-character is reached.
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
那么如何判断两个字符串? 通过比较两个字符串中对应位置上字符ASCII码值的大小。
strcmp函数是用来比较两个字符串的大小,对应位置上的字符进行比较,根据ASCII值的大小。
例子:
strcmp函数的模拟实现
我们再来看另一种写法:
七.strncpy 函数的使用
1 char * strncpy (char* destination, const char * source, size_t num);
strncpy函数的相关要求:
Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
通过比较我们知道该函数比strcpy函数多了个参数,该参数指定了你最多要拷贝多少个字符。
我们用例子来理解,比如指定想要拷贝字符串前五个字符。
但是如果我们源头字符串只有两个,却指定拷贝5个会怎么样呢?
从上面例子可知:如果源字符串不够,该拷贝的拷贝过来,其他的用\0补齐,也就是补零。
八.strncat 函数的使用
1 char * strncat ( char * destination, const char * source, size_t num );
strncat函数的相关要求:
Appends the first num characters of source to destination, plus a terminating null-character. (10字符串的前num个字符追加到destination指向的字符串末尾,再追加一个\0字符)。
If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.(如果source 指向的字符串的长度小于num的时候,只会将字符串中到\的内容追加到destination指向的字符串末尾)。
我们通过比较也发现strncat函数和strcat函数参数也是差了一个。这个参数是指定追加源头字符串多少个字符。
另一个例子:
从上面例子我们可知把两个x追加来之后又加上了一个\0。我们再来看如果指定的个数大于源头字符串字符个数,该怎么样追加呢?
我们看到它并没有像strncpy函数一样凑齐5个,不够补\0。
九.strncmp函数的使用
1 int strncmp ( const char * str1,const char * str2, size_t num );
比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不一样,就提前结束,大的字符所在的字符串大于另外一个。如果num个字符都相等,就是相等返回0。
该strncmp函数比strcmp函数多出来的参数是指定最多比较的字符个数。
举例:
十.strstr的使用和模拟实现
1 char * strstr ( const char * str1, const char * str2);
strstr函数的相关要求:
Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. (#ZO?符串str2在字符串str1中第一次出现的位置)。
The matching process does not include the terminating null-characters, but it stops there. (不包含\0字符,以\作为结束标志)。
strstr函数作用是:在一个字符串中,找一个子字符串,找第一次出现的位置。从上面我们来看该函数的参数部分,它的意思是:在str1指向的字符串中找str2指向的字符串第一次出现的位置。
该strstr函数如果找到了,就返回第一次出现的地址,如果找不到,就返回NULL。
我们来举例使用一下该函数:
strstr函数的模拟实现
const char* my_strstr(const char* str1, const char* str2)
{const char* s1 = str1;const char* s2 = str2;const char* cur = str1; // cur指针记可能的开始匹配的位置if (*str2 == '\0')//当str2是空字符串时,直接返回str1return str1;while (*cur){//完成一次匹配s1 = cur;s2 = str2;while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')return cur;cur++;}return NULL;}int main()
{char arr1[] = "abcdefabcdef";char arr2[] = "def";const char* ret = my_strstr(arr1, arr2);if (ret == NULL)printf("找不到\n");elseprintf("找到了:%s\n", ret);return 0;
}
当str2是\0时,这是特殊的情况,以后写代码的时候,根据自己需求来决定该返回什么。
我们再来优化一下
十一.strtok函数的使用
1 char * strtok ( char * str, const char * sep);
sep参数指向一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回NULL指针。
我们来看该函数的使用场景
把分隔符(如上面的:@ . )的分开的字符串提取出来。
来看例子:
但是我们一般用该函数的时候不会把源头字符串的数组名传过去,因为该数组会被改变破坏掉,我们会创建另一个数组拷贝一份来使用。
当我们第二次调用strtok函数第一个参数为NULL,它会从上一次保存的位置向后找,如上面的例子,第二次调用会返回y的地址,把 . 改成\0。
我们一般不用这样形式写代码,请看下面代码:
十二.strerror函数的使用
1 char* strerror ( int errnum);
strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语言标准库的实现中都规定了一些错误码,一般是放在 errno.h这个头文件中说明的,C语言程序启动的时候就会使用一个全局的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每一个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
上面我们只是把错误码对应的错误信息打印出来看一下,我们再来看它的使用场景:
关于fopen函数已经讲解过了,就不再说了。产生的错误码放到了errno变量中了,不要忘记包含它的头文件,如果有多个错误码,再次发生错误产生的错误码会把上一次的错误码覆盖掉了,所以要及时的检测。
perror的使用
打印的时候,先打印你传的字符串,然后它会在字符串后面加上冒号和一个空格,再打印错误信息。
这篇有点多,关于C语言的内容还剩一篇就结束了,加油!!!