str函数源码

原文地址:http://blog.csdn.net/xingerr/article/details/70257234

1、strcpy函数

  1. 原型char * strcpy(char * destin, const char * source)
  2. 作用:把source指向的字符串拷贝到destin指向的字符串中
  3. 代码
char * my_strcpy(char * destin, const char * source)
{
	/***把source指向的字符串拷贝到destin指向的字符串中***/
	assert(destin != NULL && source != NULL);  //检查source和destin的指向是否为空
	char *address = destin;
	while(*destin++ = *source++)  //将source指向的字符复制给destin指向的字符
	{};
	return address;  //返回指向最终结果的指针
}

int main()
{
	char destination[10] = {0};
	char *source = "abcdefgh";

	my_strcpy(destination, source);
	printf("%s\n", destination);

	return 0;
}

2、strncpy函数

  1. 原型char * strncpy(char * str1, char * str2, int count)
  2. 作用:把str2指向的前count个字符拷贝到str1指向的字符串中
  3. 代码
#include <stdio.h>
#include <string.h>
#include <assert.h>

char * my_strncpy(char * str1, char * str2, int count)
{
	assert(str1 != NULL);  //检验str1是否为空
	while(count && (*str1++ = *str2++))  //把str2的前n个字符复制给str1
	{
		count--;  //长度随着复制的进行而减少
	}
	while(count--)
	{
		*str1++ = '\0';  //如果str2的长度小于count那就用NULL填充str1的剩余
	}
	return str1;
}

int main()
{
	char destination[10] = {0};
   	char *source = "abcdefgh";
   	int count = 5;

   	my_strncpy(destination, source, count);
   	printf("%s\n", destination);
	return 0;
}

3、strcmp函数

  1. 原型int strcmp(const char * str1, const char * str2)
  2. 作用:比较str1和str2,str1 > str2返回1,str1 == str2返回0
  3. 代码
int my_strcmp(const char * str1, const char * str2)
{
	/***比较str1和str2,str1 > str2返回大于0的数,str1 == str2返回0,str1 < str2返回小于0的数***/
	while( ! ((*str1 != *str2) && str1 != '\0'))
	{
		//如果str1和str2的字符相等且字符str1没有到末尾则进入循环
		str1++;  //指针str1向后加一位
		str2++;  //指针str2向后加一位
	}
	return (*str1 - *str2);  //返回跳出循环的str1和str2当前的字符的差值比较的结果(0或1或-1)
}

int main()
{
	char *buf1 = "aaaa",
		 *buf2 = "aaaab",
		 *buf3 = "aaaac";
    int ptr = 0;  //定义变量用来存放my_strcmp返回的值

    ptr = my_strcmp(buf2, buf1);
    if (ptr > 0)
       	printf("string 2 is bigger than string 1\n");
    else
       	printf("string 2 is smaller than string 1\n");

    ptr = my_strcmp(buf2, buf3);
    if (ptr > 0)
       	printf("string 2 is bigger than string 3\n");
    else
       	printf("string 2 is smaller than string 3\n");

	return 0;
}

4、strncmp函数

  1. 原型int strncmp(const char * str1, const char * str2, int count)
  2. 作用:比较str1和str2的前n个字符
  3. 代码
int my_strncmp(const char * str1, const char * str2, int count)
{
	/***比较str1和str2的前n个字符***/
	if(!count)
		return 0;
	while(--count && *str1 && *str1 == *str2)
	{
		str1++;
		str2++;
	}
	return (*str1 - *str2);
}

int main()
{
	char *str1 = "China is a nation!";
	char *str2 = "French is a nation!";
	int count = 5,
		ptr = 0;

	ptr = my_strncmp(str1, str2, count);
	if(ptr != 0)
    	printf("str1 is not equal to str2!\n");
	return 0;
}

5、stricmp函数

  1. 原型int my_stricmp(const char *str1, const char *str2)
  2. 作用:不区分大小写的比较str1和str2
  3. 代码
int my_stricmp(const char *str1, const char *str2)
{
	/***不区分大小写的比较str1和str2***/
	char ch1 = '0',
		 ch2 = '0';

	do
	{
		if((ch1 = (unsigned char)(*(str1++))) >= 'A' && ch1 <= 'Z')
			ch1 += 0x20;
		if((ch2 = (unsigned char)(*(str2++))) >= 'A' && ch2 <= 'Z')
			ch2 += 0x20;
	}while(ch1 && (ch1 == ch2));  // 判断是否相等且str1不为'\0',是则进入循环
	return (ch1 - ch2);  //返回两个数的大小
}

int main()
{
	char *str1= "ammana";
    char *str2 = "bibi";
    char *str3 = "AMMANA";
    int ptr = 0,
    	ptr1 = 0;

    ptr = my_stricmp(str1, str2);
    if(ptr > 0)
    	printf("str1 bigger than str2!\n");
    else
    	printf("str1 smaller than str2!\n");

    ptr1 = my_stricmp(str1, str3);
    if(ptr1 > 0)
    	printf("str1 bigger than str3!\n");
    else if(ptr1 < 0)
    	printf("str1 smaller than str3!\n");
    else
    	printf("str1 equal to str3!\n");

	return 0;
}

6、strlen函数

  1. 原型unsigned int strlen(const char * str)
  2. 作用:计算str的长度并返回
  3. 代码
unsigned int my_strlen(const char * str)
{
	/***计算str的长度并返回***/
	unsigned length = 0;  //定义无符号变量length统计str的长度
	while(*str != '\0')  //判断str指向的字符是否为'\0'
	{
		length++;  //长度加1
		str++;  //指向的地址向后加1位
	}
	return length;
}

int main()
{
	char * str = "abcdefgh";
	int len = 0;

	len = my_strlen(str);

	printf("%d\n", len);
	return 0;
}

7、strcat函数

  1. 原型char * strcat(char* destin, const char *source)
  2. 作用:连接两个字符串,将source连接到destin
  3. 代码
char * my_strcat(char* destin, const char *source)
{
	/***连接两个字符串,将source连接到destin***/
	char * temp = destin;  //定义temp指针变量存放destin的地址

	while(*temp)  //判断temp字符串是否读到了'\0'
	{
		temp++;  //将temp指针读到字符串末尾
	}

	while(*temp++ = *source++)	//把source字符串从temp末尾开始复制给temp
		{};

	return temp;  //返回链接好的字符串的指针
}

int main()
{
	/***对函数Strcat的调用***/
	char destination[25];  //定义一个大小为25的数组
    char *space = " ",
    	 *String = "C++!",
    	 *Hello = "Hello";

	strcpy(destination, Hello);  //进行拷贝
    my_strcat(destination, space);
    my_strcat(destination, String);

    printf("%s\n", destination);  //打印最终结果
	return 0;
}

8、strchr函数

  1. 原型char * strchr(char * str, const char c)
  2. 作用:查找str中c首次出现的位置,并返回位置或者NULL
  3. 代码
char * my_strchr(char * str, const char c)
{
	/***查找str中c首次出现的位置,并返回位置或者NULL***/
	while(*str != '\0' && *str != c)  //判断str是否为'\0'且等于c
	{
		str++;
	}
	//判断如果str等于c则返回与c匹配的str否则返回NULL
	return (*str == c ? str : NULL);
}

int main()
{
	char * string = "abcdefgh";
	char c = 'd',
		 *ptr = NULL,  //存放my_strchr的返回值

	ptr = my_strchr(string, c);
	if(ptr)
		printf("%c\n", c);
	else
		printf("Not Found!\n");

	return 0;
}

9、strrchr函数

  1. 原型char * strrchr(char * str, const char c)
  2. 作用:查找str中c最后一次出现的位置,并返回位置或者NULL
  3. 代码
char * my_strrchr(char * str, const char c)
{
	/***查找str中c最后一次出现的位置,并返回位置或者NULL***/
	char * end = str + strlen(str);  //定义指针end存放str的末尾地址

	while(*str != *end && *end != c)  //判断end没有到头部且没找到和c匹配的字符
	{
		end--;  //向前进行移动
	}

	if(*end == *str && *end != c)  //如果没找到则返回NULL
		return NULL;

	return end;
}

int main()
{
	char * string = "abcdefgh";
	char c = 'd',
		 *ptr = NULL,  //存放my_strchr的返回值

	ptr = my_strrchr(string, c);
	if(ptr)
		printf("%c\n", c);
	else
		printf("Not Found!\n");

	return 0;
}

10、strrev函数

  1. 原型char * strrev(char * str)
  2. 作用:翻转字符串并返回字符串指针
  3. 代码
char * my_strrev(char * str)
{
	/***翻转字符串并返回字符串指针***/
	if(str == NULL)
	{
		return NULL;
	}
	char *end = strlen(str) + str -1;
	char temp = '0';

	while(str != end)
	{
		temp = *str;
		*str = *end;
		*end = temp;
		str++;
		end--;
	}
	return str;
}

int main()
{
	/***只能逆置字符数组,而不能逆置字符串指针指向的字符串,
	    因为字符串指针指向的是字符串常量,常量不能被修改***/
	char str[] = "Hello World";  //定义str数组

   	printf("Before reversal: %s\n", str);
  	my_strrev(str);
   	printf("After reversal:  %s\n", str);
	return 0;
}

11、strdup函数

  1. 原型char * strdup(const char * str)
  2. 作用:拷贝字符串到新申请的内存中返回内存指针,否则返回NULL
  3. 代码
#include <assert.h>

char * my_strdup(const char * str)
{
	/***拷贝字符串到新申请的内存中返回内存指针,否则返回NULL***/
	char * temp = (char*)malloc(strlen(str) + 1);  //给temp申请内存
	assert(str != NULL && temp != NULL);  //进行检查是否为NULL
	strcpy(temp, str);  //进行拷贝
	return temp;  //返回的内存在堆中需要手动释放内存
}

int main()
{
	char *str = NULL,
		 *string = "abcde";

    str = my_strdup(string);
    printf("%s\n", str);
    free(str);  //释放内存

	return 0;
}

12、strstr函数

  1. 原型char * strstr(const char * str1, char * str2)
  2. 作用:查找str2在str1中出现的位置,找到返回位置,否则返回NULL
  3. 代码
char * my_strstr(const char * str1, char * str2)
{
	/***查找str2在str1中出现的位置,找到返回位置,否则返回NULL***/
	assert(str1 != NULL & str2 != NULL);  //检查str1和str2
	int len1 = strlen(str1);  //定len1来获取str1的长度
	int len2 = strlen(str2);  //定len2来获取str2的长度

	while(len1 >= len2)  //必须str1的长度大于str2的长度
	{
		len1--;  //str1的长度每一次减去一个
		if(!strncmp(str1, str2, len2))  //进行比较str2和str1的前len2个字符
		{
			return str2;  //如果匹配返回str2
		}
		str1++;  //str1每一次都要向后走一步
	}
	return NULL;
}

int main()
{
	char *str1 = "China is a nation!",
		 *str2 = "nation",
		 *ptr = NULL;

   	ptr = my_strstr(str1, str2);
   	printf("The string is: %s\n", ptr);
	return 0;
}

13、strpbrk函数

  1. 原型char *strpbrk(const char *str1, const char *str2)
  2. 作用:从str1的第一个字符向后检索,直到’\0’,如果当前字符存在于str2中,那么返回当前字符的地址,并停止检索.
  3. 代码
#include <assert.h>

char *my_strpbrk(const char *str1, const char *str2)
{
	/***strpbrk()从str1的第一个字符向后检索,直到'\0',如果当前字符存在于str2中,
	    那么返回当前字符的地址,并停止检索***/
	assert(str1 != NULL && str2 != NULL);
	const char *str3 = str2;

	while(*str1)  //判断石头人字符串str1是否结束
	{
		for(str3 = str2; *str3; ++str3)  //str2进行循环与str1的自费比较
		{
			if(*str1 == *str3)  //如果相等则进行str1的下一个判断
				break;
		}
		if(*str3)  //如果str3结束则结束比较
			break;
		str1++;
	}

	if(*str3 == '\0')  //如果str1到末尾则返回NULL
		str1 = NULL;
	return (char*)str1;
}

int main()
{
	char s1[] = "http://see.xidian.edu.cn/cpp/u/xitong/";
    char s2[] = "see";
    char *p = my_strpbrk(s1, s2);
    if(p)
    {
        printf("The result is: %s\n",p);
    }
    else
    {
        printf("Sorry!\n");
    }
	return 0;
}

14、strspn函数

  1. 原型int my_strspn(const char *str1, const char *str2)
  2. 作用:从参数str1字符串的开头计算连续的字符,而这些字符都完全是str2所指字符串中的字符。
  3. 代码
#include <assert.h>

/***strspn()函数检索区分大小写***/
int my_strspn(const char *str1, const char *str2)
{
	/***从参数str1字符串的开头计算连续的字符,而这些字符都完全是str2所指字符串中的字符。
	简单的说,若strspn()返回的数值为n,则代表字符串str1开头连续有n个字符都是属于字符串str2内的字符***/
	assert(str1 != NULL && str2 != NULL);
	const char *tmp = str1;  //临时变量存储str1的地址
	const char *str3;

	while(*tmp)
	{
		for(str3 = str2; *str3; ++str3)
		{
			if(*str3 == *tmp)  //判断str1是否存在str2的字符
				break;
		}
		if(*str3 == '\0')  //如果str2结束则跳出循环str1++
			break;
		tmp++;
	}

	return tmp - str1;  //返回差值,即str1共有几个连续的字符是str2中存在的
}

int main()
{
	char s1[] = "hello world!";
    char s2[] = "i am lihua";

    int p = my_strspn(s1, s2);

    printf("The result is:%d\n", p);
	return 0;
}

15、strtok函数

  1. 原型char *my_strtok(char *sou, char *delim)
  2. 作用:将字符串分割成一个个片段
  3. 代码
/***因strtok函数内部使用了静态指针,因此它不是线程安全的***/
static char *olds;  //定义全局变量来进行定位
char *my_strtok(char *sou, char *delim)
{
	/***strtok函数用来将字符串分割成一个个片段,
	在参数sou的字符串中发现到参数delim的分割字符时则会将该字符改为\0 字符***/
	//参数sou指向欲分割的字符串,参数delim为分割字符串
	//在第一次调用时,strtok()必需给予参数sou字符串,往后的调用则将参数sou设置成NULL
	//每次调用成功则返回下一个分割后的字符串指针

	char *token = NULL;
	if(sou == NULL)  //如果sou为空则将上一次的位置给sou
	{
		sou = olds;
	}

	/*将指针移到第一个非delim的位置*/
	sou += strspn(sou, delim);
	if(*sou == '\0')  //如果是结束符,则将结束符保存并退出函数
	{
		olds = sou;
		return NULL;
	}

	/*获取delim的字符在字符串sou中第一次出现的位置*/
	token = sou;
	sou = strpbrk(token, delim);

	if(sou == NULL)
	{
		olds = __rawmemchr (token, '\0');  //参考http://dev.wikl.net/89401.html
	}
	else
	{
		*sou = '\0';  //将分隔符的位置用'\0'替换
		olds = sou + 1;  //将olds指向下一次需要操作的位置
	}
	return token;
}

int main()
{
	//strtok处理的是函数的局部状态信息,所以不能同时解析两个字符串
	char sou[100] = " Micael_SX is so good";
	char *delim = " ";
	char *token;
	token = my_strtok(sou, delim);
	while(token != NULL)
	{
    	printf("%s\n", token);
    	token = my_strtok(NULL, delim);
	}
	return 0;
}

16、strsep函数

  1. 原型char *my_strsep(char **stringp, const char *delim)
  2. 作用:将字符串分割成一个个片段
  3. 代码
/***********************************************************
a:如果*stringp为NULL,则该函数不进行任何操作,直接返回NULL;
b:strsep每次都是从*stringp指向的位置开始搜索,搜索到任一分割字符之后,将其置为’\0’,
   并使*stringp指向它的下一个字符。如果找不到任何分割字符,则将*stringp置为NULL。
c:strsep内部没有使用静态指针,因而strsep是线程安全的。
d:strsep返回的子串有可能是空字符串,实际上,就是因为strtok无法返回空子串,才引入的strsep函数。
   不过strtok符合C89/C99标准,因而移植性更好。但strsep却不是。
e: "二八定律",即80%情况下分隔符只有一个字节,使用strchr完成,20%情况有多个字节,调用strpbrk完成
*************************************************************/

char *my_strsep(char **stringp, const char *delim)
{
	/***strsep函数用来将字符串分割成一个个片段***/
	char *begin,
		 *end;
	begin = *stringp;
	if(begin == NULL)
	{
		return NULL;
	}

	/*delim分隔符是单个字符的情况是非常频繁的,因此不需要使用代价昂贵的strpbrk函数
     而只需要调用strchr就能解决*/
	if(delim[0] == '\0' || delim[1] == '\0')
	{
		char ch = delim[0];
		if(ch == '\0')
		{
			end = NULL;
		}
		else
		{
			if(*begin == ch)
			{
				end = begin;
			}
			else if(*begin == '\0')
			{
				end = NULL;
			}
			else
			{
				end = strchr(begin + 1, ch);
			}
		}
	}
	else
	{
		/*delim有两个字符以上,才调用strpbrk*/
		end = strpbrk(begin, delim);
	}

	if(end)
	{
		/*用0封闭这个token;返回stringp,指向一个null指针*/
		*end++ = '\0';
		*stringp = end;
	}
	else
	{
		/*没有出现delim,这是最后一个token*/
		*stringp = NULL;
	}
	return begin;
}

int main()
{
	char source[] = "hello, world! welcome to China!";
    char delim[] = " ,!";

    char *s = strdup(source);
    char *token;
    for(token = my_strsep(&s, delim); token != NULL; token = my_strsep(&s, delim))
    {
        printf(token);
        printf("+");
    }
    printf("\n");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值