自己编写的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;
}
参考:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!