文章目录
1、字符串函数介绍
strlen() //求字符串长度
//长度不受限制的字符串函数
strcpy()
strcat()
strcmp()
//长度受限制的字符串函数
strncpy()
strncat()
strncmp()
//字符串查找
strstr()
strtok()
//错误信息报告
strerror()
//字符操作
C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。
字符串常量适用于那些对它不做修改的字符串函数。
2、库函数介绍及模拟实现
2.1 strlen
所需头文件:#include<string.h>。
解释:string length:字符串长度。
作用:求字符串长度,统计的是字符串中**‘\0’*之前出现的字符个数。
原型:size_t strlen (const char str);
size_t 本质是unsigned int 无符号整型(在vs编辑器中被定义为无符号整型)。
strlen()函数使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n",strlen(arr));
return 0;
}
模拟实现strlen函数
思路:
代码:
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
assert(str);
const char* start = str;
const char* end = str;
while(*end != '\0')
{
end++;
}
return end - start;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n",len);
return 0;
}
- const权限问题:提升指针所指空间数据的健壮性。
- 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
- 参数指向的字符串必须要以’\0’结束。
- 函数的返回值为size_t,是无符号的。
- 一个汉字占两个字符。
2.2 strcpy
所需头文件:#include<string.h>。
原型:char * strcpy (char * destination, const char * source);
作用:字符串拷贝。
参数(传参)描述:目的地(destination)和源头(source),将源头拷贝到目的地。
strcpy函数使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[10] = {0};
const char* p = "abcdef";
strcpy(arr,p);
printf("%s\n",arr);
return 0;
}
模拟实现strcpy函数
思路:
代码:
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest,const char* src)
{
assert(dest);
assert(src);
char* ret = dest;
while(*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "abc";
char arr2[] = "hello world";
printf("%s\n",my_strcpy(arr1,arr2));
return 0;
}
- 源字符串必须以‘\0’结束。
- 会将源字符串中的’\0’拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串(避免发生内存空间越界)。
- 常量字符串不可修改(目标空间应当是可修改的)。
2.3 strcat
所需头文件:#include<string.h>。
原型:char * strcat( char * destination, const char * source);
作用:字符串追加。
参数(传参)描述:目的地(destination)和源头(source),将源头(数据)追加到目的地数据后方。
strcat函数使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strcat(arr1,arr2);
printf("%s\n",arr1);
return 0;
}
模拟实现strcat函数
思路:
代码:
#include<stdio.h>
char* my_strcat(char* dest,const char* src)
{
char* cur = dest;
while(*cur)
{
cur++;
}
while(*cur++ = *src++)
{
;
}
return dest;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
printf("%s\n",my_strcat(arr1,arr2));
return 0;
}
- 从’目的地里的\0’开始进行追加,结束于源字符串的’\0’ 源字符串必须以’\0’结束。
- 目标空间必须能够容纳下源字符串的内容。
- 目标空间必须可修改。
- 无法完成自己给自己追加的操作(单一字符串的结束标志’\0’已经被覆盖)。
2.4 strcmp
所需头文件:#include<string.h>。
作用:字符串比较(比较对应位置上字符的的大小而非长度)。
原型:int strcmp ( const char * str1, const char * str2);
strcmp函数使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abg";
int ret = strcmp(arr1,arr2);
if(ret < 0)
printf("arr1<arr2\n");
else if(ret>0)
printf("arr1>arr2\n");
else
printf("arr1==arr2");
printf("%d\n",ret);
return 0;
}
模拟实现strcmp函数
思路:
代码:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* s1,const char* s2)
{
assert(s1 && s2);
while(*s1 == *s2)
{
if(*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
return *s1 - *s2;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abg";
int ret = my_strcmp(arr1,arr2);
if(ret < 0)
printf("arr1<arr2\n");
else if(ret>0)
printf("arr1>arr2\n");
else
printf("arr1==arr2");
printf("%d\n",ret);
return 0;
}
标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字;
- 第一个字符串小于第二个字符串,则返回小于0的数字;
- 第一个字符串等于第二个字符串,则返回0;
2.5 strncpy
所需头文件:#include<string.h>。
原型:char * strncpy ( char * destination, const char * source, size_t num);
作用:有限字符个数的字符串拷贝。
strncpy函数使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "xxxxx";
strncpy(arr1,arr2,3);
printf("%s\n",arr1);
return 0;
}
- 从源字符串拷贝num个字符到目标空间。
- 如果源字符串的长度小于num,拷贝完源字符串后,在目标的后边追加0,直到num个。
2.6 strncat
所需头文件:#include<string.h>。
原型:char * strcat ( char * destination, const char * source,size_t num);
作用:有限字符个数的字符串追加。
strncat函数使用:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "xyz";
strncat(arr1,arr2);
printf("%s\n",arr1);
return 0;
}
- 无论追加几个字符都应加’\0’作为结束标志。
- 可以自己给自己追加(限制字符个数)。
2.7 strncmp
所需头文件:#include<string.h>。
原型: int strncmp ( const char * str1, const char * str2,size_t num);
作用:有限字符个数的字符串比较(比较对应位置上字符的的大小而非长度)。
strncmp函数使用:
#include<stdio.h>
int main()
{
int ret = strncmp("abcdef","abc",4);
printf("%d\n",ret);
}
- 比较到出现两个字符不一样或者一个字符串结束或者num个字符全部比完。
2.8 strstr
所需头文件:#include<string.h>。
原型:char * strstr ( const char * str1, const char * str2);;
作用:在一个字符串中找另一个字符串是否存在。若存在,返回字串第一次出现的地址;不存在,返回NULL。
strstr函数使用:
#include<stdio.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "bcd";
char * p =strstr(arr1,arr2);
if(p=NULL)
{
printf("不存在\n");
}
else
{
printf("%s\n",p);
}
return 0;
}
模拟实现strstr函数
思路:
代码:
#include<stdio.h>
char* my_strstr(const char *str1,const char* str2)
{
const char* s1 = str1;
const char* s2 = str2;
const char* p = str1;
if(*str2 == '\0')
{
return str1;
}
while(*p)
{
s1 = p;
s2 = str2;
while(*s1!='\0' && *s2!='\0' && (*s1 == *s2))
{
s1++;
s2++;
}
if(*s2 == '\0')
{
return (char*)p;
}
p++;
}
return NULL;
}
int main()
{
char arr1[] = "abcdefabcdef";
char arr2[] = "cde";
char * p = my_strstr(arr1,arr2);
if(p==NULL)
{
printf("不存在\n");
}
else
{
printf("%s\n",p);
}
return 0;
}
2.9 strtok
所需头文件:#include<string.h>。
原型:char * strtok ( char * str, const char *sep );
作用:以分割符作为划分线切将字符串进行切割。
参数:sep参数是个字符串,定义了用作分隔符的字符集合;str参数指定一个字符串,包含了0个或多个由sep字符串中一个或多个分隔符分割的标记。
在传NULL值时,strtok函数会使用记忆(保存)功能,获取对应地址。
strtok函数找到str中的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针。
strtok函数使用:
#include<stdio.h>
int main()
{
char arr[] = "abcdef@123.com"
char buf[200] = {0};//由于strtok函数在使用中会修改源字符串,所以在使用时尽量修改拷贝后的内容(视情况而定)
strcpy(buf,arr);
const char* p = "@.";
char* str = NULL;
for(str=strtok(buf,p);str!=NULL;str=strtok(NULL,p))
{
printf("%d",str);
}
return 0;
}
2.10 strerror
所需头文件:#include<errno.h>。
原型:char * strerror ( int errnum );
作用:把错误码转换成错误信息。
调用库函数出错时,就会把错误码记录到errno变量里。errno是C语言提供的全局的错误变量
perror函数原型:void perror ( const char * str);
perror可以看作printf加上strerror后的结果。 perror打印的依然是errno变量中的错误码对应的错误信息。
strerror函数使用:
#include<stdio.h>
#include<error.h>
int main()
{
FILE* pf = fopen("test.txt","r");
if(pf == NULL)
{
printf("%s\n",strerror(errno));
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
#include<stdio.h>
#include<errno.h>
int main()
{
FILE* pf = fopen("test.txt","r");
if(pf == NULL)
{
perror("fopen自定义命名");
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
3、字符分类函数
//字符分类
//任何控制字符
iscntrl()
//空白字符:空格' ',换页'\f',换行'\n',回车'\r',制表符'\t'或者垂直制表符'
'\v'
isspace()
//十进制数字0-9
isdigit()
//十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
isxdigit()
//小写字母a-z
islower()
//大写字母A-Z
isupper()
//字母a-z或A-Z
isalpha()
//字母或者数字,a-z,A-Z,0-9
isalnum()
//标点符号,任何不属于数字或者字母的图形字符(可打印)
ipunct()
//任何图形字符
isgraph()
//任何可打印字符,包括图形字符和空白字符
isprint()
//字符转换
//大写字母转小写
tolower()
//小写字母转大写
toupper()
3.1部分函数具体使用:
#include<stdio.h>
#include<ctype.h>
int main()
{
char ch = "a";
//非对应输出字符打印0
int ret = isdigit(ch);
int ret1 = isxdigit(ch);
int ret3 = islower(ch);
printf("%d",ret);//输出ASCII码值
return 0;
}
#include<stdio.h>
#include<ctype.h>
int main()
{
char arr[] = "Are you ok?";
char* p = arr;
while(*p){
if(islower(*p)){
*p = toupper(*p);
}
p++;
}
printf("%s\n",arr);
return 0;
}
- ch本身不会改变,改变的是它的返回值。
总结:熟练掌握库函数,可以统一代码,省略大量冗余代码,编写代码时很方便。