字符串函数
一.函数介绍
1.strlen函数
strlen函数是专门用来一个字符串长度的函数,例如下面
int main()
{
char arr[] = "abcdef";//abcdef\0
int len = strlen(arr);//随机值
printf("%d\n", len);
return 0;
}
strlen 函数是遇到 ‘ \0 ’就会停止计数。
假如字符串中没有‘\0’,那么strlen函数怎么计算呢?!
答案是随机值,它会在内存中一直找一直到直到找到‘\0’
strlen函数的返回值是size_t,是无符号的,在一些计算中要注意!
2.strcpy函数
strcpy函数类似给字符串赋值的函数,它的形式如下所示:
int main()
{
char name[3] = "";
char arr[] = "abcdef";
strcpy(name, arr);
printf("%s\n", name);
return 0;
}
strcpy函数的第一个参数是目的地,第二个参数是源头,就类似从源头开始向目的地赋值,注意两点,一是目的地的空间足够大,而且目标空间必须可变。二是这个函数会把’\0’也拷贝过来,所以要确保拷贝的字符串一定要有’\0’,否则拷贝会出错。
strcmp函数
#include <stdio.h>
#include <string.h>
int main ()
{
char key[] = "apple";
char buffer[80];
do {
printf ("Guess my favorite fruit? ");
fflush (stdout);
scanf ("%79s",buffer);
} while (strcmp (key,buffer) != 0);
puts ("Correct answer!");
return 0;
}
这个函数比较的是字符的ASCII值,不是比较字符串的长度。
strncpy
参数形式:
strncpy函数比strcpy函数多了个参数num,用来决定拷贝几个字节的数据
用法:
/* strncpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]= "To be or not to be";
char str2[40];
char str3[40];
/* copy to sized buffer (overflow safe): */
strncpy ( str2, str1, sizeof(str2) );
/* partial copy (only 5 chars): */
strncpy ( str3, str2, 5 );
str3[5] = '\0'; /* null character manually added */
puts (str1);
puts (str2);
puts (str3);
return 0;
}
结果:
strstr函数
这个函数是用来查找字符串中的字串
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
if (pch != NULL)
strncpy (pch,"sample",6);
puts (str);
return 0;
}
模拟实现strstr函数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
char* my_strstr(char* str1, char* str2)
{
char* s1 = str1;
char* s2 = str2;
char* p = str1;
while (*p)
{
s1 = p;
s2 = str2;
while (*s1 == *s2 && *s1 != '\0'&&*s2!='\0')
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return p;
}
p++;
}
return NULL;
}
int main()
{
char a[40] = "aasdffg";
char b[] = "asd";
char *p = my_strstr(a, b);
if (p)
{
printf("%s", p);
}
else
{
printf("子串不存在");
}
return 0;
}
该函数是在一个字符串中查找字串,该函数模拟实现情况考虑较为复杂,下面以图示的方法讲解。
运行结果:
模拟实现memcpy函数
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
(char*)dest = (char*)dest + 1;
(char*)src = (char*)src + 1;
}
return ret;
}
这个函数的类型是void类型,是因为它要符合各种类型的内存拷贝,所以模拟实现要进行类型转换,返回类型是void**是因为适配字符类型。
试行代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
(char*)dest = (char*)dest + 1;
(char*)src = (char*)src + 1;
}
return ret;
}
int main()
{
int a[] = { 1,2,3,4 };
int b[10] = { 0 };
my_memcpy(b, a, 16);
for (int i = 0; i < 4; i++)
{
printf("%d ", b[i]);
}
return 0;
}
结果:
模拟实现memmove函数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void* my_memmove(void* dest, void* src, size_t num)
{
void* ret = dest;
if (dest < src)
{
//目标地址小于源头地址
while (num--)
{
*(char*)dest = *(char*)src;
(char*)dest = (char*)dest + 1;
(char*)src = (char*)src + 1;
}
}
else
{
//源头地址大于目标地址
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int src[10] = { 1,2,3,4,5,6,7,8,9,10 };
int dest[10] = { 0 };
my_memmove(src+2, src, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", src[i]);
}
}
memmove函数是针对自身一个数组内存移动的函数
模拟实现这个函数,分两种情况,一是目标数组地址在源头数组的前面,二是目标数组地址在源头数组的后面。
1.源头地址在目标源头的前面
代码实现部分:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void* my_memmove(void* dest, void* src, size_t num)
{
void* ret = dest;
if (dest < src)
{
//目标地址小于源头地址
while (num--)
{
*(char*)dest = *(char*)src;
(char*)dest = (char*)dest + 1;
(char*)src = (char*)src + 1;
}
}
else
{
//源头地址大于目标地址
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int src[10] = { 1,2,3,4,5,6,7,8,9,10 };
int dest[10] = { 0 };
my_memmove(src+2, src, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", src[i]);
}
}
运行结果:
2.源头地址在目标地址的后面
运行代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void* my_memmove(void* dest, void* src, size_t num)
{
void* ret = dest;
if (dest < src)
{
//目标地址小于源头地址
while (num--)
{
*(char*)dest = *(char*)src;
(char*)dest = (char*)dest + 1;
(char*)src = (char*)src + 1;
}
}
else
{
//源头地址大于目标地址
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int src[10] = { 1,2,3,4,5,6,7,8,9,10 };
int dest[10] = { 0 };
my_memmove(src, src+4, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", src[i]);
}
}
运行结果: