栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

字符函数和字符串函数~ C

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

字符函数和字符串函数~ C

文章目录

前言一、strlen

1.1 strlen的使用1.2 strlen的实现 二、strcpy和strncpy

2.1 strcpy和strncpy的使用2.2 strcpy和strncpy的实现 三、strcat和strncat

3.1 strcat和strncat的使用3.2 strcat和strncat的实现 四、strcmp和strncmp

4.1 strcmp和strncmp的使用4.2 strcmp的实现 五、strstr

5.1 strstr的使用5.2 strstr的实现 六、strtok

6.1 strtok的使用6.2 strtok的实现 七、strerror

7.1 strerror的使用 八、内存函数memcpy和memmove

8.1 memcpy和memmove的实现 九、常用字符函数

前言

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

一、strlen
size_t strlen(const char* str);

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

    strlen函数返回的是在字符串中''前面出现的字符个数(不包括'')以''结束
1.1 strlen的使用
#include 
#include
int main()
{
 const char*str1 = "abcdef";
 const char*str2 = "bbb";
 if(strlen(str2)-strlen(str1)>0)  //6-3 = 3
 {
	 printf("str2>str1n");
 } 
 else
 {
 	printf("srt1>str2n");
 }
 return 0;
}

运行结果:

1.2 strlen的实现
#include
#Include
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("%un", len);
	return 0;
}
二、strcpy和strncpy
char* strcpy(char* dest , const char* src);

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

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

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

2.1 strcpy和strncpy的使用
#include 
#include
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("%sn",str1);
	printf("%sn",s1);
	return 0;
}

运行结果如下:

2.2 strcpy和strncpy的实现
//strcpy的实现
#include
#include
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
#include
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的’'),包含头文件string.h

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

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

    追加的字符不包含’’的,后尾补’’如果src的长度小于num,则只复制到终止空字符的内容。
3.1 strcat和strncat的使用
#include 
#include 
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
#include
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* str1 = dest;
	//dest一直走到‘’结束
	while(*dest)
	{
			dest++;
	}
	//dest从''开始追加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
#include
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) = '';
	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

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

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

4.1 strcmp和strncmp的使用
#include 
#include
int main()
{
 	const char* str1= "abcdefa";
 	const char* str2 = "abcdef";
	if(strcmp(str1,str2) == 0)
	{
		printf("YESn");
	}
	else
	{
		printf("NOn");
	}
	if(strncmp(str1,str2,6) == 0)
	{
		printf("YESn");
	}
	else
	{
		printf("NOn");
	}
 	return 0;
}

运行结果如下:

4.2 strcmp的实现
#include
#include
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("YESn");
	}
	else
	{
		printf("NOn");
	}
	return 0;
}
五、strstr
char* strstr(const char* str1, const char* str2);

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

5.1 strstr的使用
#include 
#include 
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 
#include
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	char* s1 = (char*)str1;
	char* s2 = (char*)str2;
	if (*s2 == '')
		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

    第一次提取子串完毕之后,继续对源字符串s进行提取,应在其后(第二次,第三次。。。第n次)的调用中将strtok的第一个参数赋为空值NULL(表示函数继续从上
    一次调用隐式保存的位置,继续分解字符串;对于前一次次调用来说,第一次调用结束前用一个this指针指向了分界符的下一位当this指针指向“” 时,即没有被分割的子串了,此时则返回NULL可以把delim理解为分隔符的集合,delim中的字符均可以作为分隔符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("%sn",pch1);
		pch1 = strtok(NULL, pch);
	}
	
	return 0;
}

运行结果如下:

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

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

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

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

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

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

    在程序代码中包含 #include ,然后每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,这样你只需要读errno这个全局变量就可以获得失败原因了perror函数也是针对errno错误的.
7.1 strerror的使用
#include 
#include 
#include //必须包含的头文件
int main()
{
    FILE* pFile;
    pFile = fopen("unexist.ent", "r");
    if (pFile == NULL)
    {
        printf("Error opening file unexist.ent: %sn", strerror(errno));
        perror("open file failedn");
    }      
    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
它们的区别:

    在拷贝自己时有重复的地方,memcpy不能处理重复地方的拷贝(VC自带的库函数可以)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
#include
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任何可打印字符,包括图形字符和空白字符
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/767841.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号