前言:
通过C语言指针进阶的知识,接下来继续学习关于C语言哪些实用的函数呢?
/知识点汇总/
字符串函数分类:
1.求字符串长度:strlen
2.长度不受限制的字符串函数:strcpy、strcat、strcmp
3.长度受限制的字符串函数:strncpy、strncat、strncmp
4.字符串查找函数:strstr、strtok
5.错误信息报告函数:strerroe、perror
6.字符分类函数:
iscntrl – 任何控制字符
isspace – 空白字符:‘空格’,换页’\f’,回车’\n’,制表符’\t’.
isdigit — 十进制数字0~9
isxdigit – 十六进制数字 ,包括十进制数字,小写字母af,大写字母AF
islower — 小写字母a~z
isupper — 大写字母A~Z
isalpha – 字母az或AZ
isalnum – 字母或数字 ,az,AZ,0~9
ispunct – 标点符号,任何不属于数字或者字母的图形字符
isgraph – 任何图形字符
7.字符转换函数:
int tolower (int c); — 大写转小写字母
int toupper (int c); — 小写转大写字母
(这里把1~6的函数归纳到字符串函数里讲解)
库函数:用来求字符串长度的库函数,本质上统计的是字符串中’\0’之前的字符个数
原型:size_t strlen( const char *string );
头文件:#include
#include
#include
int main()
{
size_t len1 = strlen("abcdef");
//等价,其中传参传递的首元素地址
const char* str = "abcdef";
size_t len2 = strlen(str);
printf("%d\n", len1);//6
printf("%d\n", len2);//6
//另外得注意,字符串本身就放置了'\0'的情况
size_t len1 = strlen("abc\0def");
const char* str = "abc\0def";
size_t len2 = strlen(str);
printf("%d\n", len1);//3
printf("%d\n", len2);//3
return 0;
}
补充size_t 的特点:
#include
#include
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)//因为strlen的返回值是无符号数
//两个无符号数相减得到的依然是无符号数
//相等于即使相减为负数,但是返回值会约束其符号位无效了,从而成为一个很大的数远远大于0
printf(">=0\n");
else
printf("<=0\n");
return 0;
}
功能:完成字符串的拷贝,将原目标字符串地址拷贝到目标字符串地址。
原型:char *strcpy( char *strDestination, const char *strSource );
头文件:#include
#include
#include
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
使用strcpy几个注意事项:
1.源字符串必须以’\0’结束(因为会包括’\0’一起拷贝过去)
2.会将源字符串中的’\0’拷贝到目标空间
3.目标空间必须足够大,确保能存放源字符串
4.目标空间必须可变(不能是常量)
5.学会模拟实现,才能更好掌握
#include
#include
int main()
{
char arr1[20] = "xxxxxxxxxxxxxxx";
//char arr2[] = "hello";
//char arr2[] = {'A','B','C'};
char arr2[] = { 'A','B','C','\0'};
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
小结:所以是由程序员决定目标空间必须足够大,且目标空间必须权限为可写
功能:将源头的字符串地址追加到目标字符串的地址
原型:char *strcat( char *strDestination, const char *strSource );
头文件:
执行步骤:
1.找到arr1的末尾’\0’
2.再把arr1的内容追加到arr1后边(arr2的首地址会覆盖,arr1的’\0’实现追加)
#include
#include
int main()
{
char arr1[20] = "abc";
char arr2[] = "def";
strcat(arr1, arr2);
printf("%s\n", arr1);//abc(追加)def
return 0;
}
注意事项:
1.目标空间足够大
2.目标空间必须有’\0’(保证能找到目标空间的末尾)
3.源字符串也得有’\0’,拷贝时会一通拷贝过去,从而组成新字符串得结束位标志符
4.自己追加自己时,源指针和目标指针都指向首字符,然后源字符串的’\0’,会被覆盖掉,导致后面追加时,找不到’\0’了。尽管库函数能实现,但是不建议
功能:字符串比较大小(不是比较长度,而是比较对应位置上的字符大小,即ASCII码值)
原型:int strcmp( const char *string1, const char *string2 );
头文件:
Return Value:
Value Relationship of string1 to string2
//< 0 string1 less than string2
//0 string1 identical to string2
//> 0 string1 greater than string2
标准规定:比较ASCLL码值
1.第一个字符串大于第二个字符串,则返回大于0的数字
2.第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小于0的数字
#include
#include
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);//-1,第一个字符串比第二个字符串小,返回小于零的数值
return 0;
}
小结:
strlen,strcat,strcmp,strcpy属于长度不受限制的字符串函数;
接着介绍长度受限制字符串函数:strncat,strncmp,strncpy
功能:字符串拷贝(可指定长度)
原型:char* strncpy(char* strDest, const char* strSource, size_t count);
头文件:
#include
#include
int main()
{
char arr1[20] = { 0 };
char arr2[] = "abcdefghi";
strncpy(arr1, arr2, 3);
printf("%s\n", arr1);//abc
char arr1[20] = "xxxxxxxxxxxxxxx";
char arr2[] = "abcdefghi";
strncpy(arr1, arr2, 3);
printf("%s\n", arr1);//abcxxxxxxxxxx
return 0;
}
探讨拷贝长度的影响:
#include
#include
int main()
{
char arr1[20] = "xxxxxxxxxxxx";
char arr2[] = "abc";
strncpy(arr1, arr2, 6);//长度比str2长时,自动补的'\0'.
printf("%s\n", arr1);//abc\0\0\0
return 0;
}
功能:字符串追加(可指定长度)
原型:char* strncat(char* strDest, const char* strSource, size_t count);
头文件:
#include
#include
int main()
{
char arr1[20] = "abc";
char arr2[] = "defghi";
strncat(arr1, arr2, 3);//长度比str2长时,自动补的'\0'.
printf("%s\n", arr1);//abc
return 0;
}
探究’\0’的追加情况1:
#include
#include
int main()
{
char arr1[20] = "abc\0xxxxxxxxxxx";//字符串中本身具备'\0'时,依然以'\0'开始覆盖,最后补'\0'结束
char arr2[] = "defghi";
strncat(arr1, arr2, 3);
printf("%s\n", arr1);//abcdef\0
return 0;
}
探究’\0’的追加情况2:
#include
#include
int main()
{
char arr1[20] = "abc\0xxxxxxxxxxx";//字符串中本身具备'\0'时,依然以'\0'开始覆盖,最后补'\0'结束
char arr2[] = "defghi";
strncat(arr1, arr2, 10);//10长度比str2长时,自动在末尾补'\0'.此函数就不会对超出长度的字符进行操作了
printf("%s\n", arr1);//abcdef
return 0;
}
功能:字符串大小比较(可指定长度)
原型:int strncmp( const char *string1, const char *string2, size_t count );
头文件:
#include
#include
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcqw";
//int ret = strncmp(arr1, arr2, 3);
//printf("%d\n", ret);//0
int ret = strncmp(arr1, arr2, 4);//比较字符串前4个字符
printf("%d\n", ret);//-1
return 0;
}
功能:在字符串中找字符串(字符串中找子字符串或着段),strstr会返回str1中str2第一次出现的位置,如果str1中没有str2,则返回NULL
原型:const char *strstr( const char *string, const char *strCharSet );
头文件:
#include
#include
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "def";
char* ret = strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
{
printf("%s\n", ret);//defghi
}
return 0;
}
功能:常用于切割字符串
原型:char *strtok( char *strToken, const char *strDelimit );
头文件:
注意:
strtok函数找到str中的下一个标记,并将其用’\0’,结尾返回一个指向这个标记的指针;
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。
比如:
IP地址:本来是一个无符号的整数,这种整数不方便记忆,所以将这个整数转换成点分十进制的表示方式
[email protected] – 分隔符可以是@或 ’ . ’
192.168.101.23 – 分隔符可以是 ’ . ’
#include
#include
int main()
{
char arr[] = "[email protected]";
char* p = "@.";
char* s = strtok(arr, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
printf("%s\n", s);
return 0;
}
小结:在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改
如下所示,利用一个新数组保存原数组数据:
#include
#include
int main()
{
char arr[] = "[email protected]";
char buf[200] = { 0 };
strcpy(buf, arr);
char* p = "@.";
char* s = strtok(buf, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
printf("%s\n", s);
return 0;
}
小结:
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回NULL指针。
如下所示,每次调用都会保存上次调用的标记(具备记忆功能),依次类推:
#include
#include
int main()
{
char arr[] = "[email protected]";
char buf[200] = { 0 };
strcpy(buf, arr);
char* p = "@.";
char* s = strtok(buf, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
printf("%s\n", s);
s = strtok(NULL, p);
printf("%s\n", s);
s = strtok(NULL, p);
printf("%s\n", s);
return 0;
}
为了代码的实用性,以循环的方式依次识别标记,对代码进行优化:
#include
#include
int main()
{
char arr[] = "[email protected]";
char buf[200] = { 0 };
strcpy(buf, arr);
char arr2[] = "192.168.101.23";
char buf2[200] = { 0 };
strcpy(buf2, arr2);
char* p = "@.";
char* s = NULL;
for (s = strtok(buf, p); s != NULL; s = strtok(NULL, p))
{
printf("%s\n", s);
}
char* p2 = ".";
for (s = strtok(buf2, p2); s != NULL; s = strtok(NULL, p2))
{
printf("%s\n", s);
}
return 0;
}
小结:
1.strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。
2.strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
3.strtok函数的第一个参数为NULL,函数将在同一个字符串中将被保存的位置开始,查找下一个标记。
4.如果字符串中不存在更多的标记,则返回标记为NULL指针
功能:是将错误码翻译成错误信息,返回错误信息的字符串的起始地址
原型:char *strerror( int errnum );
头文件:
错误码比如常见网页打不开显示:-404-
C语言中使用库函数的时候,如果发生错误,就会将错误码放在errno的变量中,errno是一个全局变量,可以直接使用的
#include
#include
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d: %s\n", i, strerror(i));
}
return 0;
}
strerror函数常用于文件的操作判定
以打开文件的例子展示:
fopen以读的形式打开文件,如果文件存在,打开成功;如果文件不存在,打开失败。
#include
#include
int main()
{
FILE* pf = fopen("add.txt", "r");
if (pf == NULL)
{
printf("打开文件失败,原因是:%s\n",strerror(errno));
return 1;
}
else
{
printf("打开文件成功\n");
}
return 0;
}
对比perroe函数:
原型:void perror( const char *string );
功能:直接打印错误码,所对应的错误信息(先打印自定义信息:xxx,再直接打印错误原因)
等价:perror == printf + strerror
#include
#include
int main()
{
FILE* pf = fopen("add.txt", "r");
if (pf == NULL)
{
perror("打开文件失败");
return 1;
}
else
{
printf("打开文件成功\n");
}
return 0;
}
字符分类函数:
iscntrl – 任何控制字符
isspace – 空白字符:‘空格’,换页’\f’,回车’\n’,制表符’\t’…
较常用:
isdigit — 十进制数字0~9
isxdigit – 十六进制数字 ,包括十进制数字,小写字母af,大写字母AF
islower — 小写字母a~z
isupper — 大写字母A~Z
isalpha – 字母az或AZ
isalnum – 字母或数字 ,az,AZ,0~9
ispunct – 标点符号,任何不属于数字或者字母的图形字符
isgraph – 任何图形字符
这里以常见的为例
原型:int iswlower( wint_t c );
头文件:
功能:判断字符是否为小写字母,如果为小写,则返回非零的值;如果不是小写,则返回0
#include
#include
int main()
{
char ch = 'a';
if (islower(ch))
{
printf("是小写\n");
}
else
{
printf("不是小写\n");
}
return 0;
}
原型:int isdigit( int c );
头文件:
功能:判断字符是否为十进制数字0~9
原型:int isxdigit( int c );
头文件:
功能:判断字符是否为十六进制数字 ,包括十进制数字,小写字母af,大写字母AF
#include
#include
int main()
{
//if(ch >= 'a' && ch <= 'z')
int ret = islower('a');
printf("%d\n", ret);
int ret2 = isdigit('5');
printf("%d\n", ret2);
int ret3 = isxdigit('c');
printf("%d\n", ret3);
return 0;
}
原型:int islower( int c );
头文件:
功能:判断字符是否为小写字母a~z
原型:int isupper( int c );
头文件:
功能:判断字符是否为大写字母A~Z
#include
#include
int main()
{
char ch1 = 'A';
char ch2 = 'a';
if(islower(ch2))
printf("小写字母:%c\n",ch2);
if(islower(ch1))
printf("大写字母:%c\n",ch1);
return 0;
}
C语言只有两个字符转换函数:tolower 、toupper
原型:int tolower( int c );
头文件:
功能:将大写字母转换为小写字母
#include
#include
int main()
{
char arr[] = "TEST String.";
char* p = arr;
while (*p)
{
if (isupper(*p))
{
*p = tolower(*p);
}
p++;
}
printf("%s\n", arr);
return 0;
}
原型:int toupper( int c );
头文件:
功能:将小写字母转换为大写字母
#include
#include
int main()
{
int ret = tolower('A');
printf("%c\n", ret);//a
int ret2 = toupper('a');
printf("%c\n", ret2);//A
int ret3 = tolower('A');
printf("%c\n", ret3);//a
ret3 = toupper(ret3);
printf("%c\n", ret3);//A
return 0;
}
熟悉各个函数的使用有利于程序的可读性和效率,此篇笔记有误的地方请多多指教。
半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)