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

本文参考网课为 数据结构与算法 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)及它们之间的关系 ↩︎

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

rocksdb中测试工具Benchmark.sh用法(基准、性能测试)

1.首先要安装db_bench工具&#xff0c;这个工具在成功安装rocksdb之后就自动存在了&#xff0c;主要是在使用make命令之后就成功安装了&#xff0c;详情请见我之前的文章 2.确保成功安装db_bench之后&#xff0c;找到安装的rocksdb目录下面的tools文件夹&#xff0c;查看里面是…

如何让VirtualBox系统使用Ubuntu主机的USB

如何让VirtualBox系统使用Ubuntu主机的USB 当通过 VirtualBox 尝试不同的操作系统时&#xff0c;访问虚拟机中的 USB 驱动器来传输数据非常有用。 安装Guest Additions 自行百度安装Guest Additions的方法&#xff0c;最终的效果如下&#xff1a; 将用户添加到 vboxusers 组…

前端面试题 计算机网络

文章目录 ios 7层协议tcp协议和udp协议的区别tcp协议如何确保数据的可靠http和tcp的关系url输入地址到呈现网页有哪些步骤post和get本质区别&#xff0c;什么时候会触发二次预检GET请求&#xff1a;POST请求&#xff1a;触发二次预检&#xff08;CORS中的预检请求&#xff09;&…

通过结构间比值比较迭代次数

( A, B )---3-30-2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;A有5个点&#xff0c;B全是0&#xff0c;排列组合。让A,B训练集分别有3&#xff0c;4&#xff0c;5&#xff0c;6张图片&#xff0c;统计迭代次数并排序。 先比较图片数量是3和4的情况 n4 迭代次数…

移植LVGL到单片机的一个demo简单介绍

简介 背景&#xff1a; 本文使用的是主控IC为stm32f103zet6, 显示IC为ST7735s&#xff0c;它是128*160的像素&#xff0c;色深为RGB565颜色。 官方虽然说LVGL移植平台只需 64kB 闪存和 8kB RAM 就足以满足简单的用户界面。但我移植到stm32f103c8t6&#xff0c;不管怎么修改配…

【数据结构】入队序列出队序列问题(以21年408真题举例)

题型说明 一般是一个队列&#xff0c;其中一边可以入队&#xff0c;另一边可以入队和出队只可入队的含义是从这个方向是以队列形式存在可以入队和出队表示此边以堆形式存在 怎么分析&#xff1f; 以21年408真题举例 考点分析 出队序列存在两种情况&#xff1a;入之后就出&…

是谁为所欲为,将我的电脑控作己用?

在刚刚发完短篇小杂文《要找事做&#xff0c;我真怕被闲死》的投稿之后&#xff0c;笔者继续浏览社交网站的网页搜索...... 正看到《温州殡仪馆 》《温州动车723事故死亡高 》《 动车脱轨温州事件真正原因》《 浙江平阳县灭门惨案处理结果公布》《 温州厉秀珍死亡 》这一串又一…

从HDFS到对象存储,抛弃Hadoop,数据湖才能重获新生?

Hadoop与数据湖的关系 1、Hadoop时代的落幕2、Databricks和Snowflake做对了什么3、Hadoop与对象存储&#xff08;OSD&#xff09;4、Databricks与Snowflake为什么选择对象存储5、对象存储面临的挑战 1、Hadoop时代的落幕 十几年前&#xff0c;Hadoop是解决大规模数据分析的“白…

Qt开发流程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

SpringBoot整合第三方技术

SpringBoot整合JUnit 名称&#xff1a;SpringBootTest 类型&#xff1a;测试类注解 位置&#xff1a;测试类定义上方 作用&#xff1a;设置JUnit加载的SpringBoot启动类SpringBootTest(classes Springboot05JUnitApplication.class) class Springboot07JUnitApplicationTests…

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

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

redis学习指南--概览篇

redis怎么学 官方学习网站&#xff1a; redis.cn 1、整体了解redis redis是一个内存数据库、kv数据库&#xff0c;数据结构数据库&#xff0c;redis中数据都是存储在redis中&#xff0c;可以通过key查找value&#xff0c;value可以有多种数据结构&#xff0c;有&#xff1a;…

归并外排序实现

文章目录 1. 海量数据排序 1. 海量数据排序 如果我们想在文件中海量数据排序&#xff0c;我们比较适合选用归并排序。 首先&#xff0c;我们要看要排序的文件的大小&#xff0c;比如说这个文件是10G&#xff0c;而我们的内存是1G&#xff0c;那么我们可以把文件切成10份。这样…

汽车操纵稳定性matlab仿真

1、内容简介 略 14-可以交流、咨询、答疑 2、内容说明 汽车操纵稳定性matlab仿真&#xff0c;包含完整的论文 操纵动力学、两自由度 摘要&#xff1a;当今&#xff0c;仿真技术日益广泛地应用于汽车工程领域&#xff0c;操纵稳定性研究越来越多地使用成熟的计算机仿真理论…

【LeetCode:715. Range 模块 | 线段树】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

unity line renderer绘制的颜色不是想要的红色

线条不是暗红色的&#xff0c;用的是默认的红色 将材质选则为如下即可

javaSE学习笔记(七)IO流

目录 六、IO流 1.IO流概述 概念 分类 IO体系 简单介绍 最重要&#xff0c;最常用&#xff0c;最常见的两个流 2.File类 路径分隔符 绝对路径和相对路径 构造方法 方法 重命名注意事项 删除注意事项 3.FileInputStream&FileOutputStream FileInputStream 获取…

哨兵1号回波数据(L0级)产品目录介绍

1 数据包总览 哨兵1号L0级数据产品系列如下图所示&#xff0c;本文针对图中红框中的数据产品进行介绍&#xff08;定标数据、噪声数据没下载到。。。&#xff09;。 1.1 数据包名称 示例&#xff1a; S1A_S3_RAW__0SSV_20211230T105851_20211230T105907_041237_04E698_94F0.S…

github私有仓库开发,公开仓库发布版本

文章目录 github私有仓库开发,公开仓库发布版本需求背景实现思路GitHub Releases具体步骤广告 github私有仓库开发,公开仓库发布版本 需求背景 github私有仓库开发,公开仓库发布版本&#xff0c;既可以保护源代码,又可以发布版本给用户使用。许多知名软件项目都采用了这样的开…

Qt 子窗口不设置parent时,如何随主窗口关闭

遇到个情况&#xff0c;new一个子窗口的时候&#xff0c;如果指定了parent&#xff0c;那在最小化这个子窗口时这个子窗口并不是在缩小到任务栏&#xff0c;而是在任务栏的左上角。像这种&#xff1a; 并且&#xff0c;点击主窗口之后&#xff0c;子窗口也始终显示在主窗口之前…