字符串函数<2>
- 字符串查找
strstr
strtok - 错误信息报告
strerror - 字符分类函数
- 内存操作函数
memcpy
memmove
memset
memcmp
1.strstr(字符串查找)
1.1 语法与功能
- 功能:在一个字符串中查找一个局部的字符串,例如在“ hellow world "中查找“ world ”类似这样的,具体的注意事项我们接下来继续讲解!
- 语法:
头文件:string.h
char * strstr ( const char *str1, const char * str2);
str1是源字符串,str2是要查找的字符串
char*返回的地址是在str1中找到的字符串的首地址.
1.2 代码示例
#include<stdio.h>
#include<string.h>
int main()
{
char s[] = "hellow world!";
char* p = strstr(s, "world");
printf("%s\n", p);
return 0;
}
1.3 模拟实现(strstr)
#include<stdio.h>
const char* my_strstr(const char* str1, const char* str2)
{
const char* p1 = str1;//被查找字符串
const char* p2 = str2;//要查找字符串
const char* p = str1;//返回值
while (*p1)
{
p = p1;
while (*p1 == *p2)
{
p1++;
p2++;
}
if (*p2 == 0)
return p;
else
p2 = str2;
p1++;
}
return NULL;
}
int main()
{
char s1[] = "hellow world!!!";
char s2[] = "loc";
const char* p = my_strstr(s1, s2);
if (p == NULL)
printf("找不到!!!\n");
else
printf("%s\n", p);
return 0;
}
2.strtok(字符串查找)
2.1 语法与功能
- char * strtok ( char * str, const char * sep );
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。) - strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
2.2 代码示例
#include<stdio.h>
#include<string.h>
int main()
{
char s[] = "he1ow wo2rl3d!";
for (char* p = strtok(s, "123"); p != NULL; p = strtok(NULL, "123"))
{
printf("%s\n", p);
}
return 0;
}
3.strerror(错误信息报告)
3.1 语法与功能
在这里我们先不讲解语法与功能,我们先来给大家展示一下此函数的一段代码!
从这张图中我们可以知道,strerror函数具有将错误码转换为错误信息的功能!
而C语言专属的错误码是errno,在C语言中errno可以在程序中自动接收最近的错误码!
所以完整的使用是strerror(errno);
功能:strerror函数具有将错误码转换为错误信息的功能!
语法:
头文件:string.h(errno的头文件是:errno.h)
char * strerror ( int errnum )
返回的是一个错误信息的字符串的首地址,int errnum是一个错误码!
然后接下来,我们来用代码来讲解:
3.2 示例代码
在这里有一部分的知识是后边讲的是文件操作这一部分的,首先打开文件有一个顺序流程: 打开文件 - 使用文件 - 关闭文件。我们只需要知道 “若一个文件打开失败,则fopen函数将会返回一个空指针NULL”。而代码中的“test.txt”这个文件我没有创建,就一定会返回空指针!
我们运行程序,可得
返回的错误信息的意思就是:没有该文件或文件夹。在这里C语言专属的错误码是errno,在C语言中errno可以在程序中自动接收最近的错误码!
相信大家到这里已经大概了解了,在我们写程序中让计算机以人的语言准确告诉我们错误是不是更高效呢!!!
4.字符分类函数
4.1 功能与语法
功能:可以按照ASCII码值将字符分为“数字字符”,“大写字母”,“小写字母”等各种字符。
头文件:<ctype.h>
例子:int iscntrl ( int c );
接收的是字符的ASCII码值
若符合条件则返回真
4.2 代码示例
大概的用法都一样,大家尽量自己下去尝试!
内存操作函数
5.memcpy(字节复制)
5.1 功能与语法
void * memcpy ( void * destination, const void * source, size_t num );
- 头文件:<string.h>
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。(内存地址的重复使用,则复制的结果是无意义的)
5.2 代码示例
#include<string.h>
int main()
{
const int arr = 1145258561;
//1145258561的二进制补码如下:
//01000100 01000011 01000010 01000001
// d c b a
char s[5] = "";//初始化字符串
memcpy(s, &arr, 4);
printf("%s\n", s);
return 0;
}
函数memcpy从arr的位置开始向后复制4个字节的数据到s的内存位置。
5.3 模拟实现memcpy
#include<stdio.h>
//模拟实现memcpy
void* my_memcpy(void* destination, const void* source, size_t num)
{
void* p = destination;
unsigned int i = 0;
for (i = 0; i < num; i++)
{
*((char*)destination + i) = *((char*)source + i);
}
return p;
}
int main()
{
const int arr = 1145258561;
//1145258561的二进制补码如下:
//01000100 01000011 01000010 01000001
// d c b a
char s[5] = "";//初始化字符串
my_memcpy(s, &arr, 4);
printf("%s\n", s);
return 0;
}
6.memmove(字节复制加强版)
6.1 功能与语法
void * memmove ( void * destination, const void * source, size_t num );
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
6.2 示例代码
memmove的作用和memcpy的作用相同,这样说吧!memmove比memcpy帅一点,处理的源内存块和目标内存块是可以重叠的。
6.3 模拟实现memmove
#include<stdio.h>
//模拟实现memmove
void* my_memmove(void* destination, const void* source, size_t num)
{
void* p = destination;
if (source < destination)
{
destination = (char*)destination + num-1;
source = (char*)source + num -1;
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination - 1;
source = (char*)source - 1;
}
}
else
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
return p;
}
int main()
{
char s[] = "123456789";//14
printf("%s\n", s);
char* p = my_memmove(s, s+3, 5);
printf("%s\n",p );
return 0;
}
7.memcmp(比较字节内容)
memcmp和strncmp十分的类似,都是一个字节一个字节的比较大小,但区别是strncmp只能比较字符串,而memcmp能力更强一些!
7.1 功能与语法
int memcmp ( const void * ptr1,const void * ptr2,size_t num );
- 比较从ptr1和ptr2指针开始的num个字节
- 返回值如下:
7.2 代码示例
7.3 模拟实现memcmp
#include<stdio.h>
//模拟实现memcmp
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
unsigned int i = 0;
for (i = 0; i < num; i++)
{
if (*( (char*)ptr1 + i) != *((char*)ptr2 + i) )
return *( (char*)ptr1 + i) - *( (char*)ptr2 + i);
}
return 0;
}
int main()
{
int arr1[] = { 1,2,5,0 };
int arr2[] = { 1,2,0,5 };
printf("%d\n", my_memcmp(arr1, arr2, 4 * sizeof(arr1[0])));
return 0;
}