字符和字符串函数
1.前言
相信大家写代码的时候,对字符串的处理是很频繁的,如果我们用自定义函数来处理,不免有点麻烦,今天我带大家了解并模拟实现c语言库里提供的函数,可以大大简化我们的工作。
2.strlen函数
2.1介绍
size_t strlen ( const char * str );//库函数的定义
(1)该函数是用来求字符串长度的,字符串以‘\0’结尾,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数**(不包含 ‘\0’ )**。
(2)该函数的返回类型是size_t,这是c语言库里面typedef了一下,其实是unsigned int类型。
(3)使用该函数要确保传的字符数组和字符串以’\0’结束。
这里我们来看一下第二点要注意的地方
#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;
}
这个程序的结果是打印str2>str1,大家可能会困惑,str1的长度不是明显大于str2吗,这是因为这个函数的返回值是无符号类型的,两个无符号类型的数字相减肯定是大于零的,所以该程序是输出下面这个。
2.2模拟实现
int my_strlen(const char* s)
{
int count = 0;
while (*s++)
{
count++;
}
return count;
}
int my_strlen1(const char* s)
{
if (*s == '\0')
{
return;
}
return my_strlen(s + 1) + 1;
}
int main()
{
char* s = "asdascas";
printf("%d", my_strlen1(s));
return 0;
}
3.strcpy、strncpy函数
3.1介绍
char* strcpy(char * destination, const char * source );
char * strncpy(char * destination, const char * source,size_t num);
该函数的作用是将source的字符串考拷贝到destination中。
(1)source字符串必须以‘\0’结尾
(2)这个函数会把source的‘\0’拷贝过去
(3)使用该函数注意destination的空间要大于source的空间
(4)将source中的num个字符拷贝到destination中去
(5)如果num的个数大于source中的个数,后面的会自动补‘\0’
3.2模拟实现
char* my_strcpy(char* des, const char* sour)
{
char* ret = des;
while (*des++ = *sour++);
return ret;
}
int main()
{
char* sour = "jadha";
char des[20] = {0};
my_strcpy(des, sour);
printf("%s",des);
}
4.strcat、strncat函数
char * strcat ( char * destination, const char * source );
char* strncat(char* destination,const char * source,size_t num);
4.1介绍
该函数的作用是将source字符串连接到destination后面。
(1)目标空间必须可修改
(2)destination和source字符串必须以‘\0’结尾
(3)不能自己连接到自己
(4)destination的空间要足够大
这里我们来解释一下为什么不能传两个相同的指针过去(自己连接自己)
4.2模拟实现
char* my_stract(char* des, const char* sour)
{
char* ret = des;
while (*des != '\0')
{
des++;
}
while (*des++ = *sour++);
return ret;
}
int main()
{
char des[20]= "asd ";
char* sour = "asd";
printf("%s",my_stract(des,sour));
return 0;
}
5.strcmp、strncmp函数
5.1介绍
int strcmp(const char* str1,const char* str2);
int strncmp(const char* str1,const char* str2,size_t num);
这个函数的作用是比较两个字符串的大小。
(1)str1和str2俩个字符串必须要以‘\0’结尾
(2)num表示比较到第几个字符。
(1)str1比str2大返回大于零的数,相等返回零,小返回负数
5.2模拟实现
int my_strcmp(const char* s, const char* s1)
{
while (*s == *s1)
{
if (*s == '\0')
return 0;
s++;
s1++;
}
return *s - *s1;
}
6.strstr函数
6.1介绍
char * strstr ( const char *str1, const char * str2);
(1)该字符串的作用是在str1找到第一次出现str2的地方
(2)如果找到了则返回地址,没找到返回null
6.2模拟实现
char* my_strstr(const char* s1, const char* s2)
{
char* begin1 = s1;
char* end1 = s1;
char* begin2 = s2;
char* end2 = s2;
while (*begin1 != '\0')
{
while (*end1 == *end2 && *end1 != '\0' && *end2 != '\0')
{
end1++;
end2++;
}
//找到了返回首字符地址
if (*end2 == '\0')
{
return begin1;
}
//没找到,调整指针位置,继续一下轮循环
else
{
begin1++;
end1 = begin1;
end2 = begin2;
}
}
return NULL;
}
7.strtok函数
7.1介绍
char * strtok ( char * str, const char * sep );
(1)该函数的作用是通过特定符号来切割字符串。
(2)sep参数是个字符串,定义了用作分隔符的字符集合。
(3)str参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分 割的标记。
(4)该函数会找到下一个分割符并将其变成’\0’,然后返回指向该处的指针,如果遍历到str末尾,会返回NULL(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
(5)若该字符串不含分割字符集中的任意一个字符,则返回NULL
(6)strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
(7)strtok函数的第一个参数为 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," ,.-");
//(6)(7)
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
8.strerror函数
8.1介绍
char * strerror ( int errnum );
(1)该函数的作用是返回错误码对应的错误信息
(2)#include <errno.h> //必须包含的头文件
9.字符函数
9.1字符分类函数介绍
(1)iscntrl() 任何控制字符
(2)isspace() 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
(3)isdigit 十进制数字 0~9
(4)isxdigit 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A-F
(5)islower 小写字母a~z
(6)isupper 大写字母A~Z
(7)isalpha 字母a-z或A~Z
(8)isalnum 字母或者数字,a-z,A-Z,0~9
(9)ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
(10)isgraph 任何图形字符
(11)isprint 任何可打印字符,包括图形字符和空白字符
总结:如果上面的函数的参数符合后面的则返回真,否则为假
9.2字符转换函数介绍
int tolower ( int c );
int toupper ( int c );
(1)这两个函数的作用是将小写字符转换成大写字符,小写字符转换成大写字符。
/* isupper example */
#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;
}
10.memcpy函数
10.1介绍
void * memcpy ( void * destination, const void * source, size_t num );
(1)该函数的作用是将source中的num个字节考拷贝到destination上去
(2)num的单位是字节
(3)遇到‘\0’不会停下来(这一点是该函数和strcpy、strncpy不一样的地方)
(4)假如dsetination和source的空间有重叠的部分,那么该函数的结果是不可预料的,因为可能会覆盖
(5)使用的时候要确保destination的空间足够大
10.2模拟实现
#include <stdio.h>
#include <assert.h>
void* my_memcpy(void* destination, const void* source, size_t num)
{
assert(destination && source);
void* ret = destination;
while (num--)
{
*(char*)destination = *(char*)source;
(char*)destination = (char*)destination + 1;
(char*)source = (char*)source + 1;
}
return ret;
}
int main()
{
char destination[20] = { 0 };
char* source = "hxbjqhxbcqyi";
printf("%s",(char*)my_memcpy(destination,source,6));
return 0;
}
11.memmove
11.1介绍
void * memmove ( void * destination, const void * source, size_t num );
(1)该函数的作用和memcpy函数作用一样
(2)该函数可以使用在有重叠部分的两个空间
11.2模拟实现
void* my_memmove(void* destination, const void* source, size_t num)
{
assert(destination && source);
void* ret = destination;
//从前往后拷贝
if (destination < source)
{
while (num--)
{
*(char*)destination = *(char*)source;
(char*)destination = (char*)destination + 1;
(char*)source = (char*)source + 1;
}
}
//从后往前拷贝
else
{
while (num--)
{
*((char*)destination + num+1) = *((char*)source + num+1);
}
}
return ret;
}
int main()
{
char arr[20] = { 's','d','v','c','w','r','t','x','q','d','m' };
printf("%s", (char*)my_memmove(arr+3, arr, 6));
return 0;
}
12.memcmp
12.1介绍
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
(1)该函数的作用是比较ptr1和ptr2中前num个字节的大小
(2)num的单位是字节
(3)大于返回大于0,小于返回小于0,等于返回0
/* memcmp example */
#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;
}