目录
一、字符串函数
1、strlen函数
strlen功能
strlen返回值
strlen函数注意事项
模拟实现strlen函数
2、strcpy函数
strcpy功能
strcpy返回值
strcpy注意事项
模拟实现strcpy函数
3、strcat函数
strcat功能
strcat返回值
strcat注意事项
模拟实现strcat函数
4、strcmp函数
strcmp功能
strcmp返回值
模拟实现strcmp函数
5、strncpy函数(受限制的字符串拷贝)
strncpy功能
strncpy返回值
6、strncmp函数
strncmp功能
strncmp返回值
7、strstr函数
strstr功能
strstr返回值
模拟实现strstr函数
8、strtok函数
strtok功能
二、内存函数
1、memcpy函数(没有内存重叠的时候使用)
memcpy功能
memcpy返回值
mamcpy注意事项
模拟实现memcpy函数
2、memmove函数(有内存重叠的时候使用)
memmove功能
memmove返回值
模拟实现memmove函数
一、字符串函数
1、strlen函数
strlen功能
获取字符串的长度
strlen返回值
每个函数都返回字符串中的字符数,不包括字符串的结束符。
我们来看一个例子
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char* str1 = "abc";
char* str2 = "abcedf";
if (strlen(str1) - strlen(str2) > 0)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
return 0;
}
输出结果为?
hehe
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 7720)已退出,代码为 0。
按任意键关闭此窗口. . .
?strlen(str1)的结果是3,strlen(str2)的结果是6,所以是if的条件判断语句中,应该是3 - 6。但是不要忽略strlen函数返回的是size_t类型的数据,无符号整型,所以两个无符号整型运算之后的结果依然是无符号整型。因此,strlen(str1) -?strlen(str2) > 0,输出结果是hehe。
strlen函数注意事项
1、字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。 ?
2、参数指向的字符串必须要以 '\0' 结束。
3、注意函数的返回值为size_t,是无符号的
模拟实现strlen函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
int count = 0;
assert(str);
while (*(str++))
{
count++;
}
return count;
}
int main()
{
char str[] = { "abcdefg" };
int ret = my_strlen(&str);
printf("%d\n", ret);
return 0;
}
2、strcpy函数
strcpy功能
复制字符串
strcpy返回值
函数返回目标字符串的地址。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "abcdef";
char str2[] = "kpl";
strcpy(str1, str2);
printf("%s", str1);
return 0;
}
输出结果:
kpl
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 3724)已退出,代码为 0。
按任意键关闭此窗口. . .
strcpy注意事项
1、源字符串必须以 '\0' 结束。(没有'\0'strcpy函数就不知道什么时候拷贝结束了)
2、会将源字符串中的 '\0' 拷贝到目标空间。
3、目标空间必须足够大,以确保能存放源字符串。(防止造成越界访问)
4、目标空间必须是可被写的。(目标空间不能被const修饰)
模拟实现strcpy函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char string[80];
my_strcpy(string, "Hello world from ");
strcat(string, "strcpy ");
strcat(string, "and ");
strcat(string, "strcat!");
printf("String = %s\n", string);
return 0;
}
在之前的博客中,有讲解过模拟strcpy函数,这里就不重复讲解了。
3、strcat函数
strcat功能
字符串追加
strcat返回值
返回的是目标字符串的地址。
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "abcd";
char str2[] = "efgh";
char* ret = strcat(str1, str2);
printf("%s", ret);
return 0;
}
输出结果
abcdefgh
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 15000)已退出,代码为 0。
按任意键关闭此窗口. . .
strcat注意事项
1、源字符串必须以 '\0' 结束。(没有结束标志会导致程序崩溃,因为程序不知道追加到哪里停止)
2、目标空间必须有足够的大,能容纳下源字符串的内容。
我们看到的str1的长度为5,明显只可以容纳str1的内容,不能再继续容纳str2的三个字符,这样会导致越界访问,造成程序的崩溃 ?
3、目标空间必须可修改。 (我们需要对目标空间进行字符串的追加,所以目标空间一定可以被修改,目标空间不能被const修饰)
模拟实现strcat函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
char* my_strcat(char* dest, char* src)
{
char* ret = dest;
//1、找到目标字符串的末尾\0
while (*dest)
{
dest++;
}
//2、追加源字符串直到\0
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = { "abc" };
char arr2[] = { "def" };
char* ret = my_strcat(arr1, arr2);
printf("%s\n", ret);
return 0;
}
4、strcmp函数
strcmp功能
比较字符串大小?
strcmp返回值
?这个函数是两个字符串,从第一个字符开始逐一比较,若字符不相等则返回一个不等于0的整型(参照上述图标),若字符相等,则继续比较下一个字符,直到比较到两个字符串的结束符'\0'。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "abcd";
char str2[] = "abc";
int ret = strcmp(str1, str2);
printf("%d", ret);
return 0;
}
输出结果
1
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 13560)已退出,代码为 0。
按任意键关闭此窗口. . .
模拟实现strcmp函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int my_strcmp(const char* s1, const char* s2)
{
while (*s1 && *s2)
{
if (*s1 == *s2)
{
s1++;
s2++;
}
else
{
return *s1 - *s2;
}
}
return 0;
}
int main()
{
char string1[] = "The quick brown dog jumps over the lazy fox";
char string2[] = "The QUICK brown dog jumps over the lazy fox";
char tmp[20];
int result;
/* Case sensitive */
printf("Compare strings:\n\t%s\n\t%s\n\n", string1, string2);
result = my_strcmp(string1, string2);
if (result > 0)
strcpy(tmp, "greater than");
else if (result < 0)
strcpy(tmp, "less than");
else
strcpy(tmp, "equal to");
printf("\tstrcmp: String 1 is %s string 2\n", tmp);
return 0;
}
5、strncpy函数(受限制的字符串拷贝)
strncpy功能
将源字符串中的n个字符拷贝到目标字符串当中
strncpy返回值
返回的是目标字符串的地址。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "abcd";
char str2[] = "kpl";
char* ret = strncpy(str1, str2, 2);
printf("%s", ret);
return 0;
}
输出结果
kpcd
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 8276)已退出,代码为 0。
按任意键关闭此窗口. . .
注意事项:
1、被指定复制字符串的个数可以大于源字符串的长度。(被指定的元素可以是字符也可以是‘\0’
2、目标字符串必须足够大,以确保能存放源字符串。(防止造成越界访问)
3、目标字符串必须是可被修改的。
6、strncmp函数
strncmp功能
比较两个字符串中一定数量的字符。?
strncmp返回值
?比较的方法和strcmp是一样的。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "abcd";
char str2[] = "abkl";
int ret1 = strncmp(str1, str2, 2);
int ret2 = strncmp(str1, str2, 3);
printf("%d\n", ret1);
printf("%d\n", ret2);
return 0;
}
7、strstr函数
strstr功能
?查找子串
strstr返回值
函数返回的是子串在目标字符串当中的地址。如果没有找到,则返回的是空指针,NULL。如果要查找的子串是长度为0的字符串,函数返回的是目标字符串的起始地址。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "abcdefdgh";
char str2[] = "d";
char* ret = strstr(str1, str2);
printf("%s", ret);
return 0;
}
输出结果
defdgh
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 6676)已退出,代码为 0。
按任意键关闭此窗口. . .
模拟实现strstr函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
char* my_strstr(char* p1, char* p2)
{
char* s1;
char* s2;
char* pt = p1;
if (*p2 == 0)
{
return p1;
}
while (*pt)
{
s1 = pt;
s2 = p2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == 0)
{
return pt;
}
pt++;
}
return NULL;
}
int main()
{
char str[] = "lazy";
char string[] = "The quick brown dog jumps over the lazy fox";
char fmt1[] = " 1 2 3 4 5";
char fmt2[] = "12345678901234567890123456789012345678901234567890";
char* pdest;
int result;
printf("String to be searched:\n\t%s\n", string);
printf("\t%s\n\t%s\n\n", fmt1, fmt2);
pdest = my_strstr(string, str);
result = pdest - string + 1;
if (pdest != NULL)
printf("%s found at position %d\n\n", str, result);
else
printf("%s not found\n", str);
return 0;
}
8、strtok函数
strtok功能
字符串分割函数
1、sep参数是个字符串,定义了用作分隔符的字符集合 2、第一个参数指定一个字符串,表示的是,要被分割的字符串 3、strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。) 4、strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。 5、strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。 6、如果字符串中不存在更多的标记,则返回 NULL 指针。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "by@bite.cn";
char str2[200] = { 0 };
char sep[] = "@.";
strcpy(str2, str1);
char* ret = NULL;
for (ret = strtok(str2, sep); ret != NULL; ret = strtok(NULL, sep))
{
printf("%s ", ret);
}
}
输出结果
by bite cn
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 1092)已退出,代码为 0。
按任意键关闭此窗口. . .
二、内存函数
1、memcpy函数(没有内存重叠的时候使用)
memcpy功能
拷贝内存空间的字符。
memcpy返回值
返回的是,目标内存的地址。之所以返回类型是void *,是因为该函数是以一个字节为单位进行拷贝的,并不知道拷贝的是整型、字符还是结构体。void *可以用来接收各种各样的地址。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[100] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[100] = { 0 };
int i = 0;
memcpy(arr2, arr1, 10 * sizeof(int));
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
输出结果
1 2 3 4 5 6 7 8 9 10
F:\VS编程文件\CProject\9月\test_9_16\Debug\test_9_16.exe (进程 12584)已退出,代码为 0。
按任意键关闭此窗口. . .
mamcpy注意事项
1、函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2、这个函数在遇到 '\0' 的时候并不会停下来。
3、如果source和destination有任何的重叠,复制的结果都是未定义的。
模拟实现memcpy函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
void* my_memcpy(void* dest, void* src, size_t n)
{
void* ret = dest;
assert(dest && src);
while (n--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return dest;
}
int main()
{
char arr1[20] = { "123456789" };
char arr2[20] = { "4567" };
my_memcpy(arr1, arr2, 4);
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
2、memmove函数(有内存重叠的时候使用)
memmove功能
将一个内存区移动到另外一个
memmove返回值
?返回的是,目标内存的地址。
使用方法和memcpy是一样的。
模拟实现memmove函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
//模拟memmove函数
void* my_memmove(void *dest,const void *src,size_t n)//存在重叠部分的内存拷贝,优先拷贝重叠部分的内存
{
void* ret = dest;
assert(dest && src);
if (dest < src)
{
while (n--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (n--)
{
*((char*)dest + n) = *((char*)src + n);
}
}
return ret;
}
//打印整形数组
void print(int* p, int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", p[i]);
}
printf("\n");
}
int main()
{
int arr1[20] = { 1,2,3,4,5,6,7,8,9 };
int arr2[20] = { 6,7,8,9 };
my_memmove(arr1 + 2, arr1, 16);
print(arr1, sizeof(arr1) / sizeof(arr1[0]));
print(arr2, sizeof(arr2) / sizeof(arr2[0]));
return 0;
}
|