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 -> 正文阅读

[C++知识库]字符函数和字符串函数~ C

前言

本篇文章将介绍几种常用的对字符串进行操作的库函数,以及用C语言来实现这几种函数
废话不多说,下面开始

一、strlen

size_t strlen(const char* str);

求字符串的长度,包含头文件string.h

  1. strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包括'\0'
  2. '\0'结束

1.1 strlen的使用

#include <stdio.h>
#include<string.h>
int main()
{
 const char*str1 = "abcdef";
 const char*str2 = "bbb";
 if(strlen(str2)-strlen(str1)>0)  //6-3 = 3
 {
	 printf("str2>str1\n");
 } 
 else
 {
 	printf("srt1>str2\n");
 }
 return 0;
}

运行结果:
在这里插入图片描述

1.2 strlen的实现

#include<stdio.h>
#Include<assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	const char* cur = str;
	while (*cur++)
	{
		;
	}
	return cur - str - 1;
}
int main()
{
	char* str = "abcdefg";
	unsigned int len = my_strlen(str);
	printf("%u\n", len);
	return 0;
}

二、strcpy和strncpy

char* strcpy(char* dest , const char* src);

将scr字符串拷贝到dest字符串(包括'\0'),包含头文件string.h

  1. dest目标字符串空间必须足够大,以确保能存放源字符串
  2. dest目标空间必须可变
char* strncpy(char* dest, const char* src,size_t num);

拷贝num个字符从src到dest字符串中,如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

2.1 strcpy和strncpy的使用

#include <stdio.h>
#include<string.h>
int main()
{
	char str1[20] = "abcdef";
	const char* str2 = "bbb";
	char s1[20] = "abcdef";
	const char* s2 = "bbb";
	strcpy(str1, str2); //也可以不接受返回值,自动返回到str1
	strncpy(s1, s2, 2); //拷贝两个字节
	printf("%s\n",str1);
	printf("%s\n",s1);
	return 0;
}

运行结果如下:
在这里插入图片描述

2.2 strcpy和strncpy的实现

//strcpy的实现
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* str1 = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return str1;
}
int main()
{
	char str1[20] = "abcdefg";
	const char* str2 = "ddd";
	my_strcpy(str1,str2);
	printf(str1);
	return 0;
}
//strncpy的实现

#include<stdio.h>
#include<assert.h>
char* my_strncpy(char* dest,const char* src,size_t num)
{
	assert(dest);
	char* s1 = dest;
	char* s2 = (char*)src;
	while (num--)
	{
		*s1 = *s2;
		s1++;
		s2++;
	}
	return dest;
}

int main()
{
	char str1[20] = "abcdefg";
	const char* str2 = "xyzd";
	my_strncpy(str1, str2, 4);
	printf(str1);
	return 0;
}

三、strcat和strncat

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

将src字符串追加到dest字符串中(包含src的’\0'),包含头文件string.h

  1. dest空间必须足够大
  2. src是第一个首字符会覆盖掉dest的’\0’
char* strncat ( char * dest, const char* src, size_t num );

将src字符串的num个字节追加到dest字符串中

  1. 追加的字符不包含’\0’的,后尾补’\0’
  2. 如果src的长度小于num,则只复制到终止空字符的内容。

3.1 strcat和strncat的使用


#include <stdio.h>
#include <string.h>
int main()
{
	char str1[20];
	char str2[20];
	char s1[20];
	char s2[20];
	strcpy(str1, "To be ");
	strcpy(str2, "or not to be");
	strcpy(s1, "To be ");
	strcpy(s2, "or not to be");
	strcat(str1, str2);
	puts(str1);
	
	strncat(s1, s2, 6);
	puts(s1);
	
	return 0;
}

运行结果:
在这里插入图片描述

3.2 strcat和strncat的实现

//strcat的实现
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* str1 = dest;
	//dest一直走到‘\0’结束
	while(*dest)
	{
			dest++;
	}
	//dest从'\0'开始追加src字符串
	while (*dest++ = *src++)
	{
		;
	}
	return str1;
}
int main()
{
	char str1[20] = "abcdefg";
	const char* str2 = "ddd";
	my_strcat(str1,str2);
	printf(str1);
	return 0;
}
//strncat的实现
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* str1 = dest, * str2 = (char*)src;
	while (*str1)
	{
		str1++;
	}
	while (num-- && *str)
	{
		*str1 = *str2;
		 str1++;
		 str2++;
	}
	*(str1 + 1) = '\0';
	return dest;
}
int main()
{
	char str1[20] = "abcdefg";
	const char* str2 = "dddxassax";
	my_strncat(str1, str2, 5);
	printf(str1);
	return 0;
}

四、strcmp和strncmp

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

比较两个字符串的大小,包含头文件string.h

  1. 两个字符串自左到右逐个字符相比(ASCII值大小比较),直到遇见’\0’结束
  2. str1大于str2,返回大于0的数字
  3. str1小于str2,返回小于0的数字
  4. str1等于str2,返回0
int strncmp ( const char * str1, const char * str2,size_t num);

比较出现的字符大小直到一个字符串结束或者num个字符全部比较完

4.1 strcmp和strncmp的使用

#include <stdio.h>
#include<string.h>
int main()
{
 	const char* str1= "abcdefa";
 	const char* str2 = "abcdef";
	if(strcmp(str1,str2) == 0)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
	if(strncmp(str1,str2,6) == 0)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
 	return 0;
}

运行结果如下:
在这里插入图片描述

4.2 strcmp的实现

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* dest, const char* src)
{
	int ret = 0;
	assert(dest && src);
	while (!(ret = *(unsigned char*)dest - *(unsigned char*)src) && *src 
	          && *dest)
	{
		src++;
		dest++;
	}
	if (ret < 0)
		return -1;
	else if (ret > 0)
		return 1;
	else
		return 0;

}
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "ybcdef";
	if (my_strcmp(str1, str2) < 0)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
	return 0;
}

五、strstr

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

如果str2是str1的子串,则返回在str1中字串的首字符开始一直到’\0’,结束,如果不是返回NULL

5.1 strstr的使用

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "This is a simple string";
	char* pch;
	pch = strstr(str, "simple");
	if(pch != NULL)
		printf(pch);
	return 0;
}

结果如下:
在这里插入图片描述

5.2 strstr的实现

#include <stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	char* s1 = (char*)str1;
	char* s2 = (char*)str2;
	if (*s2 == '\0')
		return s1;
	while (*s1 != *s2)
	{
		s1++;
	}

	char* cp = s1;
	while (*s1 && *s2 && !(*s1 - *s2))
	{
		s1++;
		s2++;
	}
	if (!*s2)
	{
		return cp;
	}
	return NULL;
}

int main()
{
	char str[] = "This is a simple string";
	char* pch;
	pch = my_strstr(str, "T");
	if (pch != NULL)
		printf(pch);
	return 0;
}

六、strtok

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

函数的作用是分解字符串,所谓分解,即没有生成新串,只是在str所指向的内容首次出现分界符的位置,将分界符修改成了’/0’,故第一次用strtok()返回第一个子串,包含头文件string.h

  1. 第一次提取子串完毕之后,继续对源字符串s进行提取,应在其后(第二次,第三次。。。第n次)的调用中将strtok的第一个参数赋为空值NULL(表示函数继续从上
    一次调用隐式保存的位置,继续分解字符串;对于前一次次调用来说,第一次调用结束前用一个this指针指向了分界符的下一位
  2. 当this指针指向“\0” 时,即没有被分割的子串了,此时则返回NULL
  3. 可以把delim理解为分隔符的集合,delim中的字符均可以作为分隔符
  4. strtok在调用的时候,如果起始位置即为分隔符,则忽略了起始位置开始的分隔符

6.1 strtok的使用

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

运行结果如下:
在这里插入图片描述

6.2 strtok的实现

char* strtok (char* str, const char* delim)
{
	// 生成替换字符表
	char table[256] = {0};
    while (*delim != '\0')
    {
        table[*delim] = 1;
        delim++;
    }

	// 使用 static 类型指针保存上一次函数调用时的字符串地址
	static char* pstr = NULL;
	if (str != NULL)
	{
		pstr = str;
	}

	// 保证 pstr 指向以非替换字符为首的子字符串
	while (*pstr != '\0' && table[*pstr] == 1)
	{
		pstr++;
	}	

	// ret 保存返回子字符串的首地址
	char* rst = (*pstr != '\0') ? pstr : NULL;

	while (*pstr != '\0')
	{
        if (table[*pstr] == 1)
        {
            // 切割得到子字符串,且 pstr 最后指向子字符串的下一字符
            *pstr++ = '\0';
            break;
        }
        else
        {
            pstr++;
        }
	}
    
	return rst;
}

七、strerror

char*  strerror(int errnum);

strerror()用来依参数errnum 的错误代码来查询其错误原因的描述字符串, 然后将该字符串指针返回,返回描述错误原因的字符串指针,包含头文件string.h

  1. 在程序代码中包含 #include <errno.h>,然后每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,这样你只需要读errno这个全局变量就可以获得失败原因了
  2. perror函数也是针对errno错误的.

7.1 strerror的使用


#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main()
{
    FILE* pFile;
    pFile = fopen("unexist.ent", "r");
    if (pFile == NULL)
    {
        printf("Error opening file unexist.ent: %s\n", strerror(errno));
        perror("open file failed\n");
    }      
    return 0;
}

运行结果:
在这里插入图片描述

八、内存函数memcpy和memmove

void *memcpy( void *dest, const void *src, size_t count );
void *memmove( void *dest, const void *src, size_t count );

都是内存拷贝函数,src的count个字节拷贝到dest中,包含头文件string.h
它们的区别:

  1. 在拷贝自己时有重复的地方,memcpy不能处理重复地方的拷贝(VC自带的库函数可以)
  2. memmove可以处理有重复的地方

8.1 memcpy和memmove的实现

//memcpy的实现
void* my_memcpy(void* dest,const void* src,size_t count)
{
	void* ret = dest;
	assert(dest && src);
	while (count--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

int main()
{
	int a[5] = { 1,2,3,4,5 };
	int b[] = { 16,7,8,9,10 };
	my_memcpy(a+2, a+1, 12);    //1,2,2,2,2
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

有重复的地方发生了覆盖,正常应该为1,2,2,3,4

//memmove的实现
//处理覆盖问题,可以从dest>src用逆序拷贝,dest<src用正序拷贝,就不会覆盖了
#include <stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t count)
{
	assert(dest && src);
	void* ret = dest;
	if (src > dest)
	{ //从前往后
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{   //从后往前
		dest = (char*)dest + count - 1;
		src = (char*)src + count - 1;
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}
	}
	return ret;
}
int main()
{
	int a[5] = { 1,2,3,4,5 };
	int b[] = { 16,7,8,9,10 };
	my_memmove(a + 2, a + 1, 12);   //1,2,2,3,4
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

九、常用字符函数

包含头文件ctype.h

函数如果它的参数符合下列条件就返回真
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任何可打印字符,包括图形字符和空白字符
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 21:52:22  更:2022-03-17 21:53:25 
 
开发: 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:45:46-

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