string.h c源码实现

int isspace( char c )
{
	char comp[] = { ' ', '\t', '\r', '\n', '\v', '\f' };
	const int len = 6;
	for ( int i=0; i<len; ++i )
	{
		if ( c == comp[i] )
			return 1;
	}
	return 0;
}

char tolower( char c )
{
	if ( c >= 'A' && c <= 'Z' )
		return ( c + 32 );
	return c;
}


// 在字符串s中查找 c 第一次出现的 位置。
// 找到: 返回指针位置; 未找到: 返回NULL
char * strchr( const char * s, int c )
{
	for ( ; *s != (char)c; ++s )
	{
		if ( *s == '\0' )
			return NULL; // 如果s已抵达尾部,为找到,返回NULL
	}
	
	return (char *)s; // 返回 c在s的指针位置
}

// 在字符串S中从末尾开始查找字符c, 找到则返回 字符串指针位置,未找到返回NULL
char * strrchr( const char * s, int c )
{
	const char * p = s + strlen( s ); // p 指向 s 的末端
	do {
		if ( *p == (char)c )
			return (char *)p; // 		
	} while ( --p >= s ); 
	
	return NULL;
}

// 在字符串S中指定长度内查找字符C。
char * strnchr( const char * s, size_t count, int c )
{
	for ( ; count-- && *s != '\0'; ++s )
	{
		if ( *s == (char)c )
			return (char *)s;
	}
	
	return NULL;
}

// 搜索一个字符串 s2 在另一个字符串 s1 中的第一次出现
char * strstr( const char * s1, const char * s2 )
{
	size_t l1, l2;
	l2 = strlen( s2 );
	
	if ( !l2 )
		return (char *)s1;
	l1 = strlen( s1 );
	while ( l1 >= l2 )
	{
		l1--;
		if ( !memcmp( s1, s2, l2) )
			return (char *)s1;
		s1++;
	}
	return NULL;
}

// 从字符串s开头查找符合 accept 字符, 返回字符串s开头连续包含字符串 accept 内的字符数目。
// 如返回n,则代表 字符串s 开头连续有n个字符都属于字符串accept内的字符。
//char *str="Linux was first developed for 386/486-based pcs.";
//printf("%d\n",strspn(str,"Linux")); // 输出为 5
//printf("%d\n",strspn(str,"/-")); // 输出为 0
//printf("%d\n",strspn(str,"1234567890")); // 输出为 0
size_t strspn( const char * s, const char * accept )
{
	const char * p;
	const char * a;
	size_t count = 0;
	
	for ( p = s; *p != '\0'; ++p )
	{
		for ( a = accept; *a != '\0'; ++a ) // *p 逐个与 accept允许的字符串比对。
		{
			if ( *p == *a ) // 只要符合 accept,跳出accept循环,count+1
				break;
		}
		if ( *a == '\0' ) // 如果 accept 到了末尾,则表示出现第一个不符合accept的字符位置了。
			return count;
		++count;
	}
	return count;
}

// 从字符串s开头查找符合 reject 字符, 返回字符串s 开头连续不含字符串 reject 内的字符数目
// 如返回n, 则代表字符串s 开头连续有n 个字符都不含字符串 reject 内的字符.
//char *str = "Linux was first developed for 386/486-based pcs. ";
//printf("%d\n", strcspn(str, " ")); // 输出 5 ;只计算到" "的出现, 所以返回"Linux"的长度
//printf("%d\n", strcspn(str, "/-")); // 输出 33 ; 计算到出现"/"或"-", 所以返回到"6"的长度
//printf("%d\n", strcspn(str, "1234567890")); // 输出 30 ; 计算到出现数字字符为止, 所以返回"3"出现前的长度
size_t strcspn( const char * s, const char * reject )
{
	const char * p;
	const char * r;
	size_t count = 0;
	
	for ( p = s; *p != '\0'; ++p )
	{
		for ( r = reject; *r != '\0'; ++r )
		{
			if ( *p == *r ) // 如果 *p 等于 *r, 则返回 长度
				return count;
		}
		++count; // 2者不相等时,count+1
	}
	
	return count;
}

// 在字符串S1中 检验 S2串,当s2字符出线在s1中时,则停止检验,并返回该字符位置
// char *s = "12,3a,45"
// char *ptr = strpbrk(s, ","); // ptr = ,3a,45
char * strpbrk( const char * s1, const char * s2 )
{
	const char * sc1, * sc2;
	for ( sc1 = s1; *sc1 != '\0'; ++sc1 )
	{
		for ( sc2 = s2; *sc2 != '\0'; ++sc2 )
		{
			if ( *sc1 == *sc2 ) 	// 如果 在 s1 中找到符合 s2 的字符			
				return (char *)sc1; // 则直接返回该字符位置
		}
	}
	return NULL; // 未找到则返回 NULL
}

char * strsep( char **s, const char *ct )
{
	char * sbegin = *s;
	char * end;
	
	if ( *sbegin == NULL )
		return NULL;
	
	end = strpbrk( sbegin, ct ); // 在 sbegin 中 查找 ct 第一次出线的位置。
	if ( end ) // 找到了
		*end++ = '\0'; // 添加 结束符'\0'
	
	*s = end; // s指向了新的 开始位置
	return sbegin;	
}

// 跳过空白符
char * skip_spaces( const char * str )
{
	while ( isspace( *str) )
		++str;
	return (char *)str;
}

// 跳过首尾的空白符
char * strim( char * s )
{
	size_t size;
	char * end;
	
	s = skip_spaces( s ); // 跳过空白符
	size = strlen( s ); // 计算 s 字符长度
	if ( !size ) // 长度为0,则直接返回s 
		return s; // s = '\0'
	
	end = s + size - 1; // end 指向 s 字符串末尾
	while ( end >= s && isspace( *end ) ) // 跳过末尾的空白符
		end--;
	*( end + 1 ) = '\0'; // 设置下一位为 '\0'
	
	return s;
} 

// 计算字符串s的长度. 以 '\0' 结尾
size_t strlen( const char * s )
{
	const char * sc;
	for ( sc = s; *sc != '\0'; ++sc )
		; // nothing
	return sc - s;
}


// 比较指定长度的2个字符串, 不区分大小写
int strnicmp( const char * s1, const char * s2, size_t len )
{
	unsigned char c1, c2;
	if ( !len )
		return 0;
	
	do {
		c1 = *s1++;
		c2 = *s2++;
		
		if ( !c1 || !c2 ) // 如果其中一个为空
			break;
		if ( c1 == c2 ) // 相等,则继续比较下一个
			continue;
		c1 = tolower( c1 );
		c2 = tolower( c2 ); // 都转换为小写
		if ( c1 != c2 ) // 不相等
			break;
	} while ( --len ); // 在指定长度内比较
	
	return (int)c1 - (int)c2; // 跳出循环后,比较字符是否相等。
}

// 比较2个字符串, 不区分大小写。
int strcasecmp( const char * s1, const char * s2 )
{
	int c1, c2;
	do {
		c1 = tolower( *s1++ );
		c2 = tolower( *s2++ );
	} while ( c1 == c2 && c1 != '0' ); //
	
	return c1 - c2;
}

// 比较指定长度的2个字符串, 不区分大小写
int strncasecmp( const char * s1, const char * s2, size_t n )
{
	int c1, c2;
	do {
		c1 = tolower( *s1++ );
		c2 = tolower( *s2++ );
	} while ( ( --n > 0) && c1 == c2 && c1 != '0' ); //
	
	return c1 - c2;
}

// 字符串拷贝。 将 src 内容 拷贝到 dest 中。
// 这里不带长度,src 长度 大于 dest 长度,则会超出 存储范围。
char * strcpy( char * dest, const char * src )
{
	char * begin = dest; // 指向 目的存储空间 的 开始。
	
	while ( ( *dest++ = *src++) != '\0' ) // 逐字符保存内容。s
		; // nothing
	
	return begin;
}

// 字符串拷贝。 将 src 指定长度的内容 拷贝到 dest 中。
char * strncpy( char  * dest, const char * src, size_t count )
{
	char * move = dest;
	
	while ( count )
	{
		if ( ( *move = *src ) != '\0' )
			src++;
		move++;
		count--;
	}
	
	return dest;
}

// 字符串拼接, 将 src 内容 拷贝到 dest 的后面
char * strcat( char * dest, const char * src )
{
	char * begin = dest;
	
	while ( *dest ) 
		dest++; // 
		
	while ( ( *dest++ = *src++ ) != '\0' )
		; // do nothing
	
	return begin;
}

// 字符串拼接, 将 src 指定长度的内容 拷贝到 dest 的后面
char * strncat( char * dest, const char * src, size_t count )
{
	char * begin = dest;
	
	while ( *dest ) 
		dest++; // 
		
	while ( ( *dest++ = *src++ ) != '\0' )
	{
		if ( --count == 0 )
		{
			*dest= '\0';
			break;
		}
	}
		; // do nothing
	
	return begin;
}

// 比较2个字符串。 返回值: 0, -1, 1
int strcmp( const char * s1, const char * s2 )
{
	unsigned char c1, c2;
	
	while ( 1 )
	{
		c1 = *s1++;
		c2 = *s2++;
		if ( c1 != c2)
			return ( c1 < c2 ) ? -1 : 1; // 不相等 返回 -1 1
		if ( !c1 ) // 如果c1 已抵达末尾
			break;
	}
	
	return 0; // 相等返回 0 
}

// 指定长度的2个字符串比较。 返回 0 -1 1
int strncmp( const char * s1, const char * s2, size_t count )
{
	unsigned char c1, c2;
	
	while ( count )
	{
		c1 = *s1++;
		c2 = *s2++;
		if ( c1 != c2 )
			return ( c1 < c2 ) ? -1 : 1; // 不相等 返回 -1 1
		if ( !c1 )
			break;
		
		count--; // 长度减1
	}
	
	return 0; // 相等返回 0
}

// 将 s 内长度为count 的内容 用c 来初始化s
void * memset( void *s, int c, size_t count )
{
	char * xs = (char *)s;
	while ( count-- )
		*xs++ = c;
	return s;
}

// 将 src 内count长度内容 拷贝到 dest 中
void * memcpy( void * dest, const void * src, size_t count )
{
	char * tmp = (char *)dest;
	const char * s = (const char *)src;
	while ( count-- )
		*tmp++ = *s++;
	
	return dest;
}

// 比较 s1 s2大小, 返回一个整数
int memcmp( const void * s1, const void *s2, size_t count )
{
	const unsigned char * su1 = (const unsigned char *)s1;
	const unsigned char * su2 = (const unsigned char *)s2;

	int res = 0;
	for ( ; count > 0; ++su1, ++su2, --count ) 
	{
		if ( ( res = *su1 - *su2 ) != 0 ) // 不相等,则跳出循环。
			break;
	}
	return res;
}

  

转载于:https://www.cnblogs.com/sylar-liang/p/4780380.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质?你是否想成为一名资深开发人员,想开发别人做不了的高性能程序?你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? 那么C++就是你个人能力提升,职业之路进阶的不二之选。【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署;2.吊打一切关于C++的笔试面试题;3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块基础篇本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。进阶篇本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。提升篇:本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值