字符函数和字符串函数

server/2024/11/29 17:40:23/

字符分类函数

C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。

这些函数的使用都需要包含⼀个头文件:ctype.h

这些函数的用法非常类似。

 int islower ( int c )

islower是能够判断参数部分是否是小写字母的。

通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0

练习:

写⼀个代码将字符串中的小写字母转大写,其他字符不变。

#include<stdio.h>
#include<ctype.h>
int main()
{char str[] = "Test String";int i = 0;while(str[i])//'\0'的ASCLL码为0//while (str[i] != '\0'){if (islower(str[i]))str[i] -= 32;//写法一:putcharputchar(str[i]);i++;}printf("\n");//写法二:%sprintf("%s", str);return 0;
}输出结果:
TEST STRING
TEST STRING

字符转换函数

C语⾔提供了2个字符转换函数,头文件为ctype.h

int tolower(int c);//将参数传进去的大写字母转小写字母
int toupper(int c);//将参数传进去的小写字母转大写字母

上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用转换函数。

#include<stdio.h>
#include<ctype.h>
int main()
{char str[] = "Test String";int i = 0;while (str[i]){if (islower(str[i]))str[i] = toupper(str[i]);putchar(str[i]);i++;}return 0;
}

strlen的使用和模拟实现

基本用法

strlen是C语言库函数,功能是求字符串长度

头文件为string.h

size_t strlen ( const char * str );
  • 统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数(不包含'\0')。
  • strlen函数会⼀直向后找\0字符,直到找到为止,所以可能存在越界查找

我们可以通过代码来理解:

#include<stdio.h>
#include<string.h>
int main()
{char arr1[] = "abc";char arr2[] = { 'a', 'b' , 'c' };char arr3[] = { 'a', 'b' , 'c' , '\0' };printf("%s\n%s\n%s\n", arr1, arr2, arr3);int len1 = strlen(arr1);int len2 = strlen(arr2);int len3 = strlen(arr3);printf("%d\n%d\n%d\n", len1, len2, len3);return 0;
}

运行结果为:

我们可以看到,字符串中有\0 和无\0的结果不同,这是因为arr2因为没有\0而打印没有停止,继续打印了一些随机值。

  • 函数的返回值为size_t,是无符号的。
#include<stdio.h>
#include<string.h>
int main()
{if (strlen("abc") - strlen("abcdef") > 0)printf(">");elseprintf("<");return 0;
}

输出结果为>

strlen的返回值为size_t类型,是无符号整型。

无符号整型 - 无符号整型,结果为无符号整型。

模拟实现

方法一

//计数器方式
size_t my_strlen(const char* str)
{assert(str);//assert(str != NULL);size_t count = 0;while (*str){count++;str++;}return count;
}
int main()
{char str[] = "Test String";size_t i = my_strlen(str);printf("%zd", i);return 0;
}

方法二

//指针 — 指针
#include<stdio.h>
#include<assert.h>size_t my_strlen(const char* str)
{assert(str);//assert(str != NULL);char* p = str;while (*str){str++;}return str - p;
}
int main()
{char str[] = "Test String";size_t i = my_strlen(str);printf("%zd", i);return 0;
}

方法三

//不创建临时变量——函数递归
#include<stdio.h>
#include<assert.h>size_t my_strlen(const char* str)
{assert(str);//assert(str != NULL);if (*str == '\0')return 0;elsereturn 1 + my_strlen(str + 1);
}
int main()
{char str[] = "Test String";size_t i = my_strlen(str);printf("%zd", i);return 0;
}

strcpy的使用和模拟实现

基本用法

strcpy是C语言库函数,功能是字符串的拷贝

头文件为string.h

char* strcpy(char * destination, const char * source );
  • Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
  • 源字符串必须以\0结束。
  • 会将源字符串中的’\0’拷贝到目标空间,拷贝至’\0’`结束。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可修改(常量字符串不能作为目标空间)。
  • strcpy的返回值为目标空间的起始地址(便于链式访问)。

:::

#include<stdio.h>
#include<string.h>int main()
{char arr1[20] = "abcdef";char arr2[20] = "ghijkl";strcpy(arr1, arr2);printf("%s", arr1);return 0;
}

模拟实现

#include<stdio.h>
#include<assert.h>char* my_strcpy (char* des, const char* sour)
{char* p = des;assert(des && sour);while (*des++ = *sour++)//=的返回值为所赋的值{;}//拷贝\0*des = *sour;return p;
}
int main()
{char arr1[20] = "abcdef";char arr2[20] = "ghijkl";my_strcpy(arr1, arr2);printf("%s", arr1);return 0;
}

strcat的使用和模拟实现

基本用法

strcat是C语言库函数,功能是追加字符串

头文件为string.h

char * strcat ( char * destination, const char * source );
  • Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.
  • 源字符串必须以’\0’结束。
  • 目标字符串中也得有’\0’,否则不知道从哪里开始追加。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 返回值为目标空间的地址。
  • 不适用于字符串自己给自己追加。
#include<stdio.h>
#include<string.h>int main()
{char arr1[20] = "hello ";char arr2[20] = "world!";strcat(arr1, arr2);printf("%s", arr1);return 0;
}

模拟实现

#include<stdio.h>
#include<assert.h>char* my_strcat(char* des, const char* sour)
{char* p = des;assert(des && sour);//找到'\0'while (*des){des++;}//追加字符串while (*des++ = *sour++){;}return p;
}int main()
{char arr1[20] = "hello ";char arr2[20] = "world!";my_strcat(arr1, arr2);printf("%s", arr1);return 0;
}

注意:strcat`不适用于字符串自己给自己追加。

#include<stdio.h>
#include<string.h>
#include<assert.h>char* my_strcat(char* des, const char* sour)
{char* p = des;assert(des && sour);while (*des){des++;}while (*des++ = *sour++){;}return p;
}int main()
{char arr1[20] = "abc";my_strcat(arr1, arr1);printf("%s", arr1);//陷入死循环//源字符串中的'\0'被破坏return 0;
}
#include<stdio.h>
#include<string.h>int main()
{char arr1[20] = "abc";strcat(arr1, arr1);printf("%s", arr1);//输出 abcabc//在VS中,strcat能够实现字符串自己给自己的追加return 0;
}

strcmp的使用和模拟实现

基本用法

strcmp是C语言库函数,功能是比较字符串

  • This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.
  • 比较的不是字符串的长度,而是对应位置 ASCLL 码值的大小。
  • 标准规定:
    • 第⼀个字符串大于第二个字符串,则返回大于0的数字
    • 第⼀个字符串等于第二个字符串,则返回0
    • 第⼀个字符串小于第二个字符串,则返回小于0的数字
#include<stdio.h>
#include<string.h>int main()
{int i = strcmp("abcde", "abq");printf("%d", i);//输出 -1return 0;
}
#include<stdio.h>
#include<string.h>int main()
{int r = strcmp("abcdef", "abq");if (r == 1)printf("字符串一大于字符串二");else if (r == 0)printf("字符串一等于字符串二");elseprintf("字符串一小于字符串二");return 0;
}这串代码正不正确?
在VS2022等部分编译器中,是正确的,因为这些编译器的返回值只为-1,1,0

模拟实现

方法一

//VS2022中的写法
#include<stdio.h>
#include<assert.h>int my_strcmp(const char* str1, const char* str2)
{while (*str1 == *str2){if (*str1 == '\0')return 0;str1++;str2++;}if (*str1 > *str2)return 1;elsereturn -1;
}
int main()
{int i = strcmp("abcde", "abq");printf("%d", i);return 0;
}

方法二

#include<stdio.h>
#include<assert.h>int my_strcmp(const char* str1, const char* str2)
{while (*str1 == *str2){if (*str1 == '\0')return 0;str1++;str2++;}return *str1 - *str2;
}
int main()
{int i = my_strcmp("abcde", "abq");printf("%d", i);return 0;
}

strncpy函数的使用

strncpy是C语言库函数,功能是字符串的拷贝

头文件为string.h

char * strncpy ( char * destination, const char * source, size_t num );
  • 拷贝 num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加\0,直到num个。
  • 返回值为目标空间的地址。
#include<stdio.h>
#include<string.h>int main()
{char str1[20] = "abcdef";char str2[20] = "ghi";strncpy(str1, str2, 5);printf("%s", str1);return 0;
}

strncat函数的使用

char * strncat ( char * destination, const char * source, size_t num );
  • 将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个\0字符
  • 如果source指向的字符串的长度小于num的时候,只会将字符串中到\0的内容追加到指向的字符串末尾。
  • 返回值为目标空间的地址。
#include<stdio.h>
#include<string.h>int main()
{char str1[20] = "abc";char str2[20] = "defghi";strncat(str1, str2, 3);printf("%s", str1);return 0;
}
#include<stdio.h>
#include<string.h>int main()
{char str1[20] = "xxx\0xxxxxx";char str2[20] = "abc";strncat(str1, str2, 6);printf("%s", str1);return 0;
}

注意:字符串给自身追加的操作用**strncat**更安全。

#include<stdio.h>
#include<string.h>int main()
{char str1[20] = "abcdefghi";size_t len = strlen(str1);strncat(str1, str1, len);printf("%s", str1);//输出 abcdefghiabcdefghireturn 0;
}

strncmp函数的使用

int strncmp ( const char * str1, const char * str2, size_t num );
  • 比较str1和>str2的前num个字符,如果相等就继续往后比较,**最多比较num<个字母,如果提前发现不⼀样,就提前结束,大的字符所在的字符串大于另外⼀个。如果字符都相等,就是相等返回0
  • 比较的不是字符串的长度,而是对应位置 ASCLL 码值的大小。
  • 标准规定:
    • 第⼀个字符串大于第二个字符串,则返回大于0的数字
    • 第⼀个字符串等于第二个字符串,则返回0
    • 第⼀个字符串小于第二个字符串,则返回小于0的数字
#include<stdio.h>
#include<string.h>int main()
{char str1[20] = "abcdefg";char str2[20] = "abcde";int i = strncmp(str1, str2, 7);printf("%d", i);//输出 0return 0;
}

strstr的使用和模拟实现

strstr是C语言库函数,功能是在字符串中查找子串

头文件为string.h

基本功能

char * strstr ( const char * str1, const char * str2);
  • Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. (函数返回字符串str2在字符串str1<中第⼀次出现的位置)。
  • The matching process does not include the terminating null-characters, but it stops there. (字符串的比较匹配不包含\0字符,以\0作为结束标志)。
#include<stdio.h>
#include<string.h>int main()
{char str1[20] = "abcdefabcdef";char str2[20] = "def";char* p = strstr(str1, str2);if (p == NULL)printf("找不到");elseprintf("找到了");return 0;
}

模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);//强制类型转换,更加规范char* p1 = (char*) str1;char* p2 = (char*) str2;if (!*str2/* *str2 == '\0' */)return (char*)str1;while (*p1){//多次匹配保留起始位置char* s1 = p1;char* s2 = p2;while (*s1 && *s2 && !(*s1 - *s2)/* *s1 == *s2 */){s1++;s2++;}if (!*s2)return p1;p1++;}return NULL;
}int main()
{char str1[20] = "abcdefabcdef";char str2[20] = "def";char* p = my_strstr(str1, str2);if (p == NULL)printf("找不到\n");else{printf("找到了\n");printf("%s", p);}return 0;
}

strtok函数的使用

char * strtok ( char * str, const char * sep);

● sep参数指向⼀个字符串,定义了用作分隔符的字符集合
● str参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标记。
● strtok函数找到str中的下⼀个标记,并将其用\0结尾,返回⼀个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串⼀般都是临时拷贝的内容并且可修改。)
● strtok函数的第⼀个参数不为NULL,strtok函数将保存它在字符串中的位置。
● strtok函数的第⼀个参数为NULL,函数将在同⼀个字符串中被保存的位置(存放于一个静态变量中)开始,查找下⼀个标记。
● 如果字符串中不存在更多的标记,则返回NULL指针。

#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "zpw@bitedu.net";const char arr2[] = "@.";char* p = strtok(arr1, arr2);printf("%s\n", arr1);//输出 zpwprintf("%s\n", p);//输出 zpwreturn 0;
}
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "zpw@bitedu.net";const char arr2[] = "@.";char* r = NULL; char* p1 = strtok(arr1, arr2);char* p2 = strtok(r, arr2);printf("%s\n", p1);//输出 zpwprintf("%s\n", p2);//输出 biteedureturn 0;
}

strerror函数的使用

基本用法

char * strerror ( int errnum );

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来,头文件为string.h。
在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在errno.h这个头文件中说明的,C语言程序启动的时候就会使用⼀个全面的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会讲对应的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。

#include<stdio.h>
#include<string.h>
#include<errno.h>int main()
{int i = 0;for (i = 0; i <= 10; i++){printf("%d:%s\n", i, strerror(i));}return 0;

vs2022 + windows11环境下,输出结果为:

0:No error
1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted function call
5:Input/output error
6:No such device or address
7:Arg list too long
8:Exec format error
9:Bad file descriptor
10:No child processes
#include<stdio.h>
#include<string.h>
#include<errno.h>int main()
{FILE* pf = fopen("test.txt", "r");//以读的形式打开文件if (pf == NULL){//打开文件失败printf("错误信息是:%s\n", strerror(errno));//输出 错误信息是: No such file or directory}return 0;
}

perror函数的使用

void perror(const char* str);
#include<stdio.h>
#include<string.h>
#include<errno.h>int main()
{FILE* pf = fopen("test.txt", "r");//以读的形式打开文件if (pf == NULL){//打开文件失败perror("错误信息是");//输出 错误信息是: No such file or directory//在括号中加字符串时,会自动添加':'和' 'printf("错误信息是: %s\n", strerror(errno));//输出 错误信息是: No such file or directory}return 0;
}

http://www.ppmy.cn/server/145951.html

相关文章

虚幻引擎---目录结构篇

一、引擎目录 成功安装引擎后&#xff0c;在安装路径下的Epic Games目录中可以找到与引擎版本对应的文件夹&#xff0c;其中的内容如下&#xff1a; Engine&#xff1a;包含构成引擎的所有源代码、内容等。 Binaries&#xff1a;包含可执行文件或编译期间创建的其他文件。Bui…

torch.is_nonzero(input)

torch.is_nonzero(input) input: 输入张量 若输入是 不等于零的单元素张量 则返回True&#xff0c;否则返回False 不等于零的单元素张量&#xff1a;torch.tensor([0.]) 或 torch.tensor([0]) 或 torch.tensor([False])单元素张量: 只有一个数 的张量 import torch print(t…

【插入排序】:直接插入排序、二分插入排序、shell排序

【插入排序】&#xff1a;直接插入排序、二分插入排序、shell排序 1. 直接插入排序1.1 详细过程1.2 代码实现 2. 二分插入排序2.1 详细过程2.2 代码实现 3. shell排序3.1 详细过程3.2 代码实现 1. 直接插入排序 1.1 详细过程 1.2 代码实现 public static void swap(int[]arr,…

Vue源码巧妙设计

Vue.js的源码中蕴含了许多巧妙的设计&#xff0c;这些设计使得Vue成为一个高效、灵活且易于使用的前端框架。以下是对Vue源码中一些巧妙设计的详细讲解&#xff1a; 1. 响应式系统 Vue的响应式系统是其核心特性之一&#xff0c;它允许Vue追踪数据的变化&#xff0c;并在数据变…

MySql之MVVC总结

多版本并发控制MVVC&#xff0c;Multi-Version Concurrency Control,通过数据行的多个版本来控制数据库的并发。mysql只有InnoDB引擎才支持MVVC. 通过管理每条记录的多个版本&#xff0c;实现数据库事务并发时一致性读&#xff0c;当前事务A读取正在被其他事务B更新的数据行时…

使用 Canal 实时从 MySql 向其它库同步数据

目前绝大多数项目还是采用 mysql 作为数据存储&#xff0c;对于用户访问量较高的网站来说&#xff0c;mysql 读写性能有限&#xff0c;我们通常会把 mysql 中的数据实时同步到 Redis、mongodb、elastic search 等中间件中&#xff0c;应对高并发访问场景&#xff0c;减轻 mysql…

知识图谱嵌入评估的常用任务

知识图谱嵌入&#xff08;KGE&#xff09;是通过将图中的实体和关系表示为低维向量&#xff0c;从而使得原本复杂的图结构可以被机器学习模型处理&#xff0c;并用于后续任务。有效的评估方法能够帮助研究者和工程师了解模型在不同任务中的表现&#xff0c;并优化模型以提升其在…

卷积神经网络:图像特征提取与分类的全面指南

目录 引言 卷积层&#xff1a;图像特征的初步提取 局部连接与权重共享 多个卷积核与特征图 激活函数 池化层&#xff1a;降低维度与增强不变性 最大池化与平均池化 空间不变性 全连接层&#xff1a;特征整合与分类决策 特征整合 分类器 Dropout与正则化 训练与优化…