数据结构与算法 | 第四章:字符串

news2024/12/27 11:17:17

本文参考网课为 数据结构与算法 1 第四章字符串,主讲人 张铭 、王腾蛟 、赵海燕 、宋国杰 、邹磊 、黄群。

本文使用IDE为 Clion,开发环境 C++14

更新:2023 / 11 / 12


数据结构与算法 | 第四章:字符串

  • 字符串
    • 概念
      • 字符串
      • 字符
      • 字符编码
      • 子串
    • 抽象数据类型
    • 存储与实现
      • 顺序存储
        • C / C++的标准字符串
          • 标准串运算
            • 字符串长度
            • 字符串寻找字符
        • C++的字符串类 String
          • 字符串类运算
            • 构造算子
            • 赋值算子
            • 提取子串
    • 模式匹配
      • 概念
      • 应用
      • 分类
        • 精确匹配
          • 单选模式
            • 朴素匹配算法
            • KMP 算法
        • 近似匹配
  • 参考链接


字符串

概念

字符串

字符串 是一类简单的由 字符char)构成的线性结构的 线性表

字符串 简称 ,为零个或多个 字符 / 符号 构成的有限序列。
n (>=0) 个 字符 的有限序列,一般记作 S C0C1…Cn-1

  • S 为串名
  • C0C1…Cn-1为串值。Ci中i位置上的 字符 / 符号
  • n 为字符串长度。长度为零的串,不包含任何字符内容。理论上,一个字符串的长度可以为任意的有限长度,实际上:
    • 定长
      具有固定的最大长度,所用内存量始终如一
    • 变长
      根据实际需要伸缩,以提高内存空间利用率

字符

字符 的取值依赖于字符集。常用的字符集包括:

  • 由 {0, 1} 所构成的二进制字符集
  • 由4个字符组成的生物信息的DNA字符集
  • 由26个字符和标点符号等组成的英语语言
  • 由6763个常用汉字和682个全角非汉字符号等所构成的简体中文标准字符集GB2312
  • 适用于跨语言、跨平台的通用字符集USC( Universal Character Set

这些 字符 在计算机里是如何存储和运算呢?这就需要 字符编码 来建立 字符集 与计算机数字系统之间的对应关系。


字符编码

字符编码 会将 字符集 里的每一个字符编码为由0和1组成的序列。那么,具体,哪一个二进制序列表示哪一个符号则取决于我们所使用的编码方式。常用的编码方式有:

  • ASCII 编码
    • 使用单字节( 8 bits )对字符集 charset 的128个符号进行编码
    • 基于拉丁字母的编码,主要用于现代英语和多种西欧语言,也为大多数程序设计语言所采用,例如C和C++
  • 其他编码方式
    • ANSI 编码
      支持多种东方语言:GB2312BIG5JIS 等。不同国家/地区制定不同的标准,不同 ANSI 编码间互不兼容
    • Unicode(跨语言跨平台)
      各种语言中的每一个字符具有唯一的数字编号,便于跨平台的文本转换

无论采用哪一种编码方式,对于一个给定字符集中的字符编码需要满足一组无歧义的规则,使得字符集中的每一个字符都对应唯一的一个编码。且不同的字符编码之间要满足偏序关系。
所谓偏序关系,是定义在集合上的一个二元关系满足自反性、反对称性和传递性。在偏序规则下,

  • 连续的数字 0 - 9 是要连续编码的。像在 ASCII 编码 下,0 的编码是 48,那么 1 的编码就是 49
  • 连续的字符也是需要连续编码的。像在 ASCII 编码 下,大写字母 A 的编码是65,那么 B 的编码就是66。

通常在字符偏序下,根据字符的自然含义,两个字符之间是可以根据它的编码值进行直接的比较的。两个字符串就会按照构成的字符之间的编码进行大小的比较来得到字典序。


子串

一个 字符串 中任意个连续的字符组成的子序列称为该串的 子串

比如说一个长度为 n 的字符串 s1 和长度为 m 的 s2,0<=m<=n。若存在整数 j (0<=i<=n-m) 使得 bj = ai+j,j = 0,1,…,m-1同时成立,则称串 s2 是串 s1 的字串,或称 s1 包含串 s2
另外,空串是任意串的子串。任意串S都是其自身的子串。

子串 相关的应用有:提取、插入、寻找、删除等等。


抽象数据类型

int length();                                   // 返回串的长度
int isEmpty();                                  // 判断串是否为空串
int find(const char c, const int s);            // 从s开始搜索串寻找一个给定字符
int strcmp(const char *s1, const char *s2);     // 串比较

void clear();                           		// 清空串

string substr(const int s, const int len);      // 从s开始提取一个长度为len的子串
string insert(const char s, const int index);   // 往串中给定位置插入一个字符
string append(const char c);                    // 往串尾添加字符
string concatenate(const char *s);              // 往本串后面链接串s

char *strcpy(char *s1, const char *s2);         // 串复制

存储与实现

字符串 是一种基本元素为 字符 的特殊线性表,所以本质上它的存储也有线性表的顺序和链式两种方式。但是对于 字符串 这类特殊的线性表来说,链式存储的结构性开销过大而很少被采用,所以我们主要以顺序存储为主来介绍 字符串 的存储与实现。


顺序存储

对于定长的 字符串 采用顺序存储方式,即事先申请固定长度的空间但需要有相应的机制来确切的知道当前串的长度。所以一般有3种处理方案:

  • 字符串 的第一个元素 S[0] 作为记录串长的存储单元
    缺点:该方式决定串的最大长度不能超过256 2
  • 另辟空间存储串的长度
    缺点:串的最大长度一般是静态给定的,而非动态申请
  • 特殊标记串的结束
    C / C++ 的标准字符串( #include <string.h> )

C / C++的标准字符串

C / C++ 的标准字符串是将字符串变量定义为字符数组 char s[M]

字符串的结束标记是 ASII码中8位全0码 ‘\0’,亦称 NULL。因此,字符串的实际长度为 M-1
例如,chars s1[6]='value';,定义了一个名为 chars 的字符数组,长度为6位,但是只能存储5位字母。

需要注意的是,标准串定义成了数组,所以它是无法作为左值被赋值的。例如,s1 = s2 是不合规的。


标准串运算

函数库 <string.h> 提供字符串处理函数来方便字符串的运算。下面是 string.h 提供的一些常用的字符串的操作:

函数作用
int strlen(char *s)串长
char *strcpy(char *s1, char*s2);串复制
char *strcat(char *s1, char *s2);串拼接
int strcmp(char *s1, char *s2);串比较
char *strchr(char *s, char c);字符定位
char *strrchr(char *s, char c);字符定位
int *strstr(char* s2, char* s1)子串抓取

字符串长度
  • 1. 求字符串的长度
int strlen(char s[])
{
    int i = 0;
    while (s[i] != 0)
        i ++;
    return i;
}
  • 2. 比较2个字符串的长度
int strcmp(const char *s1, const char *s2)          // 定义2个字符串,分别为s1、s2
{
    int i = 0;
    while (s2[i] != '\0' && s1[i] != '\0'){         // 字符串的结束标记为 \0
        if (s1[i] > s2[i])
            return 1;                               // s1比s2长
        else if (s1[i] < s2[i])
            return -1;                              // s1比s2短
        i ++;
    }
    if (s1[i] == '\0' && s2[i] != '\0')
        return -1;                                  // s1比s2短
    else if (s2[i] == '\0' && s1[i] != '\0')
        return 1;                                   // s2比s1短
    return 0;
}

或者,

int strcmp_1(char *s1, char *s2)                // 定义2个字符串,分别为s1、s2
{
    int i;
    for (i=0; s1[i] == s2[i]; ++i){
        if (s1[i] == '\0' && s2[i] == '\0')
            return 0;                           // 两个字符串相等
    }
    return (s1[i]-s2[i])/abs(s1[i]-s2[i]);      // 不等,比较第一个不同的字符
}

字符串寻找字符
  • 1. 在字符串 s 中正向寻找字符 c
char * strchr(char *s, char c)
{
    i = 0;
    while (s[i] != '\0' && s[i] != c)       // 循环跳过非c字符
        i++;
    // 在循环结束后
    if (s[i] == '\0')                       // 当s不包含字符c则在s[i]即串尾
        return 0;
    else                                    // 当s[i]==c则返回s[i]
        return &s[i];
}
  • 2. 在字符串 s 中反向寻找字符 c
char * strrchr(char *s, char c)
{
    i = 0;
    while (s[i] != '\0') i++;               // 获得s字符串的长度
    while (s[--i] != '\0' && s[i] != c);    // 循环反向跳过非c字符
    // 在循环结束后
    if (s[i] == '\0')                       // 当s不包含字符c则在串尾结束
        return 0;
    else                                    // 若成功则返回相应位置
        return &s[i];
}

举例,在 s = [Hello world\0] 中寻找 o

在这里插入图片描述
寻找字符 ostrchar(s, 'o') 返回 4
反向寻找 ostrchar(s, 'o') 返回 7


C++的字符串类 String

除了采用标准字符串以外,还可以采用字符串类 String 来表示和存储字符串,以适应字符串的长度动态变化。

String 类中,字符串不再是以字符数组 char S[M] 这种形式来直接出现,而是采用一种动态变长的存储结构。

String 类是通过实例化标准模板库中的 STLbasic_string 而得到的。如下:

typedef basic_string <char> string;

它的存储结构如下:

private:                // 具体实现的字符串存储结构
    char *str;                          // 字符指针表示的串实体
    int size;                           // 字符串长度
public:                 // 成员函数
    String(char *s);                    // 构构子
    ~String();                          // 析构子
    String operator=(String & s);       // 赋值
    String operator+(String);           // 拼接
    String substr(int index, int cout); // 子串
    int find(char c, int start);        // 查找
    ...
字符串类运算
操作类别方法描述
子串substr返回一个串的子串
拷贝 / 交换copy将一个串拷贝到另一个串中
swap交换两个串的内容
赋值assign把一个串、一个字符、一个子串赋值给另一个串中
=把一个串或一个字符赋值给另一个串中
插入 / 追加insert在给定位置插入一个字符、多个字符或串
+=将一个字符或串追加到另一个串后
append将一个或多个字符,或串追加在另一个串后
拼接+通过将一个串放置在另一个串后面来构建新的新串
查询find找到并返回一个子序列的开始位置
替换 / 清除replace替换一个指定字符或一个串的子串
clear清除串中的所有字符
统计size返回串中字符的数目
length返回size()
max_size返回串允许的最大长度

构造算子

String 类有多个构造函数。构造一个带有初始值的 String 类可以参照以下方法:

String::String(char *s){        // 确定新字符串需要的空间,初始值为 char *s
    size = strlen(s);           // 新字符串的长度由标准字符串函数 strlen(s) 确定
    str = new char [size+1];    // 在动态存储区域开辟一块空间,用于存储初值s,包括结束符
    assert(str != '\0');        // 开辟空间不成功时,运行异常,退出
    strcpy(str, s);             // 在空间申请成功后,用标准字符串函数strcpy将s完全复制到指针str所指的存储空间
}

例如,我们可以通过上面的带参数的构造函数通过 String s1("hello"); 定义一个 String 类的变量 s1,初始值为 hello。那么我们就可以申请一个容纳下 hello 的空间来将 hello 容纳进去,并且将 size 设置成相应的大小。

String s1("hello");

private:
    char *s;
    size_t size;        // 值为5

赋值算子
String String::operator=(String& s){        // 参数s将被赋值并覆盖本串。
    if (size != s.size){                    // 比较本串和参数串s的大小:若本串和参数串长度不一致,则释
        delete [] str;                         // 放原本的串的存储空间
        str = new char [s.size+1];             // 按照参数s的大小申请新的空间,并把参数s的串值复制到本串中
        assert(str!=0);
        size=s.size;
    }
    strcpy(str, s.str);                     // 将参数串s赋值到本串
    return *this;                           // 返回得到的字符串
}

例如,我们通过构造函数构造一个串 s2,它的初值为 hello world 并通过 String s2("hello world"); s1=s2; 将这个值赋值给 s1。而 s1 此前已经被赋值 hello,所以可以看到 hello 的空间不足以存放新的值 hello world,所以将原本的空间释放掉、申请一个新的空间来容纳新值。
在这里插入图片描述


提取子串
// 提取子串的函数是将本串从index开始提取连续的count个字符 作为子串返回,放到temp中
String String::Substr(int index, int count){    // 取出一自下表index开始长度为count的子串返回
    int i;
    int left = size - index;                    // 本串自下标index开始到串尾的长度为left
    String temp; char *p *q;
    if (index >= size)                          // 若下标index超过本串实际串长,则返回空串;
        return temp;
    if (count > left)                           // 若count超过自index开始剩余的子串长度
        count = left;                           // 则count截取为剩余长度
    delete [] temp.str;                         // 释放原来的存储空间
    temp.str = new char [count+1];
    assert(temp.str != 0);                      // 若开辟动态存储空间失败,则退出
    p = temp.str;                               // 若指针p指向目前暂无内容的字符数组的首字符处
    q = &str[index];                            // 指针q指向本实例串的str数组的下标index字符
    for (i=0; i<count; i++)                     // 从index开始逐个提取字符到串temp中
        *p++ = *q++;
    *p = 0;                                     // 循环结束后,让temp.str的结尾为 '\0'
    temp.size = count;
    return temp;
}

例如,我们可以通过 s2 = s1.substr(6 ,5) 从串 s1 hello world 的第6个位置开始,连续提取5个字符形成子串 world 赋值给 s2


模式匹配

概念

模式匹配Pattern Matching ),在目标文本 T 中寻找和定位一个给定模式 PPattern )的过程。


应用

模式匹配 有着非常广泛的应用,例如:

  • 进行文本编辑时对特定词语、语句的查找;
    • 大文本(诸如,句子、段落或书本)中定位特定的模式;
    • UNIX / Linux:sed、awk、grep;
  • 在生物信息方面,对DNA信息的提取;
  • 用于确认是否具有某种特定形式的结构:
    • 函数式语言

分类

根据匹配结果的精确性,模式匹配 可以分为 精确匹配近似匹配


精确匹配

精确匹配Extract String Matching ),若目标 T 中至少存在一处与模式 P 完全相同的子串,则称为匹配成功。

根据模式的不同,可以进一步的分为:

  • 单选模式
    例如,Set
  • 多选模式
    例如,包含通配符的 S?t
  • 正则表达式

单选模式

给定模式串 P,在目标字符串 T 中搜索与模式 P 全同的子串,简称为 配串。如果找到,则返回 T 中第一个 P 的配串的首地址。

在这里插入图片描述
因为模式匹配频繁用于文本的模式查找,所以效率是衡量模式匹配算法的一个重要指标。因此,存在许多种用于模式匹配的算法。

这里列出一些常用的单选模式的字符串匹配算法,包含每个算法的预处理时间和匹配时间:

在这里插入图片描述


朴素匹配算法

朴素 匹配算法( Native / Brute Force ),本质上是穷举,尝试所有匹配的可能。

假设 T = t0t1t2…tn, P = p0p2…pm-1。i, j 分别表示 T 和 P 当前字符的下标,在目标字符串 T 中搜索与模式 P 的配串:

  1. 将模式从头与目标串的第 i 个字符开始比较:若相等,则继续逐个比较后续字符;
  2. 匹配成功( p0 = tk,p1 = tk+1,…,pm-1 = tk+m-1),即 T.substr(k, m) == P;
  3. 若一趟匹配过程发生失配( pj != ti ),则将 P 整体右移1位开始下一趟的匹配

例如,存在目标字符串 T = ababababababb 和模式串 P = abababb

在这里插入图片描述

  1. 将P从0开始与T的第 i 个字符开始比较:若相等,则继续逐个比较后续字符;在第6个字符发生失配( P6 != T6),将P整体右移1位开始下一趟的匹配;
  2. 将P从1开始与T的第 i 个字符开始比较:在第1个字符发生失配(P0 != T1 ),将P整体右移1位开始下一趟的匹配;
  3. 重复上述步骤,直至 T.substr(k, m) == P 匹配成功或者匹配失败。

例如,存在目标字符串 T = aaaaaaaaaab 和模式串 P = aaaaaab

在这里插入图片描述

  1. 将P从0开始与T的第 i 个字符开始比较:若相等,则继续逐个比较后续字符;在第6个字符发生失配( P6 != T6),将P整体右移1位开始下一趟的匹配;
  2. 将P从1开始与T的第 i 个字符开始比较:在第1个字符发生失配(P6 != T7 ),将P整体右移1位开始下一趟的匹配;
  3. 重复上述步骤,直至 T.substr(k, m) == P 匹配成功或者匹配失败。

朴素模式 的匹配算法实现如下:

int g, j;

int FindPattern(string T, string P, int startindex)
    for (int g=startindex; g<=T.length()-P.length(); g++){     // g为T的游标,用模板P和目标T的第g位置子串进行比较
        for (int j=0; ((j<P.length()) && (T[g+j]==P[j])); j++)
            ;
        if (j==P.length())
            return g;
    }
    return (-1);                                               // for循环结束,或者,startindex溢出,匹配失败
}

朴素模式 的匹配算法的时间复杂度分析如下:

  • 最差情形

    在这里插入图片描述

  • 最佳情形

    在这里插入图片描述
    在这里插入图片描述


KMP 算法

Knuth - Morris - PrattKMP )发现每个字符对应的 k 值仅依赖于模式 P 本身,与目标串 T 无关。

1970年,S.A.Cook 在进行抽象机的理论研究时证明了最差情况下模式匹配可在 O(N+M) 时间内完成。
D.E.Knuth 和 V.R.Pratt 以 Cook理论为基础,构造了一种在 O(N+M) 时间内进行模式匹配的方法。
与此同时,J.H.Morris 在开发文本编辑器时为了避免检索文本时的回溯,也得到了同样的算法。

长度为m的模式P,P=p0p1p2p3…pm-1。特征向量N表示模式P的字符分布特征,由m个特征数nj组成 N = n0n1n2n3…nm-1
特征向量,简称 N向量。在很多文献中也称为 next 数组,每个特征数 nj 对应 next 数组的一个元素。

【还是没搞懂KMP算法的思想…此处略…】


近似匹配

近似匹配Approximate String Matching ),若模式 P 与目标 T(或其子串)存在某种程度的相似,则称为匹配成功。

字符串相似度通常定义串变换所需基本操作数目。

字符串基本操作包括 插入删除替换 三种操作。



参考链接


  1. 数据结构与算法 ↩︎

  2. 详解计算机中的字、字节(Byte)、比特(bit)及它们之间的关系 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1199530.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unbuntu安装、测试和卸载gcc11

GCC 可用于编译 C、C&#xff0c;本文介绍如何 Ubuntu 上安装 gcc11、测试和卸载它。 1. 在Ubuntu 上安装 gcc11 添加工具链存储库 sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test在 Ubuntu 上安装 gcc11 sudo apt install -y gcc-11验证 gcc11 版本 gcc-11 --v…

如何提升管理组织能力?

组织能力能力属于管理能力中的一部分&#xff0c;所以也称之为管理组织能力&#xff0c;组织是将人和事物的组合&#xff0c;有效的梳理和导向结果的能力。每个人都有组织能力&#xff0c;只是能力和效率上存在较大的差异。 一人的组织能力从学生时代就能体现出来&#xff0c;…

springboot高校全流程考勤系统-计算机毕设 附源码 27637

Springboot高校全流程考勤系统 摘 要 本文针对高校考勤等问题&#xff0c;对其进行研究分析&#xff0c;然后开发设计出高校全流程考勤系统以解决问题。高校全流程考勤系统系统主要功能模块包括&#xff1a;考勤签到、课程信息、考勤情况、申请记录列表等&#xff0c;系统功能设…

财务报告是什么

财务报告是什么 财务报告是企业对外提供的反映企业某一特定日期的财务状况和某一会计期间的经营成果、现金流量等会计信息的文件。 根据财务报告的定义&#xff0c;财务报告具有以下几层含义&#xff1a;一是财务报告应当是对外报告&#xff0c;其服务对象主要是投资者、债权人…

yolo系列报错(持续补充ing)

文章目录 export GIT_PYTHON_REFRESHquiet解决 没有pt权重文件解决 python文件路径报错解决 读取文件列名报错解决 导入不同文件夹出错解决 megengine没有安装解决然后你发现它竟然还没有用 export GIT_PYTHON_REFRESHquiet 设置环境变量 GIT_PYTHON_REFRESH &#xff0c;这个…

postgresql实现job的六种方法

简介 在postgresql数据库中并没有想oracle那样的job功能&#xff0c;要想实现job调度&#xff0c;就需要借助于第三方。本人更为推荐kettle&#xff0c;pgagent这样的图形化界面&#xff0c;对于开发更为友好 优势劣势Linux 定时任务&#xff08;crontab&#xff09; 简单易用…

【强化学习】18 —— SAC( Soft Actor-Critic)

文章目录 前言最大熵强化学习不同动作空间下的最大熵强化学习基于能量的模型软价值函数最大熵策略 Soft Q-learningSoft Q-IterationSoft Q-Learning近似采样与SVGD伪代码 Soft Actor-Critic伪代码代码实践连续动作空间离散动作空间 参考与推荐 前言 之前的章节提到过在线策略…

macOS Big Sur(macos11版本)

macOS Big Sur是苹果推出的最新操作系统&#xff0c;具有以下特点&#xff1a; 全新的设计风格&#xff1a;Big Sur采用了全新的设计语言&#xff0c;包括更加圆润的窗口和控件、更加鲜明的色彩和更加简洁的界面。这种设计风格使得操作系统更加美观和易用。强大的性能表现&…

国际阿里云:云服务器灾备方案!!!

保障企业业务稳定、IT系统功能正常、数据安全十分重要&#xff0c;可以同时保障数据备份与系统、应用容灾的灾备解决方案应势而生&#xff0c;且发展迅速。ECS可使用快照、镜像进行备份。 灾备设计 快照备份 阿里云ECS可使用快照进行系统盘、数据盘的备份。目前&#xff0c;阿…

Ubuntu取消sudo的输入密码

Ubuntu最近要安装软件&#xff0c;每次sudo都要输入一次密码&#xff0c;感觉很麻烦&#xff0c;于是想能不能设置为不输入密码&#xff0c;在网上找了一下解决办法。 主要参考这篇文章&#xff1a; Ubuntu取消sudo时输入密码 上面这篇文章使用的是vim&#xff0c;但是按照博…

Kotlin基础——接口和类

接口 使用 : 表示继承关系&#xff0c;只能继承一个类&#xff0c;但可以实现多个接口override修饰符表示重写可以有默认方法&#xff0c;若父类的默认方法冲突&#xff0c;则需要子类重写&#xff0c;使用super<XXX>.xxx()调用某一父类方法 interface Focusable {fun …

免费录屏软件哪个好用?免费录屏软件排行榜

对于您的团队&#xff0c;屏幕录像机可以用于多种原因——从为您的网站创建教程到记录反复出现的技术问题&#xff0c;再到向您的营销团队发送快速说明而不是电子邮件。 此外&#xff0c;我们不能忘记产品演示和培训视频&#xff0c;它们可供您团队中的许多部门使用&#xff0…

matlab模糊控制文件m代码实现和基础理论

1、内容简介 略 15-可以交流、咨询、答疑 通过m代码来实现生成模糊文件fis文件 2、内容说明 模糊文件m代码实现和基础理论 matlab模糊控制文件m代码实现和基础理论 模糊文件、m代码和模糊基础理论 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.co…

web前端开发第3次Dreamweave课堂练习/html练习代码《网页设计语言基础练习案例》

目标图片&#xff1a; 文字素材&#xff1a; 网页设计语言基础练习案例 ——几个从语义上和文字相关的标签 * h标签&#xff08;h1~h6&#xff09;&#xff1a;用来定义网页的标题&#xff0c;成对出现。 * p标签&#xff1a;用来设置网页的段落&#xff0c;成对出现。 * b…

NZ系列工具NZ08:图表添加标签工具

我的教程一共九套及VBA汉英手册一部&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到数据库&#xff0c;到字典&#xff0c;到高级的网抓及类的应用。大家在学习的过程中可能会存在困惑&#xff0c;这么多知识点该如何组织…

【车载开发系列】AutoSar中的CANTP

【车载开发系列】AutoSar中的CANTP 【车载开发系列】AutoSar中的CANTP 【车载开发系列】AutoSar中的CANTP一. CANTP相关术语二. CANTP相关概念1&#xff09;单帧&#xff1a;SF(Single Frame)2&#xff09;首帧&#xff1a;FF(First Frame)3&#xff09;连续帧CF(Consecutive F…

腾讯云3年轻量2核4G5M服务器756元,抓紧数量不多

腾讯云轻量应用服务器特价是有新用户限制的&#xff0c;所以阿腾云建议大家选择3年期轻量应用服务器&#xff0c;一劳永逸&#xff0c;免去续费困扰。腾讯云轻量应用服务器3年可以选择2核2G4M和2核4G5M带宽&#xff0c;3年轻量2核2G4M服务器540元&#xff0c;2核4G5M轻量应用服…

十五、信号量

1、概述 (1)前面介绍的队列(queue)可以用于传输数据&#xff1a;在任务之间、任务和中断之间。 (2)有些时候我们只需要传递状态&#xff0c;并不需要传递具体的信息&#xff0c;比如&#xff1a; 我的事做完了&#xff0c;通知一下你。卖包子了、卖包子了&#xff0c;做好了…

python 中用opencv开发虚拟键盘------可以只选择一个单词不会出现一下选择多个

一. 介绍 OpenCV是最流行的计算机视觉任务库&#xff0c;它是用于机器学习、图像处理等的跨平台开源库&#xff0c;用于开发实时计算机视觉应用程序。 CVzone 是一个计算机视觉包&#xff0c;它使用 OpenCV 和 Media Pipe 库作为其核心&#xff0c;使我们易于运行&#xff0c…

基于STM32控制直流电机加减速正反转仿真设计

**单片机设计介绍&#xff0c;基于STM32控制直流电机加减速正反转仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 本设计由STM32F103、L298N电机驱动电路、按键电路组成。通过按键可以控制电机&#xff0c;正转、反转、加…