自己编写的str操作函数

 


1 strcpy()

此函数原型为char *strcpy(char* dest, const char *src),功能为拷贝字符串内容到目的串,把 src 所指向的内容拷贝到 dest,并返回 dest 地址。

实现程序如下:

#include <stdio.h>
#include <assert.h>

char *myStrcpy(char *strDest, const char *strSrc)
{
	char *addrStr = strDest;

	assert((strDest != NULL) && (strSrc != NULL));

	while ((*strDest++ = *strSrc++) != '\0');

	return addrStr;
}

int main()
{
	char str1[6];
	char *str2 = "hello";

	myStrcpy(str1, str2);
	printf("%s\n", str1);  // 输出:hello

	return 0;
}

返回类型为 char *,主要是为了实现链式表达式。例如:

myStrcpy(strDest, myStrcpy(strDest1, strSrc));

可以将 strSrc 复制到 strDest1 与 strDest 中,也就是说,可以将函数的返回值做为另一个函数的参数。


2 strncpy()

此函数原型为char *strncpy(char* dest, const char *src, size_t n),功能为拷贝字符串的前 n 个字符到目的串,并返回 dest 地址。注意:不像 strcpy(),strncpy() 不会向 dest 追加结束标记 '\0';

实现程序如下:

#include <stdio.h>
#include <assert.h>

char *myStrcpy(char *strDest, const char *strSrc, int n)
{
	assert(strDest != NULL && strSrc != NULL);

	// 保存目标字符串的首地址
	char *addrStr = strDest;
	while ((n--) && (*strDest++ = *strSrc++) != '\0');

	// 如果n大于strSrc的字符个数,将自动补'\0'
	if (n > 0)
	{
		while (--n)
		{
			*strDest++ = '\0';
		}
	}

	return addrStr;
}

int main()
{
	char str1[6];
	char *str2 = "hello";

	myStrcpy(str1, str2, 3);
	str1[3] = '\0';
	printf("%s\n", str1);  // 输出:hel

	return 0;
}

3 strcmp()

此函数的函数原型为int strcmp(const char *str1, const char *str2),功能为比较两个字符串。

  • 当str1指向的字符串大于str2指向的字符串时,返回正数;
  • 当str1指向的字符串等于str2指向的字符串时,返回0;
  • 当str1指向的字符串小于str2指向的字符串时,返回负数。

实现程序如下:

#include <stdio.h>
#include <assert.h>

int myStrcmp(const char *str1, const char *str2)
{
	assert(str1 != NULL && str2 != NULL);

	while (*str1 == *str2)
	{
		if (*str1 == '\0') // 直到检索到字符串尾仍然相等,则返回0
			return 0;

		str1++;
		str2++;
	}

	return *str1 - *str2; // 前面未执行return 0,说明字符串不相等
}

int main()
{
	printf("%d\n", myStrcmp("aaaa", "aaaa")); // 返回0
	printf("%d\n", myStrcmp("aaaa", "aaa1")); // 返回正数
	printf("%d\n", myStrcmp("akkk", "faaa")); // 注意:这里返回负数 [只比较首次2个不相同的字符大小] 

	return 0;
}

4 strcat()

此函数原型为char *strcat(char *dest, const char *src),功能为连接两个字符串,把 src 连接到 dest 后面,并返回 dest 地址。

实现程序如下:

#include <stdio.h>
#include <assert.h>

char *myStrcat(char *strDest, const char *strSrc)
{
	char *addrStr = strDest;

	assert(strDest != NULL && strSrc != NULL);

	while (*strDest != '\0')
	{
		strDest++;
	}
	while ((*strDest++ = *strSrc++) != '\0');

	return addrStr;
}

int main()
{
	char str1[12] = "hello";
	char str2[10] = " world";
	myStrcat(str1, str2);

	printf("%s\n", str1); // 输出:hello world

	return 0;
}

5 strlen()

此函数原型为unsigned in strlen(const char *str),功能为返回字符串 str 的长度(不包括 '\0')。

实现程序如下:

#include <stdio.h>
#include <assert.h>

//自己编写的strlen函数
int myStrlen(const char  *str)
{
	int length = 0;

	while (*str != '\0')
	{
		str++;
		length++;
	}

	return length;
}

int main()
{
	printf("%d\n", myStrlen("abc")); // 输出:3

	return 0;
}

6 strrev()

此函数原型为char *strrev(char *str),功能为反转字符串,返回字符串指针。

实现程序如下:

#include <stdio.h>
#include <assert.h>

char *myStrrev(char *str)
{
	char  temp;
	char  *start = str;
	char  *end = str + myStrlen(str) - 1; // 指向倒数第二个字符(不指向'\0')

	assert(str != NULL);

	while (start<end)
	{
		// 交换字符
		temp = *start;
		*start = *end;
		*end = temp;

		start++;
		end--;
	}

	return(str);
}

int main()
{
	char arr[20] = "abcdef";
	printf("%s\n", myStrrev(arr)); // 输出:fedcba

	return 0;
}

7 strchr()、strrchr()

(1)strchr() 函数原型为char *strchr(char *str, const char c),功能为查找 str 中首次出现 c 的位置(指针),如果有,则返回出现位置,否则返回 NULL。

(2)strrchr() 函数原型为char *strrchr(char *str, const char c),功能为查找 str 中最后一次出现 c 的位置(指针),如果有,则返回出现位置,否则返回 NULL。

实现程序如下:

#include <stdio.h>
#include <assert.h>

char *myStrchr(char *str, const char c)
{
	assert(str != NULL);

	while (str != '\0')
	{
		if (*str == c)
			return str;

		str++;
	}

	return NULL;
}

char *myStrrchr(char *str, const char c)
{
	assert(str != NULL);

	char  *temp = str + myStrlen(str); // temp指向字符串最后一个字符'\0'
	while (temp != str)
	{
		if (*temp == c)
			return temp;

		temp--;
	}

	return NULL;
}

int main()
{
	char str[3] = "ab";
	printf("%p\n", str); // 输出:010FF77C
	printf("%p\n", myStrchr(str, 'b')); // 输出:010FF77D

	char str2[4] = "abb";
	printf("%p\n", str2); // 输出:010FF770
	printf("%p\n", myStrrchr(str2, 'b')); // 输出:010FF772
	printf("%p\n", myStrrchr(str2, 'c')); // 输出:0(NULL)

	return 0;
}

8 strdup()

此函数原型为char *strdup(const char *str),功能为 strdup() 会先用 maolloc() 配置与参数 str 字符串相同的空间大小,然后将参数 str 字符串的内容复制到该内存地址,然后把该地址返回。若失败,返回 NULL。要注意,返回的指针指向的内存在堆中,所以要手动释放。

实现程序如下:

#include <stdio.h>
#include <stdlib.h>

char *myStrdup(const char *str)
{
	char *temp = NULL;

	temp = (char*)malloc(myStrlen(str) + 1);
	if (temp == NULL)
		exit(-1);

	strcpy(temp, str);

	return temp;
}

int main()
{
	char str1[] = "strdup";
	char *str2;

	str2 = myStrdup(str1);
	printf("%s\n", str2); // 输出:strdup

	return 0;
}

9 strstr()

此函数原型为char *strstr(char *str, const char * substr);,功能为检索子串在字符串中首次出现的位置,找到则返回位置,否则返回 NULL。

实现程序如下:

#include <stdio.h>
#include <assert.h>

char* myStrstr(char* str, const char* substr)
{
	char *pStr;
	const char *pSubstr;

	assert(str != NULL && substr != NULL);

	// 遍历str字符串
	while (*str != '\0')
	{
		pStr = str; // 这里很重要
		pSubstr = substr;
		// 用来遍历子串
		do
		{
			if (*pSubstr == '\0') // 到了substr的结束位置,返回str位置 
				return str;
		}
		while (*pStr++ == *pSubstr++);
		str++;
	}

	return NULL;
}

int main()
{
	char *str = "HelloWorldHelloWorld";
	char *substr = "World";
	char *s = myStrstr(str, substr);
	printf("%s\n", s);  // 输出:WorldHelloWorld

	return 0;
}

10 atoi()、itoa()

C语言中常用到字符串与数字之间的相互转换,常见的此类库函数有 atoi (字符串转换成整型数)、itoa (整型数转换成字符串)、atof (字符串转换成浮点数)、atol (字符串转换成长整型数)、ltoa (长整型数转换为字符串)等。这里暂时只实现 atoi() 和 itoa()。


(1)atoi()

实现程序如下:

#include<stdio.h>
#include <assert.h>

int myAtoi(char *str)
{
	assert(str != NULL);

	// 跳过开头的空格字符
	while (*str == ' ') 
	{
		str++;
	}

	// '0xA1'是不打印字符,一般是占两个字节的汉字
	while ((*str == (char)0xA1) && (*(str + 1) == (char)0xAA))
	{
		str += 2;
	}

	// 确定符号位
	int sign = 1;
	if (*str == '+' || *str == '-')
	{
		sign = (*str = '-') ? -1 : 1;
		*str++;
	}

	// 获得字符串转换的数字
	int value = 0;
	while (*str >= '0'	&& *str <= '9')
	{
		value = value * 10 + (*str - '0');
		*str++;
	}

	return sign * value;
}

int main()
{
	printf("%d\n", myAtoi("12345")); // 输出:12345

	return 0;
}

(2)itoa()

实现程序如下:

#include <stdio.h> 

char *myItoa(int num)
{
	char str[1024];
	int sign = num, i = 0, j = 0;
	char temp[11];

	// 如果为负数,则转换为其绝对值
	if (sign<0)
	{
		num = -num;
	};

	// 数字转换为倒序的字符数组
	do
	{
		temp[i] = num % 10 + '0';
		num /= 10;
		i++;
	} while (num>0);

	// 字符数组加上“符号”
	if (sign<0)
	{
		temp[i++] = '-';
	}

	// 转换为字符串
	temp[i] = '\0';

	// 将字符串反转
	i--;
	while (i >= 0)
	{
		str[j] = temp[i];
		j++;
		i--;
	}
	str[j] = '\0';

	return str;
}

int main()
{
	printf("%s\n", myItoa(-12345)); // 输出:-12345

	return 0;
}

参考:

C语言常用字符串操作函数总结


posted @   fengMisaka  阅读(715)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示