字符串函数和内存函数
🍕博客主页:️自信不孤单
🍬文章专栏:C语言
🍚代码仓库:破浪晓梦
🍭欢迎关注:欢迎大家点赞收藏+关注
字符串函数和内存函数
文章目录
- 字符串函数和内存函数
- 前言
- 1. 字符串函数介绍
- 1.1 strlen函数
- 1.2 strcpy函数
- 1.3 strcat函数
- 1.4 strcmp函数
- 1.5 strncpy函数
- 1.6 strncat函数
- 1.7 strncmp函数
- 1.8 strstr函数
- 1.9 strtok函数
- 1.10 strerror函数
- 1.11 字符分类函数
- 2. 内存函数的介绍
- 2.1 memcpy
- 2.2 memmove
- 2.3 memcmp
- 2.4 memset
- 3. 模拟库函数的实现
- 3.1 模拟strlen函数
- 3.2 模拟strcpy函数
- 3.3 模拟strcat函数
- 3.4 模拟strcmp函数
- 3.5 模拟strstr函数
- 3.6 模拟memcpy函数
- 3.7 模拟memmove函数
前言
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。其中字符串常量适用于那些对它不做修改的字符串函数。
1. 字符串函数介绍
字符串函数需要包含头文件
#include <string.h>
1.1 strlen函数
size_t strlen(const char* str);
strlen函数(string length)的作用是计算返回字符串中结束标识符
'\0'
之前出现的的字符个数,因此,strlen函数所处理的字符串必须是以结束标识符'\0'
结尾的字符串。其返回值类型为size_t 类型,该类型为无符号类型。
strlen函数的应用:
#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;
}
输出结果为:
str1>str2
这里strlen(str2)的返回值为6,strlen(str1)的返回值为3,但为什么输出的是str1>str2呢?
由于strlen()的返回值是无符号类型,故两个无符号数相减也是无符号数,相减后的无符号数大于0,所以输出str1>str2。要想使用相减来比较字符串长度的大小,可以强制类型转换为有符号整型。
如:
#include<stdio.h>
#include<string.h>
int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";if ((int)strlen(str2) - (int)strlen(str1) > 0){printf("str2 > str1\n");}else{printf("srt1 < str2\n");}return 0;
}
1.2 strcpy函数
char* strcpy(char* destination, const char* source);
strcpy函数(string copy)的作用是,可以将字符串从源地址复制至目的地址,并返回目的空间的起始地址,并且它会将源地址内的结束标识符
'\0'
一并拷贝过去,因此源地址必须以'\0'
结尾,且目的地址也将以'\0'
结尾,通俗来讲就是用来实现字符串的复制和拷贝。并且,因为其作用为拷贝字符串,因此目标地址内的空间必须足够大,要有足够的空间容纳下源地址内的字符串,同时目的地址的空间必须是可修改的。
strcpy函数的应用:
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20];char arr2[15] = "hello world";printf("%s", strcpy(arr1, arr2));return 0;
}
输出结果为:
hello world
这里要特别注意的是strcpy函数返回的是目标空间的起始地址,该函数设置返回值类型的目的是为了实现链式访问。
1.3 strcat函数
char* strcat(char* destination, const char* source);
strcat函数(string catenate)的作用是,将源地址的字符串追加补充至目的地址处,并返回目的空间的首地址。与字符串拷贝函数相同,它在进行补充追加时是从目的地址的结束标识符处
'\0'
开始追加的,追加至源地址的结束标识符处停止。且它同样要求目标地址内的空间必须足够大,要有足够的空间容纳下源地址内的字符串,同时目的地址的空间必须是可修改的。
strcat函数的应用:
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello";char arr2[10] = " world";printf("%s\n", strcat(arr1, arr2));return 0;
}
输出结果为:
hello world
1.4 strcmp函数
int strcmp(const char* str1, const char* str2);
strcmp函数(string compare)的作用为按照顺序依次比较两字符串对应位置字符的ASCII码值(注意不是比较两字符串的长度),直到结束标识符
'\0'
或对应位置的字符不同。若比较至结束标识符都没有不同则两字符串相等,若两字符串对应位置字符有不同,对应位置上字符ASCII码值小的字符串小于另一个字符串。标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
strcmp函数的应用:
#include<stdio.h>
#include<string.h>
int main()
{const char arr1[] = "abcd";const char arr2[] = "abz";int ret = strcmp(arr1, arr2);if (ret > 0){printf("arr1 > arr2\n");}else if (ret == 0){printf("arr1 = arr2\n");}else{printf("arr1 < arr2\n");}return 0;
}
输出结果为:
arr1 < arr2
1.5 strncpy函数
char* strncpy(char* destination, const char* source, size_t num);
strncpy函数(string number copy)的作用为将指定长度的字符串复制到字符数组中,即表示把源地址中字符串开始的前n个字符拷贝到目的地址中,并返回目的空间的首地址。与strcpy相同,它同样会将源地址内的结束标识符
'\0'
一并拷贝过去,因此源地址必须以'\0'
结尾,且目的地址也将以'\0'
结尾。并且,因为其作用为拷贝字符串,因此目标地址内的空间必须足够大,要有足够的空间容纳下源地址内的字符串,同时目的地址的空间必须是可修改的。
strncpy函数的应用:
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "xxxxxxxxxxxxxx";char arr2[12] = "hello world";printf("%s", strncpy(arr1, arr2, 10));return 0;
}
输出结果为:
hello worlxxxx
1.6 strncat函数
char* strncat(char* destination, const char* source, size_t num);
strncat函数(string num catenate)的作用为从源地址处将指定长度的字符串追加补充到目的地址中与strcat函数类似,它在进行补充追加时也是从目的地址的结束标识符处
'\0'
开始追加的,不同的是追加至参数(单位是字节)限制的字符数处停止。但它同样要求目标地址内的空间必须足够大,要有足够的空间容纳下补充的字符串 ,同时目的地址的空间必须是可修改的。返回值为目的空间的首地址
strncat函数的应用:
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello";char arr2[10] = " world";printf("%s\n", strncat(arr1, arr2, 4));return 0;
}
输出结果为:
hello wor
1.7 strncmp函数
int strncmp(const char* str1, const char* str2, size_t num);
strncmp函数(string number compare)的作用为有限制(单位是字节)的按照顺序依次比较两字符串对应位置字符的ASCII码值(注意不是比较两字符串的长度),直到参数限制位数位置上全部比较结束或对应位置的字符不同。若参数限制位数位置上的字符都比较结束且都没有不同则两字符串相等,若两字符串对应位置字符有不同,对应位置上字符ASCII码值小的字符串小于另一个字符串。
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
strncmp函数的应用:
#include<stdio.h>
#include<string.h>
int main()
{const char arr1[] = "abcd";const char arr2[] = "abz";int ret = strncmp(arr1, arr2, 2);if (ret > 0){printf("arr1 > arr2\n");}else if (ret == 0){printf("arr1 = arr2\n");}else{printf("arr1 < arr2\n");}return 0;
}
输出结果为:
arr1 = arr2
1.8 strstr函数
char* strstr(const char* str1, const char* str2);
strstr函数(string string)的作用为从一个字符串中寻找其字串,通俗来讲就是从一个字符串中寻找另一个字符串。若找到目标字串则返回指向目标字串的指针,若没有找到目标字串则返回空指针。
strstr函数的应用:
#include<stdio.h>
#include<string.h>
int main()
{const char arr1[] = "abcdefg";const char arr2[] = "cde";char* ret = strstr(arr1, arr2);//从ar1中寻找arr2if (ret == NULL){printf("找不到该字符串!\n");}else{printf("成功找到该字符串\"%s\"!\n", ret);}return 0;
}
输出结果为:
成功找到该字符串"cdefg"!
1.9 strtok函数
char* strtok(char* str, const char* sep);
strtok函数(string token)的作用为将字符串分解为一组字符串。该函数有两个数组作为参数,它的实际作用便是将其中一个数组为分割数组,在另一个数组中寻找这些分割符,并在分割符处将这个数组内的字符串加上结束标识符
'\0'
,将其分割成一组(多个)字符串。若第一个参数不为NULL,将找到字符数组中的第一个标记并保存它在字符串中的位置;若第一个参数为NULL,将在同一个字符串中被保存的位置开始,查找下一个标记。返回值:该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
strtok函数的应用:
#include<stdio.h>
#include<string.h>
int main()
{char arr1[] = "1592272237@qq.com";char arr2[30] = { 0 };strcpy(arr2, arr1);const char* arr3 = "@.";printf("账号:%s\n", strtok(arr2, arr3));//找到第一个标记停止printf("域名前缀:%s\n", strtok(NULL, arr3));//从保存好的位置开始往后找printf("域名后缀:%s\n", strtok(NULL, arr3));//从保存好的位置开始往后找return 0;
}
输出结果为:
账号:1592272237
域名前缀:qq
域名后缀:com
- strtok函数是会对数组本身进行操作的,所以我们为了保护原始数据,在定义并初始化好字符数组之后,又定义了一个新的数组并将原始数据拷贝过去,作为临时拷贝供我们进行操作。
- 接着我们定义并初始化了分割符数组,函数将根据分割符数组arr3对临时拷贝arr2进行分割。第一次执行函数时之前没有标记,于是直接进行操作找到第一个标记并分割打印。
- 此时就已经存在标记了,再连续两次找到前一次执行作下的标记按照分割符将数组分割完毕并打印。
我们可以将上述代码优化为:
#include<stdio.h>
#include<string.h>
int main()
{char arr1[] = "1592272237@qq.com";char arr2[30] = { 0 };strcpy(arr2, arr1);const char* arr3 = "@.";char* str = NULL;for (str = strtok(arr2, arr3); str != NULL; str = strtok(NULL, arr3)){printf("%s\n", str);}return 0;
}
1.10 strerror函数
char* strerror(int errnum);
strerror函数(string error)的作用为返回错误码对应的信息。即根据接收到的错误码(错误码errno为全局变量),返回错误原因的详细信息。
strerror函数的应用:
#include<stdio.h>
#include<string.h>
int main()
{int i = 0;for (i = 0; i <= 4; i++){printf("错误原因为:%s\n", strerror(i));}return 0;
}
输出结果为:
1.11 字符分类函数
函数 | 如果他的参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:空格' ' ,换页'\f' ,换行'\n' ,回车'\r' ,制表符'\t' 或者垂直制表符'\v' |
isdigit | 十进制数字0~9 |
isxdigi | 十六进制数字,包括所有十进制数字,小写字母a~f ,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z 或A~Z |
isalnum | 字母或者数字,a~z ,A~Z ,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
字符转换:
int tolower(int c);
int toupper(int c);
举个栗子:
此代码的作用是将大写字符转换为小写字符
/* 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;
}
输出结果为:
test string.
2. 内存函数的介绍
2.1 memcpy
void* memcpy(void* destination, const void* source, size_t num);
memcpy函数(memory copy)的作用为从源内存空间向目的内存空间拷贝限制数量(单位是字节)的数据。它与strcpy函数类似,作用均为拷贝数据,不同的是strcpy仅仅只操作字符串故会在结束标识符
'\0'
处停止,而memcpy函数操作的是内存,内存中的数据是相邻的,故不会在结束标识符处停止。
返回值:该函数返回一个指向目标存储区destination的指针。
memcpy函数的应用:
#include <stdio.h>
#include <string.h>
struct {char name[40];int age;
} person, person_copy;
int main()
{char myname[] = "Pierre de Fermat";/* using memcpy to copy string: */memcpy(person.name, myname, strlen(myname) + 1);person.age = 46;/* using memcpy to copy structure: */memcpy(&person_copy, &person, sizeof(person));printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);return 0;
}
输出结果为:
注:如果源内存空间和目标内存空间有重叠时,memcpy是无法保证内存复制的正确性的。
2.2 memmove
void* memmove(void* destination, const void* source, size_t num);
memmove函数(memory move)和memcpy函数都是内存复制函数,他们在用法上也一样。但是如果目标区域和源区域有重叠的话,memmove是比memcpy更安全的方法,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和memcpy函数功能是完全相同的。
memmove函数的应用:
#include <stdio.h>
#include <string.h>
int main()
{char str[] = "memmove can be very useful......";memmove(str + 20, str + 15, 11);puts(str);return 0;
}
输出结果为:
2.3 memcmp
int memcmp(const void* ptr1,const void* ptr2,size_t num);
memcmp函数(memory compare)的作用与 strcmp 函数的作用类似,不过 memcmp 函数是从内存的角度以字节为单位进行处理,故 memcmp 函数同样需要第三个参数进行限制,而不会在结束标识符 ’ \0 ’ 处停止比较。
memcmp函数的应用:
#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;
}
输出结果为:
2.4 memset
void* memset(void* dest, int c, size_t count);
memset函数(memory set)的作用是复制字符c(一个无符号字符)到参数dest所指向的字符串的前n个字符。
返回值是:该值返回一个指向存储区dest的指针。
memset函数的应用:
#include <stdio.h>
#include <string.h>int main()
{char str[50];strcpy(str, "This is string.h library function");puts(str);memset(str, '$', 7);puts(str);return(0);
}
输出结果为:
3. 模拟库函数的实现
3.1 模拟strlen函数
//1.计数器
size_t my_strlen1(const char* str)
{assert(str);int count = 0;while (*str){count++;str++;}return count;
}//2.递归调用
size_t my_strlen2(const char* str)
{assert(str);if (*str)return sim_strlen2(str + 1) + 1;elsereturn 0;
}//3.指针相减
size_t my_strlen3(const char* str)
{assert(str);const char* p = str;while (*p++){;}return (p - str - 1);
}
3.2 模拟strcpy函数
char* my_strcpy(char* destination, const char* source)
{char* ret = destination;assert(destination && source);while (*destination++ = *source++){;}return ret;
}
3.3 模拟strcat函数
char* my_strcat(char* destination, const char* source)
{char* ret = destination;while (*destination){destination++;}while (*destination++ = *source++){;}return ret;
}
3.4 模拟strcmp函数
int my_strcmp(const char* s1, const char* s2)
{assert(s1 && s2);while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0'){s1++;s2++;}return *s1 - *s2;
}
3.5 模拟strstr函数
char* my_strstr(const char* s1, const char* s2)
{assert(s1 && s2);if (*s2 == '\0'){return (char*)s1;}const char* p1 = s1;const char* p2 = s2;const char* start = s1; //用于记录开始比较的位置while (*p1){ //以防主串可能小于子串,循环条件不能只为*p1 == *p2while (*p1 == *p2 && *p1 != '\0' && *p2 != '\0') //单字符匹配成功则匹配下一个字符{p1++;p2++;}if (*p2 == '\0') //匹配成功,返回开始比较的位置return (char*)start;//单趟匹配失败,子串退回到第一个字符,进行从主串的下一个字符开始与主串匹配p1 = start + 1;start = p1;p2 = s2;}return NULL; //跳出外层循环说明匹配失败
}
3.6 模拟memcpy函数
void* my_memcpy(void* dest, const void* src, size_t nums)
{assert(src && dest);int i = 0;for (i = 0; i < nums; i++){*((char*)dest + i) = *((char*)src + i);}return (char*)dest;
}
3.7 模拟memmove函数
void* my_memmove(void* dest, const void* src, size_t nums)
{assert(src && dest);void* ret = dest;int i = 0;if (dest < src)//从前向后{for (i = 0; i < nums; i++){*((char*)dest + i) = *((char*)src + i);}}else//从后向前{for (i = nums - 1; i >= 0; i--){*((char*)dest + i) = *((char*)src + i);}}return ret;
}
到此,关于《字符串函数和内存函数》的内容就结束了
感谢大家的观看
创作不易,如果对您有帮助,请一键三连
您的支持就是我创作最大的动力!!!
相关文章:

字符串函数和内存函数
🍕博客主页:️自信不孤单 🍬文章专栏:C语言 🍚代码仓库:破浪晓梦 🍭欢迎关注:欢迎大家点赞收藏关注 字符串函数和内存函数 文章目录字符串函数和内存函数前言1. 字符串函数介绍1.1 s…...

Web3中文|GPT-4超越GPT-3.5的五大看点
A Beautiful CinderellaDwelling EagerlyFinally Gains HappinessInspiring Jealous KinLove Magically Nurtures Opulent PrinceQuietly RescuesSlipper TriumphsUniting Very WondrouslyXenial Youth Zealously这是一段描述童话故事《灰姑娘》的内容,它出自GPT-4之…...

动态矢量瓦片缓存库方案
目录 前言 二、实现步骤 1.将数据写入postgis数据库 2.将矢量瓦片数据写入缓存库 3.瓦片接口实现 4.瓦片局部更新接口实现 总结 前言 矢量瓦片作为webgis目前最优秀的数据格式,其主要特点就是解决了大批量数据在前端渲染时出现加载缓慢、卡顿的问题࿰…...

628.三个数的最大乘积
给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。 示例 1: 输入:nums [1,2,3] 输出:6 示例 2: 输入:nums [1,2,3,4] 输出:24 示例 3: …...

【数据结构】堆和集合笔记
自己写一个堆首先,明确一下,为什么需要堆?>考虑插入,删除,查找的效率。数组,查找,最快是二分查找O(lgN)。但查找完如果要做什么操作,比如删除,就要挪动元素了。所以合…...

java LinkedList 源码分析(通俗易懂)
目录 一、前言 二、LinkedList类简介 三、LinkedList类的底层实现 四、LinkedList类的源码解读 1.add方法解读 : 〇准备工作 。 ①跳入无参构造。 ②跳入add方法。 ③跳入linkList方法。 ④增加第一个元素成功。 ⑤向链表中添加第二个元素。 2.remove方法解读 : 〇准备工…...

Vue中实现路由跳转的三种方式详细分解
vue中实现路由跳转的三种方式 目录 vue中实现路由跳转的三种方式 一、使用vue-router 1.下载vue-router模块到当前工程 2.在main.js中引入VueRouter函数 3.添加到Vue.use()身上 – 注册全局RouterLink和RouterView组件 4.创建路由规则数组 – 路径和组件名对应关系 5…...

全国自学考试03708《中国近现代史纲要》重点复习精要
1. 西方列强的殖民扩张和鸦片战争的影响。(两面性) :反面—破坏了了中国的小农经济,是中国由封建社会转变为两半社会。 --一系列不公平条约,破坏了中国主权领土完整。 --压迫中国人民,给中国人民带来了巨大…...

数据库面试题——锁
了解数据库的锁吗? 锁是数据库系统区别于文件系统的一个关键特性,锁机制用于管理对共享资源的并发访问。 InnoDB下两种标准行级锁: 共享锁(S Lock),允许事务读一行数据。 排他锁(X Lock&…...

Python笔记 -- 文件和异常
文章目录1、文件1.1、with关键字1.2、逐行读取1.3、写入模式1.4、多行写入2、异常2.1、try-except-else2.2、pass1、文件 1.1、with关键字 with关键字用于自动管理资源 使用with可以让python在合适的时候释放资源 python会将文本解读为字符串 # -*- encoding:utf-8 -*- # 如…...

蓝桥杯刷题冲刺 | 倒计时24天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.修剪灌木2.统计子矩阵1.修剪灌木 题目 链接: 修剪灌木 - 蓝桥云课 (lanqiao.cn) 找…...

真正理解微软Windows程序运行机制——什么是消息
我是荔园微风,作为一名在IT界整整25年的老兵,今天说说Windows程序的运行机制。经常被问到MFC到底是一个什么技术,为了解释这个我之前还写过帖子,但是很多人还是不理解。其实这没什么,我在学生时代也被这个问题困绕过。…...

HTTP 缓存的工作原理
缓存是解决http1.1当中的性能问题主要手段。缓存可能存在于客户端浏览器上,也可以存在服务器上面,当使用过期缓存可能给用户展示的是错误的信息而导致一些bug。 HTTP 缓存:为当前请求复用前请求的响应 • 目标:减少时延࿱…...

RK3568在Android上进行驱动模块开发(源码外)
文章目录 前言一、ARCH架构二、编译器三、建立自己的Makefile文件总结前言 本文记录在驱动开发时,由于编译内核时间较长,经常会选择单独编译一个模块,这里主要讲解,makefile文件如何编写(主要是编译器和架构) 提示:以下是本篇文章正文内容,下面案例可供参考 一、ARCH…...

操作技巧 | 在Revit中借用CAD填充图案的方法
在建模过程中,有时需要达到多种填充效果,而CAD中大量的二维填充图案,便是最直接的资源之一。 使用 填充图案之前 使用 填充图案之后 其中要用到主要命令便是对表面填充图案的添加与编辑 简单效果 如下 模型填充与绘图填充 区别 模型填…...

Java的二叉树、红黑树、B+树
数组和链表是常用的数据结构,数组虽然查找快(有序数组可以通过二分法查找),但是插入和删除是比较慢的;而链表,插入和删除很快(只需要改变一些引用值),但是查找就很慢&…...

昨天某读者拿到华为OD岗位offer,今天来分享一下经验,包含华为OD机试
来自读者投稿,已经拿到华为 OD 开发岗位 offer,询问了一些问题,下面是他的一些经验。 文章目录华为 OD 投递简历华为 OD 机试分数OD 机试通过之后,收到综合测评OD 技术面(时长 1 小时左右)主管/HR 面试&…...

树的遍历方式(前中后,层序遍历,递归,迭代,Morris遍历)-----直接查询代码
目录 一.前序遍历 1.递归 2.栈迭代 3.Morris遍历 二.中序遍历 1.递归 2.栈迭代 3.Morris遍历 三.后序遍历 1.递归 2.栈迭代 3.Morris遍历 四.前中后序的统一迭代法 1.前序遍历 2.中序遍历 3.后序遍历 五.层序遍历 1.队列迭代 2.之字形层序遍历 3.锯齿形层序…...

Docker Registry部署镜像私有仓库及鉴权认证
文章目录一、Docker Registry是什么?二、Docker Registry部署私有仓库2.1、Docker Registry安装2.2、Docker Registry配置2.3、启动Docker Registry2.4、Docker客户端配置2.5、向Docker Registry上传和下载镜像三、Docker Registry鉴权和认证3.1、基本认证3.2、Bear…...

stm32外设-中断详解
0. 写在最前 本栏目笔记都是基于stm32F10x 1. 中断是啥? 什么是中断:CPU在处理某一事件A时,发生的另外某一事件B请求CPU去处理(产生了中断),随后CPU暂时中断当前正在执行的任务,去对事件B进行处…...
第十四届蓝桥杯三月真题刷题训练——第 13 天
目录 第 1 题:特殊日期 问题描述 答案提交 运行限制 代码: 思路: 第 2 题:重合次数 问题描述 答案提交 运行限制 代码: 第 3 题:左移右移 问题描述 输入格式 输出格式 样例输入 样例输出…...

webgl_gpgpu_birds 样例分析
webgl_gpgpu_birds 是一个 three.js 的官方样例,这个例子模拟了鸟群的运动,是一个群组动画,并且动画的帧率也很高;鸟群的运动很自然,非常值得研究。类似的群组动画还有鱼群,boid是‘类鸟群’的英文 大概两…...

以业务行为驱动的反入侵安全能力建设
0x0 背景 最近听到一些甲方安全领域的专家分享了部分安全建设的经验,对安全运营下的反入侵技术能力建设有了些新的看法,依靠单个/多个异构的安全产品的关联能力形成的安全中台并不能在实际的攻防对抗当中占据主动地位,且很容易达到一个天花板…...

Unity3d C#使用DOTween插件的Sequence实现系列动画OnComplete无效和颜色设置无效的问题记录
前言 最近在弄一个文字动画效果的动画,使用了DOTween插件的Sequence来实现,主要就是对一个Text进行的文字打字、缩放和颜色设置等动画,功能是先对Text实现打字的动画,打字完成后,延时几秒对文字进行缩小、颜色变淡&am…...

【蓝桥杯-筑基篇】排序算法
🍓系列专栏:蓝桥杯 🍉个人主页:个人主页 目录 前言: 一、冒泡排序 二、选择排序 三、插入排序 四、图书推荐 前言: 算法工具推荐: 还在为数据结构发愁吗?这款可视化工具,帮助你更好的了解…...

编辑器进化 VSCode + Vim
本文作者为 360 奇舞团前端工程师VSCode 是一款非常流行的代码编辑器。它支持多种编程语言,拥有丰富的插件和调试功能,不论是处理前端工程还是后端工程,VSCode 都能提供给开发者优秀的用户体验。鉴于 VSCode 超高的流行度,我会默认…...

LearnOpenGL-高级OpenGL-6.天空盒
本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject 文章目录天空盒介绍如何采样OpenGL纹理目标例子0:天空盒效果环境映射反射例子1:Cube…...

Printk打印内核日志
一、背景 Linux 内核中提供了内核日志打印的工具printk。它的使用方式C语言中的printf是类似的。接下来我们介绍一下printk的使用方式。本文以打印Binder中的日志为例,进行演示。 printk的方法声明和日志级别binder驱动中增加 打印代码android系统中查看日志信息 …...

界面控件DevExpress WPF 202计划发布的新功能合集
DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。本文将介绍今年DevExpr…...

Spring Cloud Alibaba 微服务2,注册中心演变 + Nacos注册中心与配置中心
目录专栏导读一、什么是Nacos?二、注册中心演变及其设计思想1、RestTemplate调用远程服务2、通过Nginx维护服务列表(upStream)3、通过Nacos实现注册中心4、心跳版Nacos三、Nacos Discovery四、Nacos核心功能1、服务注册2、服务心跳3、服务同步…...