前言
在c语言的编程过程中,我们经常要处理字符和字符串,为了方便字符和字符串操作,c语言中提供了一系列库函数。
一.字符函数
C语言有一些函数是专门做字符分类的,也就是一个字符是属于什么类型的字符,使用该类函数要包含头文件ctype.h。
下面我们用一段代码,将字符串中的小写字母转大写来带大家熟悉一下函数的使用
#include<stdio.h>
#include<ctype.h>
int main()
{
int i = 0;
char str[]="Test String.\n";
while(str[i] != '\0')
{
if(islower(str[i])) //判断是否为小写字母
{
str[i] -= 32;
}
i++;
}
printf("%s\n",str);
return 0;
}
除了以上的函数c语言还提供了2个字符转函数:
int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写
有了这两个函数我们就可以改良上面的小案例
#include<stdio.h>
#include<ctype.h>
int main()
{
int i = 0;
char str[]="Test String.\n";
while(str[i] != '\0')
{
if(islower(str[i])) //判断是否为小写字母
{
str[i] = toupper(str[i]);
}
i++;
}
printf("%s\n",str);
}
由于上面的函数很简单,小编就不在这里给大家一一叙述了,感兴趣的兴趣可以自己试一下。
二.字符串函数
1.strlen的使用和模拟实现
《1》strlen的使用
strlen的功能:将首地址传入,统计从首地址到'\0'的字符个数。
strlen的语法形式: size_t strlen (const char * str);
strlen使用的注意事项:
• 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包含 '\0' )。
• 参数指向的字符串必须要以 '\0' 结束。
• 注意函数的返回值为size_t,是⽆符号的( 易错 )
• strlen的使⽤需要包含头⽂件
这里我们着重说一下函数的返回值是size_t(无符号整形)这种情况:
#include<stdio.h>
#include<string.h>
int main()
{
if(strlen("abc") - strlen("abcdef") > 0)
{
printf(">");
}
else
{
printf("<=");
}
return 0;
}
从这段代码我们可以看出strlen("abc")的值是3,strlen("abcdef")的值是6, 3-6得到的是-3,而-3应该小于0,应输出<=,而结果输出>这究竟是为什么呢?话不多说我们直接看图。
相信看了上面的图大家对size_t类型有了了解 ,那么上方代码我们有什么解决方法呢?
我们只需要在strlen前加上int类型的强制类型转换即可解决问题,下面上代码:
#include<stdio.h>
#include<string.h>
int main()
{
if((int)strlen("abc") - (int)strlen("abcdef") > 0)
{
printf(">");
}
else
{
printf("<=");
}
return 0;
}
《2》strlen的模拟实现
对于strlen的模拟实现我们介绍三种方法
(1)计数器法
size_t my_strlen(const char *arr)
{
size_t count = 0;
int i = 0;
while(arr[i])
{
count++;
i++;
}
return count;
}
该代码的实现思想是在函数中添加一个计数器,遍历整个字符串,若字符串不为'\0',则count++,若为'\0'则跳出循环返回count的值。
(2)指针-指针
size_t my_strlen(const char *arr)
{
size_t count = 0;
const char *arr2 = arr;
while(*arr2)
{
arr2++;
}
return arr2 - arr;
}
该函数的思想是在函数中在创建一个字符指针类型的变量arr2,把arr1的地址给arr2,然后arr2依次遍历字符串中的数据直到遇到'\0',跳出循环此时arr2保存的是'\0'的地址,arr2-arr表示的时两地址之间的元素个数(该字符串'\0'之前的元素个数),然后返回arr2-arr的值。
(3)递归方法实现
size_t my_strlen(const char *arr)
{
if(*arr != 0)
{
return 1 + my_strlen(arr+1);
}
else
{
return 0;
}
}
由上图可知该方法是利用递归函数把问题,分成若干个子问题解决。
2.strcpy函数的使用和模拟实现
《1》strcpy的使用
strcpy函数的功能:是将源字符串拷贝到目标字符串中。
strcpy函数的语法形式:char* strcpy(char * destination, const char * source );
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] ={0};
char arr2[]="hello word";
char *t = NULL;
t = strcpy(arr1,arr2);
printf("%s\n",arr1);
printf("%s\n",t);
return 0;
}
strcpy注意事项:
• strcpy返回类型为char*
• 源字符串必须以 '\0' 结束。
• 会将源字符串中的 '\0' 拷⻉到⽬标空间。
• ⽬标空间必须⾜够⼤,以确保能存放源字符串。
• ⽬标空间必须可修改。
《2》strcpy的模拟实现
char *my_strcpy(char *arr1 , const char *arr2)
{
assert(arr1 && arr2);
char *cur = arr1;
while(*arr1++ = *arr2++);
;
return cur;
}
该代码的实现思想非常简单,创建一个指针变量cur存arr1存放第一个元素首地址的位置,分别遍历arr1和arr2,同时将arr2的值赋给arr1,当arr2的值为'\0'时跳出循环,并返回cur(记录的时arr1第一个元素首地址)。
3.strcat函数的使用和模拟实现
《1》strcat的使用
strcat函数的功能:是将源字符串中的数据追加到目标字符串后面,会将源字符串的'\0'追加到目标字符串当中。
strcat函数的语法形式:char * strcat(char *dest, const char*src)
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20]="abcd";
char arr2[]="efgh";
char *cur = NULL;
cur = strcat(arr1,arr2);
printf("%s\n",arr1);
printf("%s\n",cur);
return 0;
}
strcat的注意事项:
• 源字符串必须以 '\0' 结束。
• ⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。
• ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。
• ⽬标空间必须可修改。
《2》strcat的模拟实现
char *my_strcat(char *arr1 , const char *arr2)
{
char * cur = arr1;
while(*arr1)
{
arr1++;
}
while(*arr1++ = *arr2++)
{
;
}
return cur;
}
首先,创建一个字符指针变量cur,用来存储arr1首元素的首地址,然后找到arr1的末尾节点,从arr1末尾节点开始追加arr2的元素直到追加结束。
4.strcmp函数的使用和模拟实现
《1》strcmp的使用
strcmp函数的功能:是比较两字符串的大小从首个字符串逐一往后比较,直到有一方先结束,
若
字符串1 > 字符串2 返回1
字符串1 < 字符串2 返回-1
字符串1 == 字符串2 返回0
strcmp函数的语法形式:int strcmp (const char * str1, const char * str2)
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "abcp";
char arr3[] = "abcdeeg";
char arr4[] = "abcdefg";
printf("arr1和arr2比:");
printf("%d\n",strcmp(arr1,arr2));
printf("arr1和arr3比:");
printf("%d\n",strcmp(arr1,arr3));
printf("arr1和arr4比:");
printf("%d\n",strcmp(arr1,arr4));
return 0;
}
strcmp是比较两字符ASCLL码值大小
《2》strcmp函数的模拟实现
int my_strcmp(const char *arr1 , const char *arr2)
{
assert(arr1 && arr2);
while(*arr1 == *arr2)
{
if(*arr1 == '\0')
return 0;
arr1++;
arr2++;
}
return *arr1 - *arr2;
}
首先,由arr1和arr2的值比较如果相等不断往后遍历,若同时为'\0',则证明两个字符串相等,否则继续遍历知道找到不相等的跳出循环,然后,返回*arr1-*arr2,若*arr1比*arr2大则返回大于0的数字,否则返回小于0的数字。
5.strstr函数的使用和模拟实现
《1》strstr函数的使用
函数返回字符串str2在字符串str1中第⼀次出现的位置。
字符 串的⽐较匹配不包含 \0 字符,以 \0 作为结束标志。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abbcdbcdef";
char arr2[] = "db";
char *cur = NULL;
cur = strstr(arr1,arr2);
printf("%s\n",cur);
return 0;
}
《2》strstr的模拟实现
char *my_strstr(const char *arr1,const char *arr2)
{
const char *cur = arr1;//记录每次字符比较的最初位置
const char *s1 = NULL ,*s2 = NULL;//arr1和arr2中的移动变量
if(*arr2 == '\0')
return ((char*)arr1);
while(*cur)
{
s1 = cur;
s2 = arr2;
while(*s1 == *s2)
{
s1++;
s2++;
}
if(*s2 == '\0')
return ((char *)cur);
cur++;
}
return NULL;
}
首先创建一个指针变量cur存储arr1的地址,然后创建s1,s2记录arr1和arr2中的子字符串位置进行比较,创建完成后,判断arr2是否为空字符串,若为空字符串直接返回arr1字符串首元素的首地址,如果arr2不为空字符串,进入while循环每次将s1和s2的值分别初始化成cur和arr2用来刷新查找位置,判断s1和s2中的值是否相等,如果相等则继续往下比较直到不满足条件跳出循环判断s2的值是否为0,若为0返回cur的地址,否则cur++继续向后查找,重复上述步骤,若arr2不在arr1中直到cur为'\0'结束查找返回NULL。
6.strtok函数的使用
char * strtok ( char * str, const char * sep);
• sep参数指向⼀个字符串,定义了⽤作分隔符的字符集合
• 第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标记。
• strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使⽤strtok函数切分的字符串⼀般都是临时拷⻉的内容 并且可修改。)
• strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串 中的位置。
• strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标 记。
• 如果字符串中不存在更多的标记,则返回 NULL 指针。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "15483189@163.com";//带分隔符的字符串
char arr2[] = "@.";//存储分隔符的字符串
char *ret = NULL;
for(ret = strtok(arr1,arr2) ; ret ;ret = strtok(NULL,arr2))
{
printf("%s\n",ret);
}
return 0;
}
7.strncpy函数的使用
char * strncpy ( char * destination, const char * source, size_t num );
与strncpy函数差不多,但多了以下几点:
•拷⻉num个字符从源字符串到⽬标空间。
• 如果源字符串的⻓度⼩于num,则拷⻉完源字符串之后,在⽬标的后边追加0,直到num个。
8.strncat函数的使用
char * strncat ( char * destination, const char * source, size_t num );
与strncat函数差不多,但多了以下几点:
•将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字 符
•如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾
9.strcmp函数的使用
int strncmp ( const char * str1, const char * str2, size_t num );
与strncmp函数差不多,但多了以下一点:
•⽐较str1和str2的前num个字符,如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀ 样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0.
10.strerror函数的使用
strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会讲对应的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE * pFile;
pFile = fopen ("hhh.txt","r");
if (pFile == NULL)
printf ("错误是: %s\n", strerror(errno));
return 0;
}