IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 字符函数和字符串函数的使用 -> 正文阅读

[C++知识库]字符函数和字符串函数的使用

字符函数和字符串函数的使用

  1. 求字符串长度 strlen
  2. 长度不受限制的字符串函数 strcpy strcat strcmp
  3. 长度受限制的字符串函数介绍
    strncpy strncat strncmp
  4. 字符串查找 strstr strtok
  5. 错误信息报告 strerror
  6. 内存操作函数memcpy memmove memset memcmp

c语言中对字符和字符串的处理很是频繁,但是c语言本身是没有字符串类型的字符串通常放在常量字符串中,或者字符数组中,字符串常量,适用于那些对它不做修改的字符串函数

strlen

size_t strlen(const char* str)

字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’);参数指向的字符串必须要以’\0’结束注意函数的返回值为size_t,是无符号的学会strlen函数的模拟实现,size_t是unsigned int 是无符号的整数

strlen深入理解

size_t strlen(const char* str);
//size_t 就是unsigned int是一个无符号的数字
//
int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("hehe\n");
	//结果肯定是hehe因为size_t是一个无符号的数字,所以无符号减去无符号得到的一定是一个无符号的数
	//一定是要给大于0的数字 -3被当作无符号数就是3 所以结果是hehe
	}
	else
	{
		printf("haha\n");
	}
	return 0;
}

下面代码是模拟实现strlen

size_t strlen(const char* str);
size_t 就是unsigned int是一个无符号的数字
int	 my_strlen(const char* str)//常量字符串不能改变
{
	int count = 0;
	assert(str != NULL);//保证指针有效性
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	int arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

strcpy 字符串拷贝

strcpy的参数是:

char* strcpy(char* destination, const char * source);
desitination是目的地,source是源头
1:源字符串必须以'\0'结束
2:会将源字符串中的'\0'拷贝到m目标空间
3:目标空间必须足够大,以确保能存放源字符串
4:目标空间必须可变
5:学会模拟实现

strcpy的用法

int main()
{
	char arr1[] = "abcdefghi";
	char arr2[] = "bit";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

模拟实现strcpy

char* my_strcpy(char* dest,const  char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = dest;
	//拷贝src指向的字符串到dest指向的空间,包含'\0'
	while (*src != '\-')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src; //这里是将arr2的'\0'拷贝过去
	return ret;//返回目的空间的起始位置
}
int main()
{
	char arr1[] = "abcdefghi";//这是目的地必须足够大
	char arr2[] = "bit";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

strcat 字符串追加

char * strcat (char* destination, const char * source);
字符串追加

1.源字符串必须以 '\0'结束
2.目标空间必须有足够的大,能容纳下源字符串的内容
3.目标空间必须可修改
4.字符串自己给自己追加如何
自己给自己追加要使用strncat

strcat的用法是什么

int main()
{
	char arr1[30] = "hello";
	char arr2[] = "world";
	strcat(arr1, arr2);//strcat 将arr2中的内容,追加到arr1的后面去
	printf("%s\n", arr1);
	return 0;
}

模拟实现strcat

char* my_strcat(char* arr1,const char* arr2)
{
	char* ret = arr1;
	assert(arr1 != NULL);
	assert(arr2 != NULL);
	//1.找到目的字符串'\0'
	while (*arr1 != '\0')
	{
		arr1++;
	}
	while (*arr2 != '\0')
	{
		*arr1 = *arr2;
		arr1++;
		arr2++;
	}
	*arr1 = *arr2;
	return ret;//返回arr1
}
int main()
{
	char arr1[30] = "hello";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	printf("%s\n",arr1);
	return 0;
}

strcmp 字符串比较

int strcmp(const char * str1,const char* str2);参数

标准规定
1.第一个字符串大于第二个字符串,则返回大于0的数字
2.第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小于0的数字

strcmp的用法是什么

int main()
{
	char* p1 = "asbc";
	char* p2 = "def";
	int ret = strcmp(p1, p2);
//这里是按照字符串的ASCII码值来进行比较的a的ASCIl值在字符串最小Z的ASCII码值最大
	printf("%d\n", ret);//-1

	if (strcmp(p1, p2) > 0)
	{
		printf("p1>p2\n");
	}
	else if (strcmp(p1, p2) == 0)
	{
		printf("p1======p2\n");
	}
	else if (strcmp(p1, p2) < 0)
	{
		printf(" p1<p2\n");
	}
	return 0;
}

模拟实现strcmp

int	my_strcmp(char* p1,char* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	while (*p1 == *p2)
	{
		if (*p1 == '\0')
		{
			return 0;
		}
		p1++;
		p2++;
	}
 return (*p1-*p2)
 }
 int main()
{
	char* p1 = "abcdef";
	char* p2 = "abcdds";
	int ret = my_strcmp(p1, p2);
	if (ret == 1)
	{
		printf("p1>p2\n");
	}
	else if (ret == -1)
	{
		printf("p1==p2\n");
	}
	else
	{
		printf("p1<p2\n");
	}
	return 0;
}

strncpy

char* strncpy(char* strDest,const char* strSource,size_t num); num单位是字节

拷贝num个字符从源字符串到目标空间
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,知道num个

strncpy的用法

int main()
{
	char arr1[10] = "abcdef";
	char arr2[] = "hello bit";
	strncpy(arr1, arr2, 4);
	printf("%s\n", arr1);
	return 0;
}

strncat

参数
char * strncat(char * destination, const char * source,size_t num);//追加

strncat的用法

int main()
{
	char arr1[30] = "hello\0xxxxaxx";
	char arr2[] = "world";
	strncat(arr1, arr2, 3);
	/*
	这里将arr2的前三个字符追加上去
	w追加到\0处
	o追加到x出
	r追加到x出
	但是追加完了之后还是会补上一个\0的
	所以结果会是hellowor
	r的后面会自己补上要给\0的
	如果你的个数比字符串还长,那么是会把字符串追加完了之后加上一个\0就完了
	*/
	printf("%s\n", arr1);
	return 0;
}

strncmp

参数是:int strncmp(const char * str1,const char * str2, size_t num);

int main()
{
	//strncmp - 字符串比较
	const char* p1 = "abcdef";
	const char* p2 = "abcdqwer";
	int ret = strncmp(p1, p2, 6);
	//比较字符串中几个字符
	printf("%d\n", ret);
	return 0;
}

strstr 找子字符串, 查找字符串

参数是: char* strstr(const char* ,const char*);

strstr的用法

int main()
{
	char* p1 = "abcdefsss";
	char* p2 = "def";
	char* ret = strstr(p1, p2);
	/*
	要去p1指向的字符串里面找p2指向的字符串存不存在,也就是在p1里面找p2存不存在
	如果存在返回 返回存在的首字符的地址,如果不存在,返回NULL空指针
	*/
	if (ret == NULL)
	{
		printf("子串不存在\n");
	}
	else
	{
		printf("%s\n", ret);//defsss
		//按照返回首字符的地址进行打印该地址开始到后面的字符
	}
	return 0;
}

注意平时看英文文档时

看文档时:NULL–空指针
NUL/Null 表示’\0’

模拟实现strstr

char* my_strstr(const char* p1,const char* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	char *s1 = p1;
	char *s2 = p2;
	char *cur = p1;
	if (*p2 == '\0')
	{
		return p1;
	}
	while (*cur)
	{
		s1 = cur;
		s2 = p2;
		while ((*s1 != '\0')&&(*s2 != '\0')&&(*s1 ==*s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cur;//找到子串
		}
		cur++;
	}
	return NULL;//找不到子串
}
int main()
{
	char * p1 = "abbbcdef";
	char * p2 = "bbc";
	char * ret = my_strstr(p1, p2);
	if (ret == NULL)
	{
		printf("子串不存在\n");
	}
	else
	{
		printf("%s\n",ret);
	}
	return 0;
}
模拟实现my_strstr
char* my_strstr(const char* p1,const char* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	char* s1 = p1;
	char* s2 = p2;
	char* cu = p1;
	if (*p2 == '\0')
	{
		return p1;
	}
	while (*cu)
	{
		s1 = cu;
		s2 = p2;
		while ((*s1 != '\0') && (*s2 != '\0')&&(*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cu;
		}
		cu++;
	}
	return NULL;
}
int main()
{
	char* p1 = "abbbcdef";
	char* p2 = "bbc";
	char* ret = my_strstr(p1, p2);
	if (ret == NULL)
	{
		printf("没有找到子串\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}

strtok 字符串切割打印

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

分隔符理解

192.168.31.121 //这里的分隔符就是 .
192.168.31.121 - strtok
zpw@bitdu.tech //这里的分隔符就是@和.
zpw bitdu tech

strtok的使用

int main()
{
	char arr[] = "zpw@bitdu.tech";
	char* p = ("@.");
	char buf[1024] = { 0 };
	strcpy(buf,arr);
	//切割buf中的字符串
	char* ret =strtok(arr, p);
	printf("%s\n", ret);//zpw
	ret = strtok(NULL, p);
	printf("%s\n", ret);//bitdu
	ret = strtok(NULL, p);
	printf("%s\n", ret);//tech
	return 0;
}

自己实现strtok

 //自己实现strtok 字符串切割打印s
int main()
{
	char arr[] = "zpw@bitdu.tech";
	char* p = ("@.");
	char buf[1024] = { 0 };
	strcpy(buf, arr);
	//切断buf中的字符串
	char* ret = NULL;
	for (ret = strtok(buf, p); ret != NULL;ret = strtok(NULL,p))
	{
		printf("%s\n", ret);
	}
	return 0;
}

strerror

errno是一个全局的错误码变量
当c语言的库函数在执行过程中,发生了错误,就会把对应的错误码,赋值到errno中
strerror
参数 char * strerror(int errnum);
返回错误码 所对应的错误信息
0 No error
1 Operation not permitted
2 No such file or directory

int main()
{
	//	错误码	错误信息
	char* str = strerror(errno);//1 2 3 ......
	printf("%s\n", str);
	return 0;
}
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));//打开上面文件如果有就会显示成功,如果没有就会显示错误信息
	}
	else
	{
		printf("open file success\n");
	}
	return 0;

字符分类函数

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

下面是具体的使用实例

#include<ctype.h>
int main()
{
	char ch = '@';
	//int ret = islower(ch); 判断是不是小写字母,如果是返回不为0的数,如果不是返回0
	int ret = isdigit(ch);//判断是不是数字,如果是返回不为0的数,如果不是返回0
	printf("%d\n", ret);
	return 0;
}

字符转换函数 tolower toupper

int tolower(int c);//转小写字母   将所有字母转为小写字母
int toupper(int c);//转大写字母	将所有字母转为大写字母
int main()
{
	//char ch = tolower('Q');
	//putchar(ch);//结果是Q	
	char ch = toupper('s');
	putchar(ch);//结果是S
	return 0;
}
int main()
{
	char arr[] = "I AM A Student";
	int i = 0;
	while (arr[i])
	{
		if (isupper(arr[i]))//如果它是大写
		{
			arr[i] = tolower(arr[i]);//将大写转化为小写,并返回去
		}
		i++;
	}
	printf("%s\n", arr);//结果是:	i am a student
	return 0;
}

内存操作函数 memcpy memmove memcmp memset

memcpy 内存拷贝

memcpy - 内存拷贝 void* -通用类型的指针 -无类型指针

void * mencpy( void * destination, const void * source, size_t num );

  • destination 目的地
  • source 源头
  • num多少字节

1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
2.这个函数在遇到’\0’的时候并不会停下来
3.如果source和destination有任何的重叠,复制的结果都是未定义的

下面是memcpy的用法

struct S
{
	char name[20];
	int age;
};
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[5] = { 0 };
	//memcpy(arr2 , arr1 , sizeof(arr1));
	//拷贝整型数组,将arr1的内容拷贝到arr2里面去

	struct S arr3[] = { {"张三",20}, {"李四",30} };
	struct S arr4[3] = { 0 };
	memcpy(arr4, arr3, sizeof(arr3));
	return 0;

模拟实现memcpy

void* my_memcpy(void* dest,const void* src, size_t num)//unsigned int 就是size_t
{
	assert(dest != NULL);
	assert(src  != NULL);
	char* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		++(char*)dest;
		++(char*)src;
	}
	return ret;
}
struct S
{
	char name[20];
	int age;
};
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[5] = { 0 };
	//memcpy(arr2 , arr1 , sizeof(arr1));
	//拷贝整型数组,将arr1的内容拷贝到arr2里面去
	struct S arr3[] = { { "张三", 20 }, { "李四", 30 } };
	struct S arr4[3] = { 0 };
	//my_memcpy(arr4, arr3, sizeof(arr3));
	memcpy(arr2 , arr1 , sizeof(arr1));
	return 0;
}
C语言标准
1:memcpy 只要处理 不重叠的内存拷贝就可以
2:memmove 处理重叠内存的拷贝 

memmove

参数 void * memmove( void * destination, const void * source, size_t num);
1.和memcpy的差别就是memmove函数处理的源内存块和目标n内存块是可以重叠的
2.如果源空间和目标空间出现重叠,就得使用memmove函数处理

memmove进行模拟实现

void* my_memmove(void* dest, const void* src,size_t count)
{
	void* ret = dest;
	assert(dest != NULL);
	assert(src != NULL);
	if (dest < src)
	{
		//前 -》后 从源头前面向目标前面移动
		while (--count)
		{
			*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	else
	{
		while (--count)
		{
			//后->前 从源头后面向目标后面移动
			*((char*)dest + count) = *((char*)src + count);
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	memmove(arr+4, arr+2, 20);
	return 0;
}

memcmp 内存比较

参数 int memcmp(const void* ptr1, const void* ptr2, size_t num);
返回值 >0 <0 ==

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[] = { 1, 2, 5, 4, 3 };
	int ret = memcmp(arr1, arr2, 9);
	printf("%d\n", ret);
	return 0;
}

memset - 内存设置

void * memset( void* dest, int c, size_t count); count的单位是字节
dest 目的地要把那一块的空间进行设置
c 就是你要设置的字符是什么
count 你要设置多少个字符

int main()
{
	char arr[10] = "";
	memset(arr, '#', 10);//将arr里面全部放成##########
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 10:47:24  更:2021-10-22 10:48:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:59:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码