1. 字符分类函数
C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。这些函数的使⽤都需要包含⼀个头⽂件是 ctype.h

这些函数的使用方法非常类似,基本结构 int isxxxx(xxx),返回值均为0,或非0
例题
//写⼀个代码,将字符串中的⼩写字⺟转⼤写,其他字符不变。
#include<stdio.h>
#include<ctype.h>
int main()
{
int i = 0;
char str[] = "Test";
char c;
while (str[i])
{
c = str[i];
if (islower(c))
c -= 32;
putchar(c);
i++;
}
return 0;
}
2.字符转换函数

同上一个例题
#include<stdio.h>
#include<ctype.h>
int main()
{
int i = 0;
char str[] = "Test";
char c;
while (str[i])
{
c = str[i];
if (islower(c))
c = toupper(c);
putchar(c);
i++;
}
return 0;
}
上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使touuperh函数。
3.str系列函数
3.1 strlen
函数原型
size_t strlen ( const char * str );
功能:统计参数str指向的字符串的长度。统计的是字符串中,'\\0'之前的字符的个数。
返回值:返回了str指向的字符串的⻓度,返回的长度不会是负数,所以返回类型是size_t
代码演示
int main()
{
const char* str = "abcdef";
printf("%zu\\n", strlen(str));
return 0;
}
strlen的模拟实现
1.计数器方法
size_t my_strlen(const char* p)
{
int count = 0;
while (*p)
{
count++;
p++;
}
return count;
}
2.指针 – 指针法
size_t my_strlen(const char* p)
{
char* s = p;
while (*p)
{
p++;
}
return p – s;
}
3.递归法
size_t my_strlen(const char* p)
{
if (*p != '\\0')
return 1 + my_strlen(p + 1);
else
return 0;
}
为方便大家理解这种方法,下面画一个图

3.2 strcpy
函数原型
char* strcpy(char * destination, const char * source );
功能:字符串拷贝,拷到源头字符串中的\\0为⽌。参数:
destination:指针,指向⽬的地空间
source:指针,指向源头数据
返回值:
strcpy函数返回的目标空间的起始地址
代码演示
int main()
{
char str1[20] ="————";
char str2[] = "Hello World";
strcpy(str1, str2);
printf("%s", str1);
return 0;
}


注意:
源字符串必须以 '\\0' 结束。
会将源字符串中的 '\\0' 拷贝到目标空间。
目标空间必须⾜够大,以确保能存放源字符串。
目标空间必须可修改。
strcpy的模拟实现
char* my_strcpy(char* destination, const char* source)
{
char* ret = destination;
//while (*source != '\\0')
//{
//*destination = *source;
//destination++;
//source++;
//}
//*destination = *source;
while (*destination++ = *source++);
return ret;
}
3.3 strcat
函数原型
char * strcat ( char * destination, const char * source );
功能:字符串追加,把 source 指向的源字符串中的所有字符都追加到 destination 指向的空间 中。
参数: destination :指针,指向⽬的地空间 source :指针,指向源头数据
返回值: strcat 函数返回的⽬标空间的起始地址
代码演示
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\\n", arr1);
return 0;
}
使⽤注意事项:
源字符串必须以 '\\0' 结束。
⽬标字符串中也得有 \\0 ,否则没办法知道追加从哪⾥开始。
⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。
⽬标空间必须可修改。
strcat的模拟实现
char* my_strcat(char *destination, const char* source)
{
char* ret = destination;
while (*destination)
{
destination++;
}//找到源字符\\0的位置
while (*destination++ = *source++);
return ret;
}
3.4 strcmp
函数原型
int strcmp ( const char * str1, const char * str2 );
功能:⽤来⽐较 str1 和 str2 指向的字符串,从两个字符串的第⼀个字符开始⽐较,如果两个字符 的ASCII码值相等,就⽐较下⼀个字符。直到遇到不相等的两个字符,或者字符串结束。
参数:str1 :指针,指向要⽐较的第⼀个字符串 str2 :指针,指向要⽐较的第⼆个字符串
返回值:
标准规定
第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字
第⼀个字符串等于第⼆个字符串,则返回0
第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字
代码演示
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int ret = strcmp(arr1, arr2);
printf("%d\\n", ret);
if (ret > 0)
printf("arr1 > arr2\\n");
else if (ret == 0)
printf("arr1 == arr2\\n");
else
printf("arr1 < arr2\\n");
return 0;
}
strcmp的模拟实现
int my_strcmp(const char* str1, const char* str2)
{
while (*str1 == *str2)
{
if (*str1 == 0)
return 0;
str1++;
str2++;
}
return *str1 – *str2;
}
3.5 strncpy
函数原型
char * strncpy ( char * destination, const char * source, size_t num );
功能:字符串拷⻉;将 source 指向的字符串拷⻉到 destination 指向的空间中,最多拷贝num 个字符。
参数: destination :指针,指向目的地空间 source :指针,指向源头数据 num :从source指向的字符串中最多拷⻉的字符个数
返回值: strncpy 函数返回的⽬标空间的起始地址
代码演示
int main()
{
char arr1[20] = "——–";
char arr2[] = "abcde";
strncpy(arr1, arr2, 4);
printf("%s\\n", arr1);
return 0;
}
当num>源字符数,会在后面补\\0

⽐较strcpy和strncpy函数
strcpy 函数拷⻉到 \\0 为⽌,如果⽬标空间不够的话,容易出现越界⾏为
strncpy 函数指定了拷⻉的⻓度,源字符串不⼀定要有 \\0 ,同时在设计参数的时候,就会多⼀层思考,⽬标空间的⼤⼩是否够⽤, strncpy 相对 strcpy 函数更加安全。
char* my_strncpy(char* destination, const char* source, size_t num)
{
char* ret = destination;
while (num && (*destination++ = *source++))
{
num–;
}
while (num–)
{
*destination++ = '\\0';
}
return ret;
}
3.6 strncat
函数原型
char * strncat ( char * destination, const char * source, size_t num );
功能:字符串追加;将 source 指向的字符串的内容,追加到 destination 指向的空间,最多追加 num 个字符。
参数: destination :指针,指向了⽬标空间 source :指针,指向了源头数据 num :最多追加的字符的个数
返回值:返回的是⽬标空间的起始地址
代码演示
int main()
{
char arr1[20] = "hello";
char arr2[] = "world!";
strncat(arr1, arr2, 5);
printf("%s", arr1);
return 0;
}
strcat和strncat对比
参数不同, strncat 多了⼀个参数
strcat 函数在追加的时候要将源字符串的所有内容,包含 \\0 都追加过去,但是 strncat 函 数指定了追加的⻓度。
strncat 函数中源字符串中不⼀定要有 \\0 了。
strncat 更加灵活,也更加安全。
3.7 strncmp
函数原型
int strncmp ( const char * str1, const char * str2, size_t num );
功能:字符串⽐较;⽐较 str1 和 str2 指向的两个字符串的内容,最多⽐较 num 字符。
参数: str1 :指针,指向⼀个⽐较的字符串 str2 :指针,指向另外⼀个⽐较的字符串 num :最多⽐较的字符个数
代码演示
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcqw";
int ret1 = strncmp(arr1, arr2, 3);
printf("%d\\n", ret1);//0
int ret2 = strncmp(arr1, arr2, 4);
printf("%d\\n", ret2);//<0
return 0;
}
3.8 strstr
函数原型
char * strstr ( const char * str1, const char * str2);
功能: strstr 函数,查找 str2 指向的字符串在 str1 指向的字符串中第⼀次出现的位置。 简⽽⾔之:在⼀个字符串中查找⼦字符串。
参数: str1 :指针,指向了被查找的字符串,str2 :指针,指向了要查找的字符串
返回值:
如果str1指向的字符串中存在str2指向的字符串,那么返回第⼀次出现位置的指针
如果str1指向的字符串中不存在str2指向的字符串,那么返回NULL
代码演示
int main()
{
char str[] = "This is a simple string";
char* pch;
pch = strstr(str, "simple");
if (pch != NULL)
printf("%s\\n", pch);
else
printf("查找的字符串不存在\\n");
return 0;
}
运行结果

strstr的模拟实现
char* my_strstr(const char* str1, const char* str2)
{
const char* s1;
const char* s2;
const char* cp = str1;
while (*cp)
{
s1 = cp;
s2 = str2;
if (*str2 == '0')
return str1;
while (*s2!='\\0' && *s1 != '\\0' && * s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\\0')
{
return cp;
}
cp++;
}
return NULL;
}





