+ [2.4 模拟实现strstr](#24_strstr_404)
+ [2.5 模拟实现strcmp](#25_strcmp_427)
+ [2.6 模拟实现memcpy](#26_memcpy_445)
+ [2.7 模拟实现memmove](#27_memmove_465)
前言
C语言
中对字符和字符串的处理很是频繁,但是C语言
本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中- 字符串常量适用于那些对它不做修改的字符串函数
一、函数介绍
1.1 strlen
size\_t strlen ( const char \* str );
- 字符串已经
'\0'
作为结束标志,strlen函数返回的是在字符串中
‘\0’前面出现的字符个数(不包 含
’\0’` ) - 参数指向的字符串必须要以
'\0'
结束。 - 注意函数的返回值为
size_t
,是无符号的( 易错 )
注:
#include <stdio.h>
int main()
{
const char\* str1 = "abcdef";
const char\* str2 = "bbb";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
输出结果:
1.2 strcpy
char\* strcpy(char \* destination, const char\* source);
- 源字符串必须以
'\0'
结束 - 会将源字符串中的
'\0'
拷贝到目标空间 - 目标空间必须足够大,以确保能存放源字符串
- 目标空间必须可变
1.3 strcat
char \* strcat ( char \* destination, const char \* source );
- 源字符串必须以 ‘\0’ 结束
- 目标空间必须有足够的大,能容纳下源字符串的内容
- 目标空间必须可修改
- 字符串自己给自己追加,如何?
- 不可以,按上述规则自我追加的时候会覆盖掉某些值
1.4 strcmp
int strcmp ( const char \* str1, const char \* str2 );
- 第一个字符串大于第二个字符串,则返回大于
0
的数字 - 第一个字符串等于第二个字符串,则返回
0
- 第一个字符串小于第二个字符串,则返回小于
0
的数字 - 那么如何判断两个字符串?
- 从首字符依次对比,对比的是相应的
ASCII
码值
- 从首字符依次对比,对比的是相应的
1.5 strncpy
char \* strncpy ( char \* destination, const char \* source, size\_t num );
- 拷贝
num
个字符从源字符串到目标空间。 - 如果源字符串的长度小于
num
,则拷贝完源字符串之后,在目标的后边追加0
,直到num
个
1.6 strncat
char \* strncat ( char \* destination, const char \* source, size\_t num );
- 与
strncpy
对strcpy
的改进一样,strncat
也是对strcat
的改进,而且可以自我追加 - 参数和
strncpy
无异
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20];
char str2[20];
strcpy(str1, "To be ");
strcpy(str2, "or not to be");
strncat(str1, str2, 6);
puts(str1);
return 0;
}
输出结果:
1.7 strncmp
int strncmp ( const char \* str1, const char \* str2, size\_t num );
- 比较到出现另个字符不一样或者一个字符串结束或者
num
个字符全部比较完 - 也是对
strcmp
的改进
#include <stdio.h>
#include <string.h>
int main()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts("Looking for R2 astromech droids...");
for (n = 0; n < 3; n++)
if (strncmp(str[n], "R2xx", 2) == 0)
{
printf("found %s\n", str[n]);
}
return 0;
}
输出结果:
1.8 strstr
char \* strstr ( const char \*str1, const char \* str2);
- 去
str1
寻找与str2
相等的子串,然后把该子串的起始位置返回
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "This is a simple string";
char\* pch;
pch = strstr(str, "simple");
puts(pch);
return 0;
}
1.9 strtok
char \* strtok ( char \* str, const char \* sep );
sep
参数是个字符串,定义了用作分隔符的字符集合- 第一个参数指定一个字符串,它包含了
0
个或者多个由sep
字符串中一个或者多个分隔符分割的标记 strtok
函数找到str
中的下一个标记,并将其用\0
结尾,返回一个指向这个标记的指针(注:strtok
函数会改变被操作的字符串,所以在使用strtok
函数切分的字符串一般都是临时拷贝的内容
并且可修改)strtok
函数的第一个参数不为NULL
,函数将找到str
中第一个标记,strtok
函数将保存它在字符串
中的位置strtok
函数的第一个参数为NULL
,函数将在同一个字符串中被保存的位置开始,查找下一个标
记- 如果字符串中不存在更多的标记,则返回
NULL
指针
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "- This, a sample string.";
char\* pch;
printf("Splitting string \"%s\" into tokens:\n", str);
pch = strtok(str, " ,.-");
while (pch != NULL)
{
printf("%s\n", pch);
pch = strtok(NULL, " ,.-");
}
return 0;
}
输出结果:
1.10 strerror
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main()
{
FILE\* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
printf("Error opening file unexist.ent: %s\n", strerror(errno));
//errno: Last error number
return 0;
}
输出结果:
1.11 字符分类函数
- 字符转换:
int tolower ( int c );
int toupper ( int c );
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char str[] = "Test String.\n";
char c;
while (str[i])
{
c = str[i];
if (isupper(c))
c = tolower(c);
putchar(c);
i++;
}
return 0;
}
输出结果:
1.12 memcpy
void \* memcpy ( void \* destination, const void \* source, size\_t num );
- 函数
memcpy
从source
的位置开始向后复制num
个字节的数据到destination
的内存位置。 - 这个函数在遇到
'\0'
的时候并不会停下来。 - 如果
source
和destination
有任何的重叠,复制的结果都是未定义的
#include <stdio.h>
#include <string.h>
struct {
char name[40];
int age;
} person, person_copy;
int main()
{
char myname[] = "Pierre de Fermat";
/\* using memcpy to copy string: \*/
memcpy(person.name, myname, strlen(myname) + 1);
person.age = 46;
/\* using memcpy to copy structure: \*/
memcpy(&person_copy, &person, sizeof(person));
printf("person\_copy: %s, %d \n", person_copy.name, person_copy.age);
return 0;
}
输出结果:
1.13 memmove
void \* memmove ( void \* destination, const void \* source, size\_t num );
- 和
memcpy
的差别就是memmove
函数处理的源内存块和目标内存块是可以重叠的 - 如果源空间和目标空间出现重叠,就得使用
memmove
函数处理
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "memmove can be very useful......";
memmove(str + 20, str + 15, 11);
puts(str);
return 0;
}
输出结果:
1.14 memcmp
int memcmp ( const void \* ptr1,
const void \* ptr2,
size\_t num );
- 比较从ptr1和ptr2指针开始的num个字节
- 返回值如下:
#include <stdio.h>
#include <string.h>
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n = memcmp(buffer1, buffer2, sizeof(buffer1));
if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
return 0;
}
输出结果:
二、库函数的模拟实现
2.1 模拟实现strlen
- 三种方式:
方式1:
//计数器方式
int my\_strlen(const char\* str)
{
int count = 0;
while (\*str)
{
count++;
str++;
}
return count;
}
方式2:
//不能创建临时变量计数器
int my\_strlen(const char \* str)
{
if(\*str == '\0')
return 0;
else
return 1+my\_strlen(str+1);
}
方式3:
//指针-指针的方式
int my\_strlen(char \*s)
{
char \*p = s;
while(\*p != ‘\0’ )
p++;
return p-s;
}
2.2 模拟实现strcpy
参考代码:
//1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题目出自《高质量C/C++编程》书籍最后的试题部分
char\* my\_strcpy(char\* dest, const char\* src)
{
char\* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while ((\*dest++ = \*src++))
{
;
}
return ret;
}
2.3 模拟实现strcat
参考代码:
char\* my\_strcat(char\* dest, const char\* src)
{
char\* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (\*dest)
{
dest++;
}
while ((\*dest++ = \*src++))
{
;
}
return ret;
}
2.4 模拟实现strstr
参考代码:
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
rt(dest != NULL);
assert(src != NULL);
while ((*dest++ = *src++))
{
;
}
return ret;
}
### 2.3 模拟实现strcat
>
> 参考代码:
>
>
>
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{
;
}
return ret;
}
### 2.4 模拟实现strstr
>
> 参考代码:
>
[外链图片转存中...(img-p5e0Vdnw-4702036860140)]
[外链图片转存中...(img-NL8ubo4y-4702036860141)]
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**