字符串操作函数和内存操作函数介绍及模拟实现
strlen
strlen介绍
size_t strlen ( const char * str );
strlen函数返回的是在字符串中
'\0'
前面出现的字符个数,不包括'\0'
参数所指向的字符串必须以'\0'
结束
strlen的模拟实现
size_t my_strlen(const char* string)
{
assert(string);
size_t count = 0;
while (*string)
{
count++;
string++;
}
return count;
}
int main()
{
char arr1[] = "qwertyu";
printf("%d\n", my_strlen(arr1));
return 0;
}
strcpy
strcpy介绍
char * strcpy ( char * destination, const char * source );
源字符串必须以
'\0'
结束。会改变从目的字符串的第一个地址里的内容,直至copy完源字符串的内容,会将源字符串的'\0'
拷贝到目标空间。目标空间必须足够大,以确保能存放源字符串。
strcpy的模拟实现
char* my_strcpy(char* destination,const char* source)
{
char* ret = destination;
assert(destination&&source);
//while (*source)
//{
// *destination = *source;
// destination++;
// source++;
//}
//*destination = '\0';
while (*destination++ = *source++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
my_strcpy(arr1,arr2);
//strcpy(arr1,arr2);
return 0;
}
strncpy
strncpy介绍
char * strncpy ( char * destination, const char * source, size_t num );
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加0,直至num个。
值得注意的是,strncpy在copy结束的时候仍然是以目标字符串的'\0'
作为字符串的结束标志。
strncpy的模拟实现
char* my_strncpy(char* destination,const char* resource ,size_t n)
{
assert(destination&&resource);
char* start = destination;
while (n--)
{
*destination = *resource;
destination++;
resource++;
}
return start;
}
int main()
{
char arr1[] = "xxxxxxxxxxxxx";
my_strncpy(arr1,"abcde",10);
printf("%s\n",arr1);
return 0;
}
strcat
strcat介绍
char * strcat ( char * destination, const char * source )0
在目的字符串的
'\0'
处,开始追加源字符串的内容,源字符串的首字符会占据掉目的字符串的'\0'
所在的空间。同时也会将源字符串中的'\0'
追加过去。
strcat的模拟实现
char* my_strcat(char* destination,const char* source)
{
assert(destination&&source);
char* ret = destination;
while (*destination)
{
destination++;
}
//while (*source)
//{
// *destination = *source;
// destination++;
// source++;
//}
while (*destination++ = *source++)
{
;
}
return ret;
}
int main()
{
char arr1[30] = "hello ";
char arr2[] = "world";
my_strcat(arr1, arr2);
return 0;
}
strncat
strncat介绍
char * strncat ( char * destination, const char * source, size_t num )
可指定追加的字符数量。它的首字符会占据目标字符串
'\0'
的位置,同时它会在追加的末尾加上一个'\0'
,使得目标空间最后还是一个字符串。
strncat的模拟实现
char* my_strncat(char* string1,const char* string2,size_t n)
{
assert(string1&&string2);
char* start = string1;
//在目的地址的后面追加指定个数的字符后,再追加一个\0
while (*string1)
{
string1++;
}
while (n--)
{
*string1 = *string2;
string1++;
string2++;
}
*string1 = '\0';
return string1;
}
int main()
{
char arr1[20] = "xxxxx";
my_strncat(arr1,"abcd",3);
printf("%s\n",arr1);
return 0;
}
strcmp
strcmp介绍
int strcmp ( const char * str1, const char * str2 );
比较两个字符串,实际为比较两个字符串中对应位置字符的ASSII码值的大小。
若第一个字符串大于第二个字符串,则返回大于0的数字
若第一个字符串小于第二个字符串,则返回小于0的数字
若第一个字符串等于第二个字符串,则返回0
strcmp的模拟实现
int my_strcmp(const char* string1,const char* string2)
{
assert(string1&&string2);
//while (*string1&&*string2)
//{
// if (*string1 > *string2)
// {
// return 1;
// }
// else if (*string1 < *string2)
// {
// return -1;
// }
// else
// {
// string1++;
// string2++;
// }
//}
//只有两个字符串完全相等时,才会return 0
while (*string1==*string2)
{
if (*string1=='\0')
{
return 0;
}
else
{
string1++;
string2++;
}
}
if (*string1>*string2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char arr1[] = "a";
char arr2[] = "abc";
//printf("%d\n", strcmp(arr1, arr2));
printf("%d\n", my_strcmp(arr1, arr2));
return 0;
}
strncmp
strncmp介绍
int strncmp ( const char * str1, const char * str2, size_t num )
比较到出现两个字符不一样或者num个字符全部比较完
strncmp的模拟实现
int my_strncmp(const char* string1, const char* string2, size_t n)
{
assert(string1 && string2);
//指定次数n
while (n--)
{
if (*string1 == *string2)
{
string1++;
string2++;
}
else if (*string1 > *string2)
{
return 1;
}
else
{
return -1;
}
}
return 0;
}
int main()
{
char arr1[] = "abczefg";
char arr2[] = "abckghjk";
printf("%d\n", my_strncmp(arr1, arr2, 2));
return 0;
}
strstr
strstr介绍
char * strstr ( char * str1, const char * str2 )
在str1字符串中查找str2字符串,若有,则返回str2字符串在str1中的地址(是指首字符的地址);若无,则返回空指针
strstr的模拟实现
char* my_strstr(char* string1,char* string2)
{
assert(string1&&string2);
//首先排除一个特殊的情况
if (*string2=='\0')
{
return string1;
}
//考虑一次循环过程,需要两个临时指针s1,s2来随时控制在两个字符串中的位置
//一个指针cp,来记录在循环过程中指向s1中某个字符的位置
char* s1 = NULL;
char* s2 = NULL;
char* cp = string1;
while (*cp)
{
s1 = cp;
s2 = string2;
while (*s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abcdefgh";
printf("%s\n", my_strstr(arr1, "fg"));
return 0;
}
memcpy
memcpy介绍
void * memcpy ( void * destination, const void * source, size_t num )
它从source的位置开始向后复制num个字节的数据到destination的内存位置。
在遇到'\0'
的时候不会停下来
如果source和destination有任何的重叠,复制的结果都是未定义的,并不会得到预期想要的效果。
memcpy的模拟实现
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*)source)++;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[] = {11,22,33,44,55};
my_memcpy(arr1,arr2,9);
return 0;
}
memmove
memmove介绍
void * memmove ( void * destination, const void * source, size_t num )
与strcpy相比,memmove不仅可以对字符串进行操作,还可以对整型,结构体等进行操作;它们的最大差别在于memmove还可以处理源内存块和目标内存块相重合的情况。比如:在同一个数组的内部进行操作。
memmove的模拟实现
void* my_memmove(void* destination,const void* source,size_t num)
{
assert(destination && source);
void* ret = destination;
//向前move和向后move
if (destination<source)
{
//向前move
while (num--)
{
*(char*)destination = *(char*)source;
((char*)destination)++;
((char*)source)++;
}
}
else
{
//向后move
while (num--)
{
*((char*)destination + num) = *((char*)source + num);
}
}
return ret;
}
int main()
{
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
my_memmove(arr1+2,arr1,20);
return 0;
}
memcmp
memcmp介绍
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
比较从ptr1和ptr2指针开始的num个字节,返回的规则同strcmp
memcmp的模拟实现
int my_memcmp(const void* ptr1,const void* ptr2,size_t num)
{
assert(ptr1&&ptr2);
while (num--)
{
if ((*(char*)ptr1)> (*(char*)ptr2))
{
return 1;
}
else if ((*(char*)ptr1) < (*(char*)ptr2))
{
return -1;
}
else
{
((char*)ptr1)++;
((char*)ptr2)++;
}
}
return 0;
}
int main()
{
int arr1[] = {1,2,3};
int arr2[] = {1,2,2};
printf("%d\n", my_memcmp(arr1, arr2, 8));
}
其它函数
strtok
char * strtok ( char * str, const char * delimiters )
delimiters参数是一个字符串,定义了用作分隔符的字符集合
str参数指定一个字符串,它包含0个或者多个由delimiters字符串中的一个或者多个分隔符分割的标记。
strtok函数在str中从左至右找到delimiters中的一个符号标记,并将其替换为'\0'
,返回一个指向以这个'\0'
结尾的字符串(strtok将会改变被操作的字符串,所以使用strtok函数切分的字符串一般都是临时拷贝的内容)
strtok函数的第一个参数不为NULL
,函数将找到str中出现的第一个标记,并保存它在字符串中的位置
strtok函数的第一个参数为NULL
,函数将在上一次字符串中被保存的位置开始,查找下一个标记
如果字符串中不存在更多的标记,将会返回NULL
int main()
{
char arr[] = "abc@qq.com";
//char arr[] = "192.168.120.87";
char sep[] = "@.";
//记录好位置之后找标记
char* ret=strtok(arr,sep);
printf("%s\n",ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
//char* ret = NULL;
//for (ret=strtok(arr,sep);ret!='\0';ret=strtok(NULL,sep))
//{
// printf("%s\n",ret);
//}
return 0;
}
如下,以"@."
为分隔符,将字符串拆分为3个部分。
如下,是一种更为标准的输出格式。
int main()
{
//char arr[] = "abc@qq.com";
char arr[] = "192.168.120.87";
char sep[] = ".";
//记录好位置之后找标记
//char* ret=strtok(arr,sep);
//printf("%s\n",ret);
//ret = strtok(NULL, sep);
//printf("%s\n", ret);
//ret = strtok(NULL, sep);
//printf("%s\n", ret);
char* ret = NULL;
for (ret=strtok(arr,sep);ret!='\0';ret=strtok(NULL,sep))
{
printf("%s\n",ret);
}
return 0;
}
strerror
char * strerror ( int errnum )
返回错误码所对应的错误信息
与之相对应的perror会打印出错误信息,并可以自己定义输出格式
举例说明
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
printf("%s\n", strerror(5));
printf("%s\n",strerror(6));
return 0;
}
正确的使用方式
#include <errno.h>
int main()
{
FILE* ret=fopen("test.txt","r");
if (ret=='\0')
{
//如果有错误,会将错误码存到errno中
printf("%s\n",strerror(errno));
//perror("错误信息是:");
}
fclose(ret);
return 0;
}
perror 的使用:
字符分类函数和字符转换函数islower,isupper,tolower,toupper
两个例子
int main()
{
int ret=islower('A');
printf("%d\n", ret);
ret = isupper('A');
printf("%d\n", ret);
ret = tolower('F');
printf("%c\n", ret);
ret = toupper('a');
printf("%c\n", ret);
return 0;
}
int main()
{
char arr[] = "I Have An Apple";
//如果是大写就转换为小写,然后输出;否则直接输出
int i = 0;
while (arr[i])
{
if (isupper(arr[i]))
{
//printf("%c",tolower(arr[i]));
arr[i] = tolower(arr[i]);
}
printf("%c",arr[i]);
i++;
}
return 0;
}