当前位置: 首页 > article >正文

C语言之字符函数和字符串函数(下)

欢迎拜访:雾里看山-CSDN博客
本篇主题:C语言之字符函数和字符串函数(下)
发布时间:2025.1.19
隶属专栏:C语言

在这里插入图片描述

目录

  • 字符串查找
    • strstr
      • 函数介绍
      • 函数使用
    • strtok
      • 函数介绍
      • 函数使用
  • 错误信息报告
    • strerror
      • 函数介绍
      • 函数使用
  • 字符操作
    • 字符分类函数
      • 函数介绍
      • 函数使用
    • 字符转换函数
      • 函数介绍
      • 函数使用
  • 内存操作
    • memcpy
      • 函数介绍
      • 函数使用
      • 函数实现
    • memmove
      • 函数介绍
      • 函数使用
      • 函数实现
    • memset
      • 函数介绍
      • 函数使用
      • 函数实现
    • memcmp
      • 函数介绍
      • 函数使用
      • 函数实现

字符串查找

strstr

函数介绍

strstr
函数格式char *strstr (char *str1, char *str2 );
功能:在str1中查找子串str2,找到后返回子串的起始地址,找不到则返回空指针(NULL)。
返回值:指向str2中指定的整个字符序列在tr1中第一次出现的指针,如果该序列不存在于str1中,则为空指针(NULL)。
头文件strstr函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

  1. C++中重载了另外两个版本的strstr: 1. const char * : strstr(const char *str1,const char *str2);2. char *strstr (char *str1, const char *str2 );

函数使用

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[] = "abbbcdef";
	char str2[] = "bbc";
	char* ret = strstr(str1, str2);
	if (ret != NULL)
		printf("找到了,起始位置是:%d\n", ret-str1);
	else
		printf("找不到,该子串不存在");
	return 0;
}

在这里插入图片描述

strtok

函数介绍

strtok
函数格式char *strtok(char *str, const char *delimiters);
功能:对该函数的一系列调用将str拆分为子串,子串是由delimiters中的一个或多个字符进行分割的。子串的结尾自动替换为空字符\0,并由函数返回子串的开头。在第一次调用时,该函数需要一个字符串作为strtok的第一个参数,其第一个字符用作扫描令牌的起始位置。在随后的调用中,该函数需要一个空指针(NULL),并使用上一个子串结束后的位置作为扫描的新起始位置。
返回值:如果找到子串,则返回指向该子串开头的指针。否则为空指针(NULL)。当遇到正在扫描的字符串的末尾(即空字符\0)时,返回空指针(NULL)。
头文件strtok函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

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

函数使用

#include <stdio.h>
#include <string.h>

int main()
{
    char str[] = "This, a sample string.";
    char* pch;
    printf("str = %s\n", str);
    pch = strtok(str, " ,.");
    while (pch != NULL)
    {
        printf("%s\n", pch);
        pch = strtok(NULL, " ,.");
    }
    return 0;
}

在这里插入图片描述

在这里插入图片描述

错误信息报告

strerror

函数介绍

strerror
函数格式char *strerror(int errnum);
功能:获取指向错误消息字符串的指针。解释errnum的值,生成一个带有描述错误条件的消息的字符串。
返回值:指向描述错误errnum的错误字符串的指针。
头文件strerror函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

  1. 返回的指针指向一个静态分配的字符串,该字符串不能被程序修改。
  2. strerror产生的错误字符串可能是特定于每个系统和库实现的。
  3. 库函数在执行的时候,发生了错误,会将错误码存在errno这个变量中,errno是C语言提供的一个全局变量。
错误码错误信息
0No error
1Operation not permitted
2No such file or directory
3No such process
4Interrupted function call
5Input/output error
6No such device or address
7Arg list too long
8Exec format error
9Bad file descriptor
10No child processes
11Resource temporarily unavailable
12Not enough space
13Permission denied
14Bad address
15Unknown error
16Resource device
17File exists
18Improper link
19No such device
20Not a directory
21Is a directory
22Invalid argument
23Too many open files in system
24Too many open files
25Inappropriate I/O control operation
26Unknown error
27File too large
28No space left on device
29Invalid seek
30Read-only file system
31Too many links
32Broken pipe
33Domain error
34Result too large
35Unknown error
36Resource deadlock avoided
37Unknown error
38Filename too long
39No locks available
40Function not implemented
41Directory not empty
42Illegal byte sequence

函数使用

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main()
{
    FILE* pFile;
    pFile = fopen("unexist.ent", "r");
    if (pFile == NULL)
        printf("打开文件错误,错误信息是: %s\n", strerror(errno));
    return 0;
}

在这里插入图片描述

字符操作

字符分类函数

函数介绍

函数如果符合条件就返回真
iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母af,大写字母AF
islower小写字母a~z
isupper大写字母A~Z
isalpha字母az或AZ
isalnum字母或者数字,az,AZ,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

以上函数的声明在ctype.h的头文件中,在使用时,要使用#include <ctype.h>操作包含头文件。

函数使用

#include <stdio.h>
#include <ctype.h>

int main()
{
    printf("%d\n", isdigit('2'));
    printf("%d\n", isupper('a'));
    printf("%d\n", isalpha('c'));
    printf("%d\n", ispunct('.'));
    return 0;
}

在这里插入图片描述

字符转换函数

函数介绍

tolower
toupper
函数格式int tolower(int c);
     int toupper(int c);
功能tolower是将大写字符转为小写字符,toupper是将小写字符转为大写字符。
返回值:返回一个int类型,该值可隐形转换为char
头文件tolowertoupper函数的声明在ctype.h的头文件中,在使用时,要使用#include <ctype.h>操作包含头文件。
特别注意

  1. 当不存在相应的小写或者大写字母时,返回其原值。

函数使用

#include <stdio.h>
#include <ctype.h>

int main()
{
    printf("%c\n", toupper('a'));
    printf("%c\n", tolower('A'));
    printf("%c\n", toupper(','));
    printf("%c\n", tolower('2'));

    return 0;
}

在这里插入图片描述

内存操作

memcpy

函数介绍

memcpy
函数格式void *memcpy(void *destination, const void *source, size_t num );
功能:将num字节的值从source指向的位置直接复制到destination指向的内存块。
返回值:返回destination的指针
头文件 memcpy函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

  1. source指针和destination指针所指向的对象的底层类型与此函数无关;结果是数据的二进制拷贝。
  2. 该函数不检查 source中是否有任何终止的\0字符,它总是精确地复制num个字节。
  3. 为了避免溢出,destination参数和source参数所指向的内存的大小应该至少为num字节.
  4. destinationsource不应该重叠,重叠后的结果是不确定的(对于重叠的内存块,memmove是一种更安全的方法)。

函数使用

#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 40);
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

函数实现

void* my_memcpy(void* dest, void* src, size_t num)
{
	void* ret = dest;//记录起始地址
	assert(dest != NULL);
	assert(src != NULL);

	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

memmove

函数介绍

memmove
函数格式void *memmove(void *destination, const void *source, size_t num );
功能:将num字节的值从 source指向的位置复制到destination指向的内存块。允许 sourcedestination重叠。
返回值:返回destination的指针
头文件 memmove函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

  1. source指针和destination指针所指向的对象的底层类型与此函数无关;结果是数据的二进制拷贝。
  2. 该函数不检查 source中是否有任何终止的\0字符,它总是精确地复制num个字节。
  3. 为了避免溢出,destination参数和source参数所指向的内存的大小应该至少为num字节.

函数使用

#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1+2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

函数实现

void* my_memmove(void* dest, void* src, size_t num)
{
	void* ret = dest;//记录起始地址
	assert(dest != NULL);
	assert(src != NULL);
	if (dest < src)
	{
		while (num--)//从前往后
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (num--)//从后往前
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

memset

函数介绍

memset
函数格式void* memset(void* ptr, int value, size_t num);
功能:将ptr指向的内存块的前num个字节设置为指定的值
返回值:返回ptr的指针
头文件 memset函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

  1. value作为int类型传递,但函数使用该值的无符号字符(unsigned char)转换来填充内存块。
  2. 该函数不检查ptr中是否有任何终止的\0字符,它总是精确地设置num个字节。
  3. 为了避免溢出,ptr参数所指向的内存的大小应该至少为num字节.

函数使用

#include <stdio.h>
#include <string.h>

int main()
{
	char str[] = "hello world";
	memset(str+1, '-', 6);
	puts(str);
	return 0;
}

在这里插入图片描述

函数实现

void* my_memset(void* ptr, int value, size_t num)
{
	void* ret = ptr;//记录起始地址
	unsigned char c = (unsigned char)value;
	while (num--)//从前往后
	{
		*(char*)ptr = c;
		ptr = (char*)ptr + 1;
	}
	return ret;
}

memcmp

函数介绍

memcmp
函数格式int memcmp(const void* ptr1, const void* ptr2, size_t num );
功能:将ptr1所指向的内存块的前num字节与ptr2所指向的前num字节进行比较,如果它们都匹配则返回0,如果不匹配则返回不同于0的值,表示哪个值更大。
返回值:返回一个整数,表示内存块内容之间的关系:

返回值结果
>0在两个内存块中不匹配的第一个字节在ptr1中的值高于ptr2中的值
=0两个内存块的内容是相等的
<0在两个内存块中不匹配的第一个字节在ptr1中的值低于ptr2中的值

头文件 memcmp函数的声明在string.h的头文件中,在使用时,要使用#include <string.h>操作包含头文件。
特别注意

  1. 该函数在找到\0字符后不会停止比较。
  2. ptr1参数和ptr2参数所指向的内存的大小应该至少为num字节.
  3. 字节之间的比较是通过转换成unsigned char类型进行比较的。

函数使用

#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,257 };
	int ret = memcmp(arr1, arr2, 10);
	if (ret > 0)
	{
		printf("arr1 > arr2\n");
	}
	else if (ret < 0)
	{
		printf("arr1 < arr2\n");
	}
	else
	{
		printf("arr1 = arr2\n");
	}
	return 0;
}

在这里插入图片描述

在这里插入图片描述

函数实现

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 != NULL);
	assert(ptr2 != NULL);

	for (int i = 0; i < num; i++)
	{
		if (*(unsigned char*)ptr1 == *(unsigned char*)ptr2)
		{
			ptr1 = (char*)ptr1 + 1;
			ptr2 = (char*)ptr2 + 1;
			continue;
		}
		return (*(unsigned char*)ptr1 - *(unsigned char*)ptr2);
	}
	return 0;
}

⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!


http://www.kler.cn/a/511298.html

相关文章:

  • 【Python运维】用Python管理Docker容器:从`docker-py`到自动化部署的全面指南
  • 【视觉惯性SLAM:十七、ORB-SLAM3 中的跟踪流程】
  • 华为数据中心CE系列交换机级联M-LAG配置示例
  • Leetcode3097:或值至少为 K 的最短子数组 II
  • 2025.1.16——六、BabySQL 双写绕过|联合注入
  • [0242].第4-3章:SpringBoot2核心技术笔记
  • 如何使用 Pytest 断言测试 Python 异常处理
  • 计算机网络 (51)鉴别
  • Mysql 主从复制原理及其工作过程,配置一主两从实验
  • LeetCode热题100(子串篇)
  • CesiumLab和CIMRTS的尝试融合
  • 学技术学英语:TCP的三次握手和四次挥手
  • 基于PSO粒子群优化TCN时间卷积神经网络时间序列预测算法matlab仿真
  • 代码随想录26
  • OpenCV相机标定与3D重建(60)用于立体校正的函数stereoRectify()的使用
  • 51c自动驾驶~合集48
  • 设计模式:责任链模式——行为型模式
  • 【从零开始入门unity游戏开发之——C#篇46】C#补充知识点——命名参数和可选参数
  • Markdown学习笔记(2)
  • C# 控制打印机:从入门到实践
  • 胶质母细胞瘤浸润的个性化预测:数学模型、物理信息神经网络和多模态扫描|文献速递-视觉大模型医疗图像应用
  • 机器学习——什么是代价函数?
  • BUUCTF_Web(October 2019 Twice SQL injection)
  • 【物联网】ARM核介绍
  • C++实现矩阵Matrix类 实现基本运算
  • Python网络自动化运维---SSH模块