C语言字符(串)函数

简介: C语言字符(串)函数

在我们写代码的过程中呢,经常会遇到一些处理字符和字符串的问题,比如将大小写字母的转换,计算字符串长度等,为了方便操作这些字符和字符串,C语言标准库提供了一些库函数,接下来就学习一下这些字符和字符串函数

一、字符函数

       <1>字符分类函数

C语言中有专门对字符进行分类操作的函数,简单来说就是判断一个字符是属于什么类型的,这些函数的使用需要头文件 ctype.h

函数具体如下:

这些函数使用起来非常相似,这里使用一个islower函数,

int islower ( int c );

islower  是能够判断参数c是否为小写字母的;

如果是就返回一个非0的整数,如果不是就返回0。

接下来,具体使用一下:写一个代码,将字符串中的小写字母转换成大写,其他字符不变。l

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

 <2>字符转换函数

字符串中字母的大小写转换,我们可以像上面那样减去32(字母大小写ASCII值相差32),当然我们也可以使用这里的字符转换函数。

C语言当中提供了2个字符转换函数:

int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写 
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写

知道有这样的大小写转换的函数,我们代码就可一这样去写:

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

二、字符串函数

要去了解一个函数呢,我们就要先知道这个函数的类型和作用,参数,返回值等。

使用字符串函数,需要包含头文件 string.h

       <1>strlen使用与模拟实现

strlen函数是用来求字符串长度的,函数类型:

size_t strlen ( const char * str );

使用注意

  • 字符串是以'\0'为结束标志,strlen在统计字符串长度时,统计的时'\0'之前的字符个数(不包含'\0')
  • 函数参数所指向的字符串必须以'\0'结束
  • 函数的返回值类型是size_t,是无符号的

strlen使用

使用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;
}

strlen模拟实现

为了更好的了解,我们这里自己写一个函数来代替strlen:

//方法一
//计数器⽅式
int my_strlen(const char * str)
{
 int count = 0;
 assert(str);
 while(*str)
 {
 count++;
 str++;
 }
 return count;
}
 
//方法二
//不能创建临时变量计数器
int my_strlen(const char * str)
{
 assert(str);
 if(*str == '\0')
 return 0;
 else
 return 1+my_strlen(str+1);
}
 
//方法三
//指针-指针的⽅式
int my_strlen(char *s)
{
 assert(str);
 char *p = s;
 while(*p != ‘\0’ )
 p++;
 return p-s;
}

       <2>strcpy使用与模拟实现

函数类型:

char* strcpy(char * destination, const char * source );

strcpy是字符串拷贝函数,将source所指向的字符串(源字符串)拷贝到destination所指向的字符串(或目标空间)当中去。

使用注意:

  • 源字符串必须以'\0'结束
  • strcpy在拷贝过程中,会将源字符串中'\0'一起拷贝到目标空间
  • 目标空间必须足够大,确保能够存放源字符串
  • 目标内空间须可以修改
  • strcpy函数会返回目标空间的起始地址,便于链式访问

strcpy使用

int main() {
  char str1[] = "hello world";
  char str2[50] = { 0 };//目标空间足够大
  strcpy(str2, str1);
  printf(str2);
  return 0;
}

strcpy模拟实现

char* my_strcpy(char *dest, const char*src)
{ 
    char *ret = dest;
    assert(dest != NULL);
    assert(src != NULL); 
    while((*dest++ = *src++))
    {
        ;
    }
    return ret;
}

       <3>strcat使用与模拟实现

函数类型:

char* strcat(char* dest,const char* src)

strcat函数是字符串连接,可以将src所指向的字符串内容连接到dest所指向的字符串后面。

返回值:是dest的起始地址  

使用注意:

  • dest和src字符串必须’\0’结束
  • 目标空间必须可修改(前面不能加const并且不能说常量字符串)
  • dest最后的结束字符’\0’会被覆盖掉,并在连接后的字符串的尾部再增加一个’\0’
  • dest与src所指的内存空间不能重叠
  • dest要有足够的空间来容纳要复制的字符串。
  • 字符串不可以连接字符串本身:自己连接自己就会覆盖\0,这样就会死循环

strcat使用:

int main() {
  char str1[50] = "hello ";
  char str2[] = "world";
  char* ret = strcat(str1, str2);
  printf(ret);
  return 0;
}

strcat模拟实现

char *my_strcat(char *dest, const char*src)
{
     char *ret = dest;
     assert(dest != NULL);
     assert(src != NULL);
     while(*dest)
     {
         dest++;
     }
     while((*dest++ = *src++))
     {
         ;
     }
     return ret;
}

<4>strcmp使用与模拟实现

函数类型:

int my_strcmp (const char * str1, const char * str2)

strcmp函数比较两个字符串的大小,使用这个函数就要知道:

  1. 第⼀个字符串大于第⼆个字符串,则返回大于0的数字
  2. 第⼀个字符串等于第⼆个字符串,则返回0
  3. 第⼀个字符串小于第⼆个字符串,则返回小于0的数字
  4. 那么如何判断两个字符串? ⽐较两个字符串中对应位置上字符ASCII码值的大小

strcmp使用

int main() {
  char str1[] = "abcdef";
  char str2[] = "abcdef";
  char str3[] = "abc";
  char str4[] = "abddef";
  int ret1 = strcmp(str1, str2);
  int ret2 = strcmp(str1, str3);
  int ret3 = strcmp(str1, str4);
  printf("%d\n%d\n%d", ret1, ret2, ret3);
  return 0;
}

strcmp模拟实现

int my_strcmp (const char * str1, const char * str2)
{
 int ret = 0 ;
 assert(str1 != NULL);
 assert(str2 != NULL);
 while(*str1 == *str2)
 {
 if(*str1 == '\0')
 return 0;
 str1++;
 str2++;
 }
 return *str1-*str2;
}

<5>strstr使用与模拟实现

函数类型:

char * strstr ( const char * str1, const char * str2);

strstr函数是在str1指向的字符串中查找str2所指向的字符串

如果能找到就返回字符串str2在str1中第一次出现的位置(地址)

如果没有找到,就返回空指针(NULL)

strstr使用

#include <stdio.h>
#include <string.h>
int main ()
{
 char str[] ="This is a simple string";
 char * pch;
 pch = strstr (str,"simple");
 strncpy (pch,"sample",6);
 printf("%s\n", str);
 return 0;
}

strstr模拟实现

char * strstr (const char * str1, const char * str2)
{
 char *cp = (char *) str1;
 char *s1, *s2;
 if ( !*str2 )
 return((char *)str1);
 while (*cp)
 {
 s1 = cp;
 s2 = (char *) str2;
 while ( *s1 && *s2 && !(*s1-*s2) )
 s1++, s2++;
 if (!*s2)
 return(cp);
 cp++;
 }
 return(NULL);
}

<6>strncpy 、strncat 、strncmp

strncpy相比于strcpy,通过观察两个函数类型,可以发现多了一个参数,

//strcpy
char* strcpy(char * destination, const char * source );
//strncpy
char * strncpy ( char * destination, const char * source, size_t num );

在使用的过程中

strcpy是将source指向的字符串全部拷贝过去,而strncpy只拷贝num个。

了解了strcpy与strncpy、其实strcat与strncat、strcmp与strncmp其实都只是差了一个size_t的参数,这个参数呢,就决定了函数要操作字符串里字符的个数。

<7>strtok

函数类型:

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

strtok函数是在str字符串中,寻找sep中字符串的内容,找到并将其修改成'\0'并记录位置

使用说明:

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

<8>strerror  

函数类型:

char * strerror ( int errnum );

strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。

知识补充:

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

这里输出一下0--10的错误信息

#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;
}

这里简单使用一下,会涉及到文件操作方面的知识

 

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
  FILE* pFile; //定义文件指针变量
  pFile = fopen("unexist.ent", "r"); //以只读的方式打开文件,unexist.ent
  if (pFile == NULL) //文件打开失败,fopen才会返回空指针
    printf("Error opening file unexist.ent: %s\n", strerror(errno)); //输出错误信息
  return 0;
}

文件打开失败,strerror把参数部分对应的错误信息的地址返回,printf输出错误信息。

在这里也可以使用perror函数来输出错误信息,作用直接输出错误信息

所以代码也可以这样写

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
 FILE * pFile;
 pFile = fopen ("unexist.ent","r");
 if (pFile == NULL)
 perror("Error opening file unexist.ent");
 return 0;
}

perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。

相关文章
|
24天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
16天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
20天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2577 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
18天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
3天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
2天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
164 2
|
20天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1576 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
22天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
979 14
|
4天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
221 2
|
17天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
735 9