Hello, 大家好,我是一代,今天给大家带来有关字符函数和字符串函数的有关知识
所属专栏:C语言
创作不易,望得到各位佬们的互三呦
一.字符函数
在C语言中有一些函数是专门为字符设计的,这些函数的使用都需要包含一个头文件<ctype.h>
如:(注:以下函数原型都很相似,都为int 函数(int 字符))
函数
iscntrl 检查字符是否为可控制字符
isspace 检查字符是否为一个空格、制表符、换行,换页’\f‘或回车
isdigit 检查字符是否为数字’0‘-’9‘
isxdigit 检查字符是否为16进制的字符包括所有10进制数字,小写字母,a-f,大 写字符A-F
islower 检查字符是否为小写字母
isupper 检查字符是否为大写字母
isalpha 检查字符是否为可打印字符
isalnum 检查字符是否为字母或十进制数字
ispunct 检查字符是否为可打印标点字符(不属于数字和字母的图形字符)
isgraph 检查字符是否为可打印字符(不包括空格)
isprint 检查字符是否为可打印字符(包括空格)
以上函数当条件满足时的返回值都为非0的整数
如: islower(c),如果c是小写字母,返回非零整数,不是小写字母就返回0
#include<stdio.h>
#include<ctype.h>
int main()
{
printf("%d", islower('b'));
}
二.字符转换函数
C语言提供了两种字符转换函数
1.int tolower(int c) 将传进去的大写字母转换为小写
2. int upper(int c) 将传进去的小写字母转换为大写
如:
#include<stdio.h>
#include<ctype.h>
int main()
{
printf("%c", tolower('A'));//将大写字母转小写,如果不为大写字母则不改变
}
三.字符串函数及字符串模拟
这里字符串函数包含的头文件都为string.h
一.strlen函数
函数原型:size_t strlen (const char*str)
头文件:string.h
功能:计算字符串长度(字符串以‘\0’为结束标志,strlen函数返回的是在字符串中‘\0’前面面出现的字符个数)
注意:1.参数指向的字符串必须以'\0'为结束标志,否则不知道字符串在哪里结束,返回随机值
2.函数的返回值为size_t , 是无符号的(下面会举相关例题)
就strlen的返回值有一个例题:
#include<stdio.h>
#include<string.h>
int main()
{
const char* str1 = "acbdh";
const char* str2 = "ads";
if (strlen(str2) - strlen(str1) > 0)
{
printf(">");
}
else
{
printf("<");
}
return 0;
}
这里很多人会认为输出的是<,但实际输出的是>,为什么呢?其实是以为strlen的返回值为size_t,其表示的数都为无符号数,也就是表示的为正数,比如-1,因为返回类型为size_t,其最高位的符号为表示的就为2的32次方,而不是表示正负号。
strlen函数模拟实现
方法1:指针减指针,指针减指针表示的是两个指针之间相差的元素个数
#include<stdio.h>
#include<assert.h>
size_t my_strlen(char*str)
{
assert(str);//防止str为空指针,包含头文件为assert.h
char* p = str;
while (*str != '\0')
{
str++;
}
return str - p;
}
int main()
{
const char* str1 = "acbdh";
printf("%zd", my_strlen(str1));
return 0;
}
方法2:计数器方式,用count记录元素个数
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
assert(str);//防止str为空指针,包含头文件为assert.h
int count = 0;
while (*str != '\0')
{
str++;
count++;
}
return count;
}
int main()
{
const char* str1 = "acbdh";
printf("%zd", my_strlen(str1));
return 0;
}
方法3:递归方式
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
assert(str);//防止str为空指针,包含头文件为assert.h
if (*str == '\0')
return 0;
return my_strlen(str + 1) + 1;
}
int main()
{
const char* str1 = "acbdh";
printf("%zd", my_strlen(str1));
return 0;
}
二.strcpy函数
函数原型:char* strcpy(char* destination ,const char* source)
功能:把源字符串复制到目标字符串
注意:1.源字符必须以‘\0’结束
2.会将源字符串的‘\0’拷贝到目标空间
3.目标空间足够大,以确保能够存放源字符串
4.目标空间必须可修改
strcpy的模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* str1, char* str2)
{
assert(str1 && str2);
char* s = str1;
while (*str1++ = *str2++);//先解引用在++
return s;
}
int main()
{
char str1[] = "acbdh";
char* str2 = "acb";
printf("%s", my_strcpy(str1,str2));
return 0;
}
三.strcat函数
函数原型:char* strcat(char*dest,const char*str)
功能:将两个字符串拼接起来,将str拼接到dest上
注意:1.源字符串必须以'\0'结束
2.目标字符串中也得有‘\0’,否则没办法知道从哪里开始拼接
3.目标空间足够大,能容纳下源字符的内容
4.目标空间必须可修改
strcat模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* str1,const char*str2)
{
assert(str1&&str2);//防止str为空指针,包含头文件为assert.h
char* s = str1;
while(*str1)
{
str1++;
}
while (*str1++ = *str2++);//当*str2为'\0'时表达式结果为假
return s;
}
int main()
{
char str1[20] = "acbdh";
const char* str2 = "sad";
printf("%s", my_strcat(str1,str2));
return 0;
}
四.strcmp函数
函数原型:int strcmp(char*str1,char*str2)
功能:比较两个字符串的大小,若第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串小于第二个字符串,则返回小于0的数字
第一个字符串等于第二个字符串,则返回0
注意:比较两个字符串大小是用ascii值比较,一个一个字符比较
strcmp函数模拟
#include<stdio.h>
#include<assert.h>
int my_strcmp(char* str1,const char*str2)
{
assert(str1&&str2);//防止str为空指针,包含头文件为assert.h
while (*str1 == *str2)
{
if (*str1 == '\0')//代表*str1和*str2都为'\0'
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
const char *str1 = "acbdh";
const char* str2 = "sad";
printf("%d", my_strcmp(str1,str2));
return 0;
}
五.strncpy函数
函数原型:char* strncpy(char* destination,char *source,size_t num)
功能:拷贝num个字符从源字符串到目标空间
注意:如果源字符串的长度小于num,则拷贝完源字符后,到目标空间的后边追加'\0',直至num个
strncpy函数模拟
#include <stdio.h>
#include <string.h>
#include<assert.h>
char* my_strncpy(char* str1, const char* str2, size_t n)
{
assert(str1 && str2);
char* s = str1;
for(int i=0;i<n && str2!='\0';i++)
{
*str1++ = *str2++;
}
*str1 = '\0';
return s;
}
int main()
{
char str1[20]="name ";
char str2[20]="str";
printf("%s", my_strncpy(str1, str2, 1));
}
六.strncat函数
函数原型:char*strncat(char* destination ,const char*source ,size_t num)
功能 :将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符
注意:如果source 指向的字符串的长度小于num的时候,只会将字符串中到'\0'的内容追加到destination指向的字符串末尾
strncat模拟
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* dest, char* str, size_t n)
{
assert(dest && str);
int i;
char* s = dest;
while (*dest != '\0')
{
dest++;
}
for (i = 0; i < n && str[i] != '\0'; i++)
{
dest[i] = str[i];
}
dest[i] = '\0';
return s;
}
int main()
{
char str[] = { "abcd" };
char dest[20] = { "mnkj***\0***" };
char* ret = my_strncat(dest, str, 2);
printf("%s", ret);
}
七.strncmp函数
函数原型:(const char*str1, const char*str2,size_t num)
功能: 比较str1和str2的前num个字符,如果相等就继续往后⽐较,最多比较num个字⺟,如果提前发现不一样,就提前结束。如果num个字符都相等,就是相等返回0,如果str字符串<str2字符串,就返回小于0的数,反之,返回大于0的数
strncmp函数模拟
#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* str1, const char* str2,size_t num)
{
assert(str1 && str2);//防止str为空指针,包含头文件为assert.h
while (*str1 == *str2&& num--)
{
if (*str1 == '\0')//代表*str1和*str2都为'\0'
return 0;
str1++;
str2++;
}
if (num == 0)
{
return 0;
}
return *str1 - *str2;
}
int main()
{
const char* str1 = "afbdh";
const char* str2 = "afbh";
printf("%d", my_strncmp(str1, str2, 9));
return 0;
}
八.strstr函数
函数原型:char* strstr(const char *str1,const char*str2)
功能: 返回字符串str2在字符串str1中第⼀次出现的位置
strstr函数模拟
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* p1 = NULL;
const char* p2 = NULL;
const char* cur = str1;
if (*str2 == '\0')
return str1;
while (*cur)
{
p1 = cur;//记录str1开始的起始位置
p2 = str2;//记录str2的位置
while (*p1 == *p2 && *p1 != '\0' && *p2 != '\0')
{
p1++;
p2++;
}
if (p2 == '\0')
{
return (char*)cur;//将const char*强转
}
if (*p1 == '\0')
{
return NULL;
}
cur++;//起始位置不可以,刷新起始位置
}
return NULL;
}
int main()
{
char a[] = { "abbbcde" };
char b[] = { "bc" };
printf("%s", my_strstr(a, b));
}
九.strtok函数
函数原型:char* strtok(char*str1, const char*str2)
功能: 将str1进行分割,str2中包含分割符(第⼀个参数指定⼀个字符串,它包含了0个或者多个由str2字符串中⼀个或者多个分隔符分割的标记)
注意:1.strtok函数找到str1中出现的分割符,将其标记,并将其之前的字符串⽤ \0 结尾,返回⼀个指向这个标记的指针,下次用的时候第一个参数为NULL。(注: strtok函数会改变被操作的字符串,所以在使⽤strtok函数切分的字符串⼀般都是临时拷贝的内容 并且可修改。)
2.strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。
3.strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记。
4.如果字符串中不存在更多的标记,则返回 NULL 指针。
strstr使用示例
#include<stdio.h>
#include<string.h>
int main()
{
char a[] = { "zhju.sj@sj" };
char* sep = ".@";
char* str = NULL;
for (str = strtok(a, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
}
九.strerror函数
函数原型:char*strerror (int errnum)
功能:strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。 在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头文件中说明 的,C语言程序启动的时候就会使⽤一个全面的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会讲对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。