目录
在编程的过程中,我们经常要处理字符和字符串,为了方便操作字符和字符串,C语言标准库中提供了⼀系列库函数,接下来我们就学习⼀下这些函数。
1. 字符分类函数
C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使用都需要包含⼀个头文件是 ctype.h
这些函数的使用方法大相径庭,今天就举⼀个函数的例子,其他的非常类似:
islower 是能够判断参数部分的 c 是否是小写字母的。这个函数通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回 0。
接下来我们用小写字母转换为大写字母这个例子练一下手~
int main()
{
char ch1[] = "hello world";
char ch2[20] = { 0 };
int i = 0;
int len = strlen(ch1);
for (i = 0; i < len; i++)
{
if (islower(ch1[i])) // 判断是不是小写字符,若是则返回非0数,若不是则返回0
{
ch2[i] = ch1[i] - 32;// 小写字符比大写字符的ASCII值大32
}
else
{
ch2[i] = ch1[i];// 若不是小写字符则直接复制即可
}
}
ch2[i] = '\0';// 结尾添加'\0'保证结束
printf("%s\n", ch2);
return 0;
}
2. 字符转换函数
C语言提供了2个字符转换函数:
上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用 tolower 函 数。
我们改造一下:
#include <stdio.h>
#include<ctype.h>
int main()
{
char ch1[] = "hello world";
char ch2[20] = { 0 };
int i = 0;
int len = strlen(ch1);
for (i = 0; i < len; i++)
{
ch2[i] = toupper(ch1[i]);
}
ch2[i] = '\0';
printf("%s\n", ch2);
return 0;
}
3. strlen的使用和模拟实现
以下有几点注意事项:
1.字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
2.参数指向的字符串必须要以 '\0' 结束。
3.注意函数的返回值为size_t,是无符号的( 易错 )
4.strlen的使用需要包含头文件(string.h)
3.1 strlen的使用
#include <stdio.h>
#include<string.h>
int main()
{
const char* str1 = "abcdef";
const char* str2 = "bbb";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
嗯?怎么会是这个结果呢?明明是str1更长。大家可以思考一下原因。
其实问题就出在这条上。哈哈,大家是不是已经踩坑了。
所以我们得修改一下让它可以返回负数:
#include <stdio.h>
#include<string.h>
int main()
{
const char* str1 = "abcdef";
const char* str2 = "bbb";
if ((int)strlen(str2) - (int)strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
直接强制转换为整形,以保证有负数的返回。
现在就对了:
3.2 strlen的模拟实现
我列举了三种模拟实现的方法,代码如下:
3.2.1 计数器实现
int my_strlen1(char* c)// 计数器方式
{
assert(c);
int count = 0;
while (*c)
{
count++;
c++;
}
return count;
}
int main()
{
char ch[] = "hello world";
int ret1 = my_strlen1(ch);
printf("%d\n", ret1);
}
3.2.2 递归实现
int my_strlen2(char* c)// 递归
{
assert(c);
if (*c == '\0')
{
return 0;
}
else
{
return 1 + my_strlen2(c + 1);
}
}
int main()
{
char ch[] = "hello world";
int ret2 = my_strlen2(ch);
printf("%d\n", ret2);
}
3.2.3 指针偏移量实现
int my_strlen3(char* c)// 通过指针的偏移量进行判断
{
assert(c);
char* str = c;
while (*c)
{
c++;
}
return (c - str);
}
int main()
{
char ch[] = "hello world";
int ret3 = my_strlen3(ch);
printf("%d\n", ret3);
}
4. strcpy的使用和模拟实现
以下有几点注意事项:
1.源字符串必须以 '\0' 结束。
2. 会将源字符串中的 '\0' 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4. 目标空间必须可修改。
4.1 strcpy的使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "hello world";
char arr2[20] = { 0 };
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
上述代码实现的是通过strcpy这个函数将arr1中的字符拷贝到arr2上,可以看到我设置的arr2的空间大小是足够大的。
4.2 strcpy的模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* sorc)
{
char* ret = dest;
assert(dest && sorc);
while (*(dest++) = *(sorc++))
{
;
}
return ret;
}
int main()
{
char arr1[] = "hello world";
char arr2[20] = { 0 };
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
5. strcmp的使用和模拟实现
标准规定如下:
1.第⼀个字符串大于第二个字符串,则返回大于0的数字
2.第⼀个字符串等于第二个字符串,则返回0
3. 第⼀个字符串小于第二个字符串,则返回小于0的数字
4.那么如何判断两个字符串? 比较两个字符串中对应位置上字符ASCII码值的大小。
5.1 strcmp的使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "hello";
char arr2[] = "world";
int ret = strcmp(arr1, arr2);
if (ret > 0)
{
printf("arr1 > arr2\n");
}
else if (ret < 0)
{
printf("arr1 < arr2\n");
}
else
{
printf("arr1 = arr2\n");
}
return 0;
}
5.2 strcmp的模拟实现
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1++ == *str2++)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char arr1[] = "hello";
char arr2[] = "world";
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\n");
}
return 0;
}
6. strcat的使用和模拟实现
注意事项:
1.源字符串必须以 '\0' 结束。
2.目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。
3.目标空间必须有足够的大,能容纳下源字符串的内容。
4.目标空间必须可修改
6.1 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;
}
6.2 strcat的模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest)// 使其移到'\0'
{
*dest++;
}
while (*dest++ = *src++)// 复制
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello";
char arr2[] = " world";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
7. strncat函数的使用
注意事项:
1. 将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符。
2.如果source指向的字符串的长度小于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾。
7.1 strncat的使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "hello";
char arr2[] = " world";
strncat(arr1, arr2,6);
printf("%s\n", arr1);
return 0;
}
注:6是因为有个空格要算
7.2 strncat的模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strncat(char* dest, const char* src,size_t num)
{
assert(dest && src);
char* ret = dest;
while (*dest)// 使其移到'\0'
{
*dest++;
}
int i = 0;
for (i = 0; i < num; i++)// 根据指定长度进行复制
{
*dest++ = *(src + i);
}
*dest = '\0';// 结尾追加'\0'
return ret;
}
int main()
{
char arr1[20] = "hello";
char arr2[] = " world";
my_strncat(arr1, arr2, 6);
printf("%s\n", arr1);
return 0;
}
8. strncpy函数的使用和模拟实现
注意事项:
1. 拷贝num个字符从源字符串到目标空间
2.如果源字符串的长度小于num,则拷贝完源字符串之后,在⽬标的后边追加0,直到num个。
8.1 strncpy的使用
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "hello world";
char arr2[20] = { 0 };
strncpy(arr2, arr1,11);
printf("%s\n", arr2);
return 0;
}
8.2 strncpy的模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strncpy(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* ret = dest;
int i = 0;
for (i = 0; i < num; i++)
{
*dest++ = *(src + i);
}
dest = '\0';
return ret;
}
int main()
{
char arr1[] = "hello world";
char arr2[20] = { 0 };
my_strncpy(arr2, arr1, 11);
printf("%s\n", arr2);
return 0;
}
9. strncmp函数的使用
比较方法:
比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不一样,就提前结束,大的字符所在的字符串大于另外⼀个。如果num个字符都相等,就是相等返回0
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "hello world";
char arr2[] = "hello moon";
int ret = strncmp(arr1, arr2, 7);
if (ret < 0)
{
printf("arr1 < arr2\n");
}
else if (ret > 0)
{
printf("arr1 > arr2\n");
}
else
{
printf("arr1 = arr2\n");
}
return 0;
}
10. strstr的使用和模拟实现
注意事项:
1.函数返回字符串str2在字符串str1中第一次出现的位置
2.字符串的比较匹配不包含 \0 字符,以 \0 作为结束标志
10.1 strstr的使用
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "This is a simple string";
char* pch;
pch = strstr(str, "simple");
if (pch == NULL)
{
printf("这个字符不存在\n");
}
else
{
printf("%c\n", *pch);
}
return 0;
}
10.2 strstr的模拟实现
#include <stdio.h>
#include <assert.h>
const char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
if (*str2 == '\0')
{
return str1;
}
char* s1 = str1;
char* s2 = str2;
char* cp = str1;
while (*cp)
{
s1 = cp;
s2 = str2;
while (s1 != '\0' && s2 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char str[] = "This is a simple string";
char* pch;
pch = my_strstr(str, "simple");
if (pch == NULL)
{
printf("这个字符不存在\n");
}
else
{
printf("%c\n", *pch);
}
return 0;
}
11. strtok函数的使用
注意事项:
1.sep参数指向⼀个字符串,定义了用作分隔符的字符集合
2.第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标 记。
3. strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串⼀般都是临时拷贝的内容并且 可修改。)
4. strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。
5.strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标 记。
6. 如果字符串中不存在更多的标记,则返回 NULL 指针。
代码如下:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "192.168.6.111";
char* sep = ".";
char* str = NULL;
for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
return 0;
}
strtok(arr,sep)使用后,原字符串变成"192'\0'168'\0'6'\0'111 "。
strtok(arr,sep)会从'\0'位置开始向后标记。
12. strerror函数的使用
strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明 的,C语言程序启动的时候就会使用⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i = 0;
for (i = 0; i <= 10; i++) {
printf("%s\n", strerror(i));
}
return 0;
}
在Windows11+VS2022环境下输出的结果如下:
举例:
输出:
也可以了解⼀下perror函数,perror函数相当于⼀次将上述代码中的第9行完成了,直接将错误信息 打印出来。perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
输出:
到这里文章就结束咯,感谢大家的阅读~