字符函数和字符串函数

目录

[1. 字符分类函数](#1. 字符分类函数)

[2 字符转换函数](#2 字符转换函数)

2个字符转换函数:

[3 strlen](#3 strlen)

[3.1 代码演示](#3.1 代码演示)

[3.3 strlen的模拟实现](#3.3 strlen的模拟实现)

[4 strcpy](#4 strcpy)

[4.1 代码演示](#4.1 代码演示)

[4.2 模拟实现](#4.2 模拟实现)

[5 strcat](#5 strcat)

[5.1 代码演示](#5.1 代码演示)

[5.2 模拟实现](#5.2 模拟实现)

[6 strcmp](#6 strcmp)

[6.1 代码演示](#6.1 代码演示)

​编辑

[6.2 模拟实现:](#6.2 模拟实现:)

[7. strncpy](#7. strncpy)

[7.1 代码演示](#7.1 代码演示)

[7.2 ⽐较strcpy和strncpy函数](#7.2 ⽐较strcpy和strncpy函数)

[8 strncat](#8 strncat)

[8.1 代码演示](#8.1 代码演示)

[8.2 strcat和strncat对⽐](#8.2 strcat和strncat对⽐)

9.1代码演示

[9.2 strcmp和strncmp⽐较](#9.2 strcmp和strncmp⽐较)

[10 strstr](#10 strstr)

10.1代码演示

[10.2 strstr的模拟实现](#10.2 strstr的模拟实现)

[11. strtok函数的使用](#11. strtok函数的使用)

[11.1 代码演示](#11.1 代码演示)

[11.2 注意事项](#11.2 注意事项)

[12 strerror函数的使用](#12 strerror函数的使用)

[12.1 代码演示](#12.1 代码演示)

[12.2 perror](#12.2 perror)


1. 字符分类函数

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


的使⽤⽅法:
int islower ( int c );

islower 是能够判断参数部分的 c 是否是⼩写字⺟的。
通过返回值来说明是否是⼩写字⺟,如果是⼩写字⺟就返回⾮0的整数,如果不是⼩写字⺟,则返回0。

练习:
int main()
{
//写一个代码,将字符串中的小写字母转大写,其他字符不变。
char arr[] = "I Am a Chinese.";//'\0' - 0
// 0123...
//将字符串中的字符逐个进行处理
//遇到小写,转换成大写,再输出
//如果不是小写,正常输出
int i = 0;
while (arr[i])
{
if (islower(arr[i]))
arr[i] -= 32;
printf("%c", arr[i]);
i++;
}
return 0;
}

2 字符转换函数

2个字符转换函数:

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

上⾯的代码,我们将⼩写转⼤写,是-32完成的效果,有了转换函数,就可以直接使⽤ tolower 函数。
int main()

{

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

char arr[] = "I Am a Chinese.";//'\0' - 0

// 0123...

//将字符串中的字符逐个进行处理

//遇到小写,转换成大写,再输出

//如果不是小写,正常输出

int i = 0;

while (arr[i])

{

if (islower(arr[i]))

arr[i] = toupper(arr[i]);

printf("%c", arr[i]);

i++;

}

return 0;

}

3 strlen

size_t strlen ( const char * str );
**功能:**统计参数 str 指向的字符串的⻓度。统计的是字符串中 '\0' 之前的字符的个数。
参数: str :指针,指向了要统计⻓度的字符串。
**返回值:**返回了 str 指向的字符串的⻓度,返回的⻓度不会是负数,所以返回类型是 size_t 。

3.1 代码演示

#include <string.h>

int main()

{

const char* str = "abcdef";

printf("%zd\n", strlen(str));

}

使⽤注意事项:

①字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不 包含 '\0' )。
② 参数指向的字符串必须要以 '\0' 结束。
③ 注意函数的返回值为 size_t ,是⽆符号的( 易错 )
④ strlen的使⽤需要包含头⽂件 <string.h>
3.2 strlen 返回值
#include <string.h>

int main()

{

if (strlen("abc") - strlen("abcdef") > 0)

{

printf(">\n");

}

else

{

printf("<=\n");

}

return 0;

}

size_t 无符号的整型 >= 0

3.3 strlen的模拟实现

1,计时器

2,指针 - 指针

不能在函数内部创建临时变量,使用递归

3,递归

#include <assert.h>

size_t my_strlen(const char* str)

{

assert(str);

if (*str != '\0')

return 1 + my_strlen(str+1);

else

return 0;

}

int main()

{

char arr[] = "abc";

size_t len = my_strlen(arr);

printf("%zu\n", len);

return 0;

}


4 strcpy

代码块
char * strcpy ( char * destination, const char * source );
**功能:**字符串拷⻉,拷⻉到源头字符串中的 \0 为⽌
参数:
destination :指针,指向⽬的地空间
source :指针,指向源头数据
返回值:
strcpy 函数返回的⽬标空间的起始地址

4.1 代码演示

#include <string.h>

int main()

{

char arr1[] = "hello world";

char arr2[20] = { 0 };

char* ret = strcpy(arr2, arr1);

printf("%s\n", arr2);

printf("%s\n", ret);

//arr2 = arr1;//ok?

//因为数组名是地址,地址是一个编号,地址是常量值,不能被修改

//5 = 3;

//地址是指向空间的,但是地址不是空间

return 0;

}


使⽤注意事项:

①源字符串必须以 '\0' 结束。
②会将源字符串中的 '\0' 拷⻉到⽬标空间。
③⽬标空间必须⾜够⼤,以确保能存放源字符串。
④⽬标空间必须可修改。

4.2 模拟实现

代码1:

void my_strcpy(char* dest, char* src)
{
//拷贝\0前面的字符
while (*src != '\0')
{
*dest = *src;
src++;
dest++;
}
*dest = *src;//拷贝\0
}
int main()
{
char arr1[] = "hello world";
char arr2[20] = "xxxxxxxxxxxxxxx";
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}

代码2:

void my_strcpy(char* dest, const char* src)

{

while (*dest++ = *src++)

{

;

}

}

int main()

{

char arr1[] = "hello world";

char arr2[20] = "xxxxxxxxxxxxxxx";

my_strcpy(arr2, arr1);

printf("%s\n", arr2);

return 0;

}

代码3:模拟实现

#include <assert.h>

char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(dest && src);
while (*dest++ = *src++)
{
;
}
return ret;//返回目标空间的起始地址
}

int main()
{
char arr1[] = "hello world";
char arr2[20] = "xxxxxxxxxxxxxxx";
char* r = my_strcpy(arr2, arr1);
printf("%s\n", arr2);
printf("%s\n", r);

return 0;
}

5 strcat

代码块
char * strcat ( char * destination, const char * source );
**功能:**字符串追加,把 source 指向的源字符串中的所有字符都追加到 destination 指向的空间
中。
参数:
destination :指针,指向⽬的地空间
source :指针,指向源头数据
返回值:
strcat 函数返回的⽬标空间的起始地址

5.1 代码演示

#include <string.h>

int main()

{

char arr1[20] = "hello\0xxxxxxxxxx";

char arr2[] = "world";

char* r = strcat(arr1, arr2);

printf("%s\n", arr1);

printf("%s\n", r);

return 0;

}


使⽤注意事项:

源字符串必须以 '\0' 结束。
⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。
⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。
⽬标空间必须可修改。

5.2 模拟实现

#include <assert.h>

char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest && src);
//1. 目标空间的\0
while (*dest != '\0')
dest++;
//2. 拷贝
while (*dest++ = *src++)
{
;
}
return ret;
}

int main()
{
char arr1[20] = "hello\0xxxxxxxxxx";
char arr2[] = "world";
char* r = my_strcat(arr1, arr2);

printf("%s\n", arr1);
printf("%s\n", r);

return 0;
}

6 strcmp

代码块
int strcmp ( const char * str1, const char * str2 );
功能:⽤来⽐较 str1 和 str2 指向的字符串,从两个字符串的第⼀个字符开始⽐较,如果两个字符
的ASCII码值相等,就⽐较下⼀个字符。直到遇到不相等的两个字符,或者字符串结束。
参数:
str1 :指针,指向要⽐较的第⼀个字符串
str2 :指针,指向要⽐较的第⼆个字符串
返回值:
标准规定:
第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字
第⼀个字符串等于第⼆个字符串,则返回0
第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字

6.1 代码演示

代码1:

#include <stdio.h>

#include <string.h>

int main()

{

char arr1[] = "abcdef";

char arr2[] = "abc";

int r = strcmp(arr1, arr2);

if (r > 0)

printf("arr1 > arr2\n");

else if(r < 0)

printf("arr1 < arr2\n");

else

printf("arr1 == arr2\n");

return 0;

}

代码2:

int main()

{

int r = strcmp("abcdef", "abc");

if (r > 0)

printf(">\n");

else if (r < 0)

printf("<\n");

else

printf("==\n");

return 0;

}

6.2 模拟实现:

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

}

if (*str1 > *str2)

return 1;

else

return -1;

}

int main()

{

char arr1[] = "abc";

char arr2[] = "abcdef";

int r = my_strcmp(arr1, arr2);

if (r > 0)

printf("arr1 > arr2\n");

else if(r < 0)

printf("arr1 < arr2\n");

else

printf("arr1 == arr2\n");

return 0;

}


7. strncpy

代码块
char * strncpy ( char * destination, const char * source, size_t num );
**功能:**字符串拷⻉;将 source 指向的字符串拷⻉到 destination 指向的空间中,最多拷⻉ num
个字符。
参数:
destination :指针,指向⽬的地空间
source :指针,指向源头数据
num :从source指向的字符串中最多拷⻉的字符个数
返回值:
strncpy 函数返回的⽬标空间的起始地址

7.1 代码演示

7.2 ⽐较strcpy和strncpy函数

①strcpy 函数拷⻉到 \0 为⽌,如果⽬标空间不够的话,容易出现越界⾏为。

②strncpy 函数指定了拷⻉的⻓度,源字符串不⼀定要有 \0 ,同时在设计参数的时候,就会多⼀层
③思考:⽬标空间的⼤⼩是否够⽤, strncpy 相对 strcpy 函数更加安全。

8 strncat

代码块
char * strncat ( char * destination, const char * source, size_t num );
**功能:**字符串追加;将 source 指向的字符串的内容,追加到 destination 指向的空间,最多追
加 num 个字符。
参数:
destination :指针,指向了⽬标空间
source :指针,指向了源头数据
num :最多追加的字符的个数
**返回值:**返回的是⽬标空间的起始地址

8.1 代码演示

8.2 strcat和strncat对⽐

①参数不同, strncat 多了⼀个参数
②strcat 函数在追加的时候要将源字符串的所有内容,包含 \0 都追加过去,但是 strncat 函
数指定了追加的⻓度。
③strncat 函数中源字符串中不⼀定要有 \0 了。
④strncat 更加灵活,也更加安全。

9 strncmp

代码块
int strncmp ( const char * str1, const char * str2, size_t num );
**功能:**字符串⽐较;⽐较 str1 和 str2 指向的两个字符串的内容,最多⽐较 num 字符。
参数:
str1 :指针,指向⼀个⽐较的字符串
str2 :指针,指向另外⼀个⽐较的字符串
num :最多⽐较的字符个数
返回值:
标准规定:
第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字
第⼀个字符串等于第⼆个字符串,则返回0
第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字

9.1代码演示

int main()

{

char arr1[10] = "abcqw";

char arr2[20] = "abcdef";

int r = strncmp(arr2, arr1, 3);

if (r > 0)

printf(">\n");

else if(r < 0)

printf("<\n");

else

printf("==\n");

return 0;

}

9.2 strcmp和strncmp⽐较

①参数不同
②strncmp可以⽐较任意⻓度了
③strncmp函数更加灵活,更加安全

10 strstr

代码块
char * strstr ( const char * str1, const char * str2);
功能:
strstr 函数,查找 str2 指向的字符串在 str1 指向的字符串中第⼀次出现的位置。
简⽽⾔之:在⼀个字符串中查找⼦字符串。
strstr 的使⽤得包含<string.h>
参数:
str1 :指针,指向了被查找的字符串
str2 :指针,指向了要查找的字符串
返回值:
如果str1指向的字符串中存在str2指向的字符串,那么返回第⼀次出现位置的指针
如果str1指向的字符串中不存在str2指向的字符串,那么返回NULL

10.1代码演示

int main()

{

char arr1[] = "heheabcdefabcdef";

char arr2[] = "deq";

char* p = strstr(arr1, arr2);

if (p != NULL)

{

printf("找到了, %s\n", p);

}

else

{

printf("找不到\n");

}

return 0;

}

10.2 strstr的模拟实现

char* my_strstr(const char* str1, const char* str2)

{

assert(str1 && str2);

const char* p = str1;

const char* s1 = NULL;

const char* s2 = NULL;

//特殊的场景的处理

if (*str2 == '\0')

return (char*)str1;

while (*p) //枚举查找的次数

{

s1 = p;

s2 = str2;

//找一次的匹配过程

while (*s1 && *s2 && *s1 == *s2)

{

s1++;

s2++;

}

if (*s2 == '\0')

return (char*)p;

p++;

}

return NULL;

}

int main()

{

/*char arr1[] = "heheabcdefabcdef";

char arr2[] = "deq";*/

char arr1[] = "abbbcdef";

char arr2[] = "bbc";

char* p = my_strstr(arr1, arr2);

if (p != NULL)

{

printf("找到了, %s\n", p);

}

else

{

printf("找不到\n");

}

return 0;

}

11. strtok函数的使用

代码块
char * strtok ( char *str, const char *delim);
功能:
分割字符串:根据 delim 参数中指定的分隔符,将输⼊字符串 str 拆分成多个⼦字符串。
修改原始字符串: strtok 会直接在原始字符串中插⼊ '\0' 终⽌符,替换分隔符的位置,因
此原始字符串会被修改。
参数:

  1. str :⾸次调⽤时传⼊待分割的字符串;后续调⽤传⼊ NULL ,表⽰继续分割同⼀个字符串。
  2. delim :包含所有可能分隔符的字符串(每个字符均视为独⽴的分隔符)。
    返回值:
    成功时返回指向当前⼦字符串的指针。
    没有更多⼦字符串时返回 NULL 。
    使⽤步骤:
  3. ⾸次调⽤:传⼊待分割字符串和分隔符。
  4. 后续调⽤:传⼊ NULL 和相同的分隔符,继续分割。
  5. 结束条件:当返回 NULL 时,表⽰分割完成。

11.1 代码演示

int main()

{

char arr[] = "zpengwei@@yeah.net.hehe.haha@heihei";

char sep[] = "@.";

char buf[200] = { 0 };

strcpy(buf, arr);

char* p = NULL;

for (p = strtok(buf, sep); p != NULL; p = strtok(NULL, sep))

{

printf("%s\n", p);

}

//buf

//zpengwei\0yeah\0net

//char*p = strtok(buf, sep);

//printf("%s\n", p);//zpengwei

//p = strtok(NULL, sep);//yeah

//printf("%s\n", p);

//p = strtok(NULL, sep);//net

//printf("%s\n", p);

//p = strtok(NULL, sep);//返回NULL

//printf("%s\n", p);//(null)

return 0;

}

11.2 注意事项

破坏性操作: strtok 会直接修改原始字符串,将其中的分隔符替换为 '\0' 。如果需要保留 原字符串,应先拷⻉⼀份。
**连续分隔符:**多个连续的分隔符会被视为单个分隔符,不会返回空字符串。

**空指针处理:**如果输⼊的 str 为 NULL 且没有前序调⽤,⾏为未定义。

12 strerror函数的使用

char * strerror ( int errnum );
功能:

  1. strerror 函数可以通过参数部分的 errnum 表⽰错误码,得到对应的错误信息,并且返回这
    个错误信息字符串⾸字符的地址。
  2. strerror 函数只针对标准库中的函数发⽣错误后设置的错误码的转换。
  1. strerror 的使⽤需要包含<string.h>
    参数:

errnum :表⽰错误码
包含⼀个头⽂件 errno.h 。
返回值:
函数返回通过错误码得到的错误信息字符串的⾸字符的地址。

12.1 代码演示

int main()

{

int i = 0;

for (i = 0; i < 10; i++)

{

printf("%d: %s\n", i, strerror(i));

}

return 0;

}

举例:

#include <errno.h>

int main()

{

//C语言可以打开文件

//fopen

//如果以读的形式打开文件,文件是必须要存在的,如果文件不存在,则打开文件失败

//fopen函数就会将错误码放在errno

//同时函数会返回NULL

FILE* pf = fopen("data.txt", "r");

if (pf == NULL)

{

printf("%s\n", strerror(errno));

return 1;

}

//读文件

//关闭文件

fclose(pf);

pf = NULL;

return 0;

}

12.2 perror

也可以了解⼀下 perror 函数, perror 函数相当于⼀次将上述代码中的
printf("%s\n", strerror(errno)); 完成了,直接将错误信息打印出来。
perror 函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
int main()

{

//C语言可以打开文件

//fopen

//如果以读的形式打开文件,文件是必须要存在的,如果文件不存在,则打开文件失败

//fopen函数就会将错误码放在errno

//同时函数会返回NULL

FILE* pf = fopen("data.txt", "r");

if (pf == NULL)

{

perror("test");

//test: 错误信息

return 1;

}

//读文件

//关闭文件

fclose(pf);

pf = NULL;

return 0;

}

相关推荐
冲帕Chompa21 分钟前
图论part10 bellman_ford算法
数据结构·算法·图论
緈福的街口24 分钟前
【leetcode】144. 二叉树的前序遍历
算法·leetcode
GG不是gg29 分钟前
排序算法之基础排序:冒泡,选择,插入排序详解
数据结构·算法·青少年编程·排序算法
随意起个昵称1 小时前
【双指针】供暖器
算法
倒霉蛋小马1 小时前
最小二乘法拟合直线,用线性回归法、梯度下降法实现
算法·最小二乘法·直线
codists1 小时前
《算法导论(第4版)》阅读笔记:p82-p82
算法
埃菲尔铁塔_CV算法1 小时前
深度学习驱动下的目标检测技术:原理、算法与应用创新
深度学习·算法·目标检测
float_com2 小时前
【背包dp-----分组背包】------(标准的分组背包【可以不装满的 最大价值】)
算法·动态规划
丶Darling.3 小时前
Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先
数据结构·c++·算法·二叉树
思茂信息3 小时前
CST软件对OPERA&CST软件联合仿真汽车无线充电站对人体的影响
c语言·开发语言·人工智能·matlab·汽车·软件构建