当前位置:网站首页>字符串和内存函数
字符串和内存函数
2022-07-16 09:45:00 【刀剑侠客】
字符串
基础知识
用双引号引起的一串内容是字符串。用双引号引起的字符串,代表的是一个指向无名数组起始的字符指针,该数组被双引号之间的字符以及一个额外的二进制为0的字符’\0’初始化。
我们通常见到的字符串有两种:1. 字符数组:例如:char str = "hello world";
2. 常量字符串:例如:char* pstr = "hello world";
需要注意的几点:
- 字符串是以’\0’为结束标志的,如果使用
sizof操作符计算字符数组中字符的个数,结果得减去1. - 常量字符串是不能修改的,将常量字符串赋值给一个指针的话,本质上是将其首字符的地址赋给这个指针变量
有关库函数以及模拟实现
strlen
size_t strlen(const char* str);
strlen是求字符串长度的库函数,想求出字符串的长度,目的是要找到'\0'
size_t是typedef为unsigned int类型创建的别名
模拟实现
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)//const放在*的左边,指针指向的内容不能直接被修改
{
assert(str);//断言,保证指针的有效性
size_t num = 0;
while (*str++)//当不再满足循环中的条件时,指针指向的是\0后
{
num++;
}
return num;
}
int main()
{
char arr[] = "hello world";
int ret = my_strlen(arr);
printf("%d\n", ret);
return 0;
}
strcpy
char* strcpy(char* destination, const char* source);
strcpy是拷贝字符串的库函数,有几点需要注意的:
- 源字符串必须以
'\0'结束. - 会将源字符串的
'\0'拷贝到目标空间里去. strcpy的返回值是目标函数的起始地址(目的是为了链式访问).
模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* destination, const char* source)
{
assert(destination && source);//断言,保证指针的有效性
char* start = destination;
while (*destination++ = *source++)//源字符拷贝到目标字符后,指针向后移动一位,当拷贝的是'\0'时,不再满足循环条件
{
;
}
return start;
}
int main()
{
char arr1[20] = "happy everyday";
char arr2[] = "hello world";
char* ret = my_strcpy(arr1, arr2);
printf("%s\n", ret);
return 0;
}
strcat
char* strcat(char* destination, const char* source);
strcat是字符串追加的函数
先是要找到
'\0',从该位置起开始进行字符串的追加。为了保证字符串追加之后任然是一个字符串,得在追加有效字符的同时,在最后追加一个
'\0'。自己给自己增加,一般不用
strcat.
模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* destination, const char* source)
{
assert(destination && source);
char* start = destination;
//先找到'\0'
while (*destination)
{
destination++;
}
//循环结束,指针指向'\0'
//正式开始字符串的增加
while (*destination++ = *source++)
{
;
}
return start;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
char* ret = my_strcat(arr1, arr2);
printf("%s\n", ret);
return 0;
}
strcmp
int strcmp(const char* str1, const char* str2);
strcmp是字符串比较函数,是一对字符一对字符的比较
比较规则
- 首先是从第一对字符开始比较,要是相等,则比较下一对字符,如果
str1指向的字符大于str2指向的字符,返回一个大于0的数;如果str1指向的字符小于str2指向的字符,返回一个小于0的数。 - 当
str1和str2同时指向'\0',并且前面对应的字符都相等,则返回0。
模拟实现
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while ((*str1 == *str2) && (*str1 != '\0') && (*str2 != '\0'))
{
str1++;
str2++;
}
//跳出循环时,1.*str1 != *str2
// 2.*str1 == *str2 == '\0'
//version_1
/*if (*str1 > *str2) { return 1; } else if (*str1 < *str2) { return -1; } return 0;*/
//version_2
return (*str1 - *str2);
}
int main()
{
char str1[10] = "abcd";
char str2[10] = "abcd";
int ret = my_strcmp(str1, str2);
if (ret < 0)
{
printf("<\n");
}
else if (ret == 0)
{
printf("=\n");
}
else
{
printf(">\n");
}
return 0;
}
上述strcpy strcat strcmp都是长度不受限制的字符串函数,接下来的strncpy strncat strncmp都是长度受限制的字符串函数
strncpy
char* strncpy(char* destination, const char* source, size_t num);
跟strcpy相似的是:strncpy也是字符串拷贝函数,只不过多了一个长度的限制,单位是字节.
模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strncpy(char* destination, const char* source, size_t num)
{
assert(destination && source);//断言,保证指针的有效性
char* start = destination;
while (num--)//num次循环
{
*destination++ = *source++;
}
//拷贝'\0'
*destination = '\0';
return start;
}
int main()
{
char arr1[20] = "hello world!";
char arr2[] = "Good luck to you.";
char* ret = my_strncpy(arr1, arr2, 17);
printf("%s\n", ret);
return 0;
}
strncat
char* strncat(char* destination, const char* source, size_t num);
跟strcat类似,strncat也是字符串追加函数,只不过是有长度的限制,为了保证追加字符之后任然是一个字符串,应在最后在追加一个\0。
模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strncat(char* destination, const char* source, size_t num)
{
assert(destination && source);
char* start = destination;
//找到'\0'
while (*destination)
{
destination++;
}
//开始追加字符
while (num--)
{
*destination++ = *source++;
}
//追加'\0'
*destination = '\0';
return start;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world.";
char* ret = my_strncat(arr1, arr2, 6);
printf("%s\n", ret);
return 0;
}
strncmp
int strcmp(const char* str1, const char* str2, size_t num);
跟strcmp一样,strncmp只是在原有的基础上有了长度的限制,实现的方法其实还是类似的。
模拟实现
#include <stdio.h>
#include <assert.h>
int my_strncmp(const char* str1, const char* str2, size_t num)
{
assert(str1 && str2);
while (--num)
{
//不满足if的条件
// 1.*str1 != *str2
// 2.*str1 == *str2 == '\0'
if ((*str1 == *str2) && (*str1 != '\0') && (*str2 != '\0'))
{
str1++;
str2++;
}
}
return (*str1 - *str2);
}
int main()
{
char arr1[] = "abcd";
char arr2[] = "abce";
int ret = my_strncmp(arr1, arr2, 3);
if (ret < 0)
{
printf("<\n");
}
else if (ret == 0)
{
printf("=\n");
}
else
{
printf(">\n");
}
}
strstr
const char* strstr(const char* str1, const char* str2);
在字符串中找子串用strstr,找到返回字符串与字串第一个相同字符的地址,找不到返回空指针。
模拟实现
按照下面给出的例子以及函数的返回值综合分析。
str1和str2分别指向数组arr1和数组arr2的起始地址,不要直接用str1和str2两个指针维护这两块空间。- 创建两个指针变量
s1和s2并分别将str1和str2的值赋给s1和s2,显然,要是真的能找到字串,光靠s1和s2并不能带回返回值,故创建第三个指针p,用于维护数组arr1。 - 每次开始比较的时候,
s1从p指向的地方开始,s2从str2指向的地方开始,每对字符开始比较,直到s2指向\0前,每对字符都相等,说明arr2是arr1的子串。p指针在比较不相同的情况下,每次移动一位,结束标志为p指向\0。
#include <stdio.h>
#include <assert.h>
//dabc
//abc
const char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);//断言,保证指针的有效性
const char* s1 = str1;
const char* s2 = str2;
const char* p = str1;
while (*p)
{
//开始比较
while ((*s1 == *s2) && (*s2 != '\0'))
{
s1++;
s2++;
}
//1. *s1 != *s2
//2. *s2 == '\0'
if (*s2 == '\0')
{
return p;
}
p++;
s1 = p;
s2 = str2;
}
//p指向'\0'
return NULL;
}
int main()
{
char arr1[] = "bbabcd";
char arr2[] = "abcdd";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到该字符串");
return;
}
else
{
printf("%s\n", ret);
}
return 0;
}
内存相关函数
memcpy
void* memcpy(void* destination, const void* source, size_t num);
内存拷贝函数
memcpy,是从source位置向后复制num个字节的数据到destination内存位置。适用于两块独立的内存空间,对于两块重叠的空间,结果是未定义的。
适用于所有类型的数据。
模拟实现
#include <stdio.h>
#include <assert.h>
void* my_memcpy(void* destination, const char* source, size_t num)
{
assert(destination && source);
char* start = destination;
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
return start;
}
int main()
{
char arr1[20] = {
0 };
char arr2[] = "hello world";//12byte
char* ret = (char*)my_memcpy(arr1, arr2, 12);
printf("%s\n", ret);
return 0;
}
memmove
void* memmove(void* destination, const void* source, size_t num);
memmove其实也是内存拷贝函数,只不过它具有的功能更加的强大,能操作两块重叠的空间
#include <stdio.h>
#include <assert.h>
void* my_memmove(void* destination, const void* source, size_t num)
{
assert(destination && source);
char* start = destination;
//判断指针位置
if (source > destination)
{
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
}
else
{
while (num--)
{
*((char*)destination + num) = *((char*)source + num);
}
}
return start;
}
int main()
{
int arr[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
my_memmove(arr, arr + 2, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
边栏推荐
猜你喜欢

OSPF的5个数据包、LSA信息

NFT players' consensus segmentation: money, community and culture

MATLAB数字图像处理 实验二:单像素空域图像增强

Self signed SSL Certificate creation and use

【TensorFlow2.9】泰坦尼克号生存预测—结构化数据建模流程

Sword finger offer 10- I. Fibonacci sequence (4 solutions)

HCIP PPP/HDLC、GRE/MGRE实验

实现团队工作效率与质量共赢,这款办公协同工具真够用!
![[vsctf2022]web topic recurrence](/img/6f/56a9ec14ec699e427e9e21ee48c9eb.png)
[vsctf2022]web topic recurrence
![[bioinformatics] introductory practice and growth camp of imaging omics](/img/c5/29d9588d1fc5c30ba9242555358531.png)
[bioinformatics] introductory practice and growth camp of imaging omics
随机推荐
Irregular area of OSPF
NFT players' consensus segmentation: money, community and culture
CF514B Han Solo and Lazer Gun
ARTS_202207W1
A collection of dichotomous (dichotomous answers) questions
[QNX hypervisor 2.2 user manual]8.2 guest exit
玩转“私域电商”,链动2+1模式值得企业深入了解吗?
1388. 3n 块披萨 动态规划
Upgrade mysql5.5.27 to 5.7.35 under Windows Environment
PG operation and maintenance -- error log and slow log
【今天的小go同学要去丢垃圾(1)】
jitsi manu install(三)
[recognizing cloud Nativity] Chapter 4 cloud network section 4.9.4.2 - Implementation of smart network card
[recursion] square filling (backtracking method)
【今天的小go同学要去丢垃圾(3)】
High-Resolution Network (篇二):MMpose代码讲解之Backbone及关键点Detector部分
LeetCode腾讯精选练习50题-059.螺旋矩阵II
给已有数据的字段添加索引(达梦数据库版)
Learning notes - DC motor governor
Hcip - ppp/hdlc and gre/mgre experiments