C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在
常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数。本篇文章为大家详解八个常用的字符串操作函数,同时我们尝试模拟实现该函数,加深我们对函数的认识和了解。
目录
1. strlen
1.1 strlen()函数简介
strlen(): 返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
函数原型
注:
需包含<string.h>头文件
字符串以 '\0' 作为结束标志。
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的(unsigned int)( 易错 )
1.2 strlen()的基本使用
int main() { const char* p = "Hello world"; int len = (int)strlen(p); printf("%d\n", len); return 0; }
1.3 模拟实现strlen()函数
创建临时变量
#include <stdio.h> #include <assert.h> // 创建临时变量实现strlen int my_strlen(const char* str) { int count = 0; assert(str);//不为空指针 while (*str) { count++; str++; } return count; } int main() { const char* ch = "abcdef"; int len = my_strlen(ch); printf("%d\n", len);// 6 return 0; }
不创建临时变量(递归实现)
// 不创建临时变量实现strlen int my_strlen(const char* str) { if (*str == '\0') { return 0; } else { return 1 + my_strlen(str + 1); } } int main() { const char* ch = "abcdef"; int len = my_strlen(ch); printf("%d\n", len);// 6 return 0; }
2. strcpy
2.1 strcpy()函数简介
strcpy(): 将源指向的C字符串复制到目标指向的数组中,包括终止空字符(并在该点停止)。
函数原型
注:Destination(目的地),Source(源自)
需包含<string.h>头文件
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
2.2 strcpy()的基本使用
int main() { char ch1[20] = { 0 }; const char ch2[] = "hello world"; strcpy(ch1, ch2); printf("%s\n", ch1); return 0; }
2.3 模拟实现strcpy()函数
#include <stdio.h>
#include <assert.h>
//模拟实现strcpy函数
char* my_strcpy(char* des, const char* sou)
{
char* ret = des;
assert(des && sou);//不为空指针
// 拷贝
while (*des++ = *sou++)
{
;
}
return ret;//返回目标地址
}
int main()
{
char ch1[20] = { 0 };
const char ch2[] = "hello world";
my_strcpy(ch1, ch2);
printf("%s\n", ch1); // hello world
return 0;
}
3. strcat
3.1 strcat()函数简介
strcat(): 将源字符串的副本追加到目标字符串。目标中的终止空字符(\0)被源的第一个字符覆盖,并在目标中两者的连接形成的新字符串的末尾包含一个空字符(\0)。
函数原型
注:
需包含<string.h>头文件
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改
不可自己追加追加
3.2 strcat()的基本使用
int main() { char ch1[30] = "hello "; const char ch2[] = "world"; strcat(ch1, ch2); printf("%s\n", ch1); return 0; }
3.3 模拟实现strcat()函数
#include <stdio.h>
#include <assert.h>
//模拟实现strcat
char* my_strcat(char* des, const char* sou)
{
assert(des && sou);
char* ret = des;
//找到目标字符串的‘\0’
while (*des)
{
des++;
}
//追加
while (*des++ = *sou++)
{
;
}
return ret;//返回目标地址
}
int main()
{
char ch1[30] = "hello ";
const char ch2[] = "world";
my_strcat(ch1, ch2);
printf("%s\n", ch1);// hello world
return 0;
}
4. strcmp
4.1 strcmp()函数简介
strcmp(): 比较每个字符串的第一个字符。如果它们相等,则继续执行以下对,直到字符不同或到达一个终止的空字符为止。
函数原型
返回值:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
注:比较大小的依据:不是比较两个字符串的长度,而是比较两个字符串中字符的ASCII码值大小
4.2 strcmp()的基本使用
int main() { const char* p1 = "abcdef";// a 的ASCII码为 97 const char* p2 = "bcdef";// b 的ASCII码为 98 int ret = strcmp(p1, p2); printf("%d\n", ret); return 0; }
4.3 模拟实现strcmp()函数
#include <stdio.h>
#include <assert.h>
// 模拟实现strcmp
int my_strcmp(const char* des, const char* sou)
{
assert(des && sou);
//如果两个字符相等,继续往后面找到不同字符进行比较
while (*des == *sou)
{
//元素全部相等
if (*des == '\0')
{
return 0;
}
des++;
sou++;
}
//返回值
return *des - *sou;
}
int main()
{
const char* p1 = "abcdef";// a 的ASCII码为 97
const char* p2 = "bcdef";// b 的ASCII码为 98
int ret = my_strcmp(p1, p2);
printf("%d\n", ret);
return 0;
}
5. strncpy
5.1 strncpy()函数简介
strncpy():将源字符串的num个字符复制到目标。如果源字符串的结束在复制字符之前找到,目标将用0填充,直到总共向其写入了num字符 。
函数原型
注:
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
5.2 strncpy的基本使用
int main() { char p1[20] = "abcd"; const char p2[] = "hello"; strncpy(p1, p2,2 ); printf("%s\n", p1); return 0; }
5.3 模拟实现strncpy()函数
#include <stdio.h>
#include <assert.h>
// 模拟实现strncpy
char* my_strncpy(char* des, const char* sou, unsigned int num)
{
assert(des && sou);
char* ret = des;
//拷贝
while (num && (*des++ = *sou++))//num范围
{
num--;
}
//范围大于源字符串全部置0
if (num)
{
while (--num)//先--再使用,避免多进入循环一次
{
*des++ = '\0';
}
}
return des;//返回目标值
}
int main()
{
char p1[20] = "abcd\0aaaaaaa";
const char p2[] = "hello";
my_strncpy(p1, p2, 8);
printf("%s\n", p1);
return 0;
}
6. strncat
6.1 strncat() 函数简介
strncat(): 将源字符串的num个字符加上一个结束空字符追加到目标。如果源字符串中的追加字符串的长度小于num,则只复制终止空字符之前的内容。
函数原型
注:
需包含<string.h>头文件
如果源字符串中的追加字符串的长度小于num,则只复制终止空字符之前的内容。
6.2 strncat的基本使用
int main() { char p1[20] = "hello"; const char p2[] = "world"; strncat(p1, p2, 3); printf("%s\n", p1); return 0; }
6.3 模拟实现strncat()函数
#include <stdio.h>
#include <assert.h>
// 模拟实现strncat
char* my_strncat(char* des, const char* sou, unsigned int num)
{
assert(des && sou);//不为空
char* ret = des;
//找到目标字符串的'\0'
while (*des)
{
des++;
}
//按给定范围追加
while (num && (*des = *sou))
{
num--;
des++;
sou++;
}
return ret;//返回目标地址
}
int main()
{
char ch1[20] = "hello\0aaaaaaa";
char ch2[] = "world";
my_strncat(ch1, ch2, 8);
printf("%s\n", ch1);
return 0;
}
7. strncmp
7.1 strncmp()函数简介
strncmp(): 比较到出现一个字符串结束或者num个字符全部比较完
函数原型
返回值
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字注:
比较是两个字符串一起比较相同num范围
比较的是两个字符串中字符的ASCII码值大小
7.2 strncmp的基本使用
int main() { const char* p1 = "abcdef"; const char* p2 = "bcde"; int ret = strncmp(p1, p2, 2);//比较的是ab-bc printf("%d\n", ret); return 0; }
7.3 模拟实现strncmp()函数
#include <stdio.h>
#include <assert.h>
int my_strncmp(const char* p1, const char* p2, unsigned int num)
{
assert(p1 && p2);//不为空
//先找到不相同的字符
while (num && (*p1 == *p2))
{
num--;
p1++;
p2++;
}
if (num == 0)//num个字符都相等
return 0;
else
return *p1 - *p2;
}
int main()
{
const char* p1 = "dbcdef";
const char* p2 = "dzde";
int ret = my_strncmp(p1, p2, 2);//比较的是db-dz
printf("%d\n", ret);// -24
return 0;
}
8. strstr
8.1 strstr()函数简介
strstr(): 查找子字符串,返回指向目标字符串中需要查找到的第一个出现的指针,如果str2不是str1的一部分,则返回一个空指针
函数原型
注:
如果源字符串中出现多个需查找的子字符串,返回的是第一个出现的地址
8.2 strstr的基本使用
int main() { const char* p1 = "abcdefg"; const char* p2 = "cd"; char* ret = strstr(p1, p2); printf("%s\n", ret); return 0; }
8.3 模拟实现strstr()函数
#include <stdio.h>
#include <assert.h>
//模拟实现strstr
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 && p2);//不为空
char* s1 = NULL;
char* s2 = NULL;//使p1和p2发生改变
char* cur = (char*)p1;//用来存放查找到地址
if (*p2 == '\0')//查找子字符串只存放了'\0'
{
return (char*)p1;
}
//开始查找
while (*cur)
{
s1 = cur;
s2 = (char*)p2;
//查找到一个相同的字符串,判断后面是不是全部相同,两个字符串不为\0,s1等于s2
while (*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
// 判断s1被查完既查找字符串长度大于源字符串abc-abcd
if (*s1 == '\0')
{
return NULL;
}
//判断p2是否全部查找完了
if (*s2 == '\0')
{
return cur;//返回第一次出现的地址
}
cur++;
}
return NULL;//源字符串查找完了没找到子字符串中的内容,返回空指针
}
int main()
{
const char* p1 = "abcdefg";
const char* p2 = "cd";
char* ret = my_strstr(p1, p2);
printf("%s\n", ret);// cdefg
return 0;
}