C++正则表达式全攻略:从基础到高级应用

C++正则表达式全攻略:从基础到高级应用

  • 一、基础知识
  • 二、正则表达式的基本匹配
  • 三、C++中使用正则表达式
  • 四、高级正则表达式
  • 五、实践示例
  • 六、性能优化
    • 6.1、编译正则表达式
    • 6.2、避免过度使用回溯
    • 6.3、优化匹配算法
  • 七、总结

一、基础知识

正则表达式是一种用于匹配、搜索和编辑文本的字符串模式。它由一系列字符和特殊符号构成,可以灵活地表达文本的模式、结构和特征。正则表达式在各种编程语言和应用程序中广泛应用,包括C++。它可以用来在文本中查找特定模式的字符串、验证输入的格式、提取信息和进行文本替换等操作。

正则表达式的基本元素包括普通字符(如字母、数字和符号)、特殊字符(如通配符、边界符和量词)以及捕获组和反向引用等高级功能。通过组合这些元素,可以构建复杂的匹配规则,实现强大的文本处理功能。

C++中使用正则表达式的优势:

  1. 强大的文本处理能力:正则表达式提供了灵活的方式来描述文本模式和规则,能够轻松地实现复杂的文本匹配、搜索和提取功能。

  2. 通过正则表达式,可以快速验证用户输入的数据格式是否符合要求,提高了数据的准确性和一致性。

  3. 正则表达式可以轻松地进行文本替换和格式化操作,例如批量替换文本中的内容或者格式化输出文本。

  4. 正则表达式可以用较短的代码实现复杂的文本处理功能,提高代码的可读性和简洁性。

  5. 正则表达式可以用于日志分析、数据提取、文本解析等各种场景,为 C++ 提供了强大的文本处理工具。

在 C++ 中使用正则表达式,通过提供的<regex>头文件来实现。基本语法和规则:

  1. 普通字符:包括字母、数字和一些符号,表示自身字符。

  2. 特殊字符:包括元字符(如 ^$.*+?|\ 等),用于描述匹配规则。

  3. 量词:指定前面模式出现的次数,如 *(零次或多次)、+(一次或多次)、?(零次或一次),{m,n}(出现次数范围为m到n次)等。

  4. 转义字符:使用 \ 来转义特殊字符,使其成为普通字符。

  5. 字符类:用 [ ] 表示一组字符中的任意一个。比如 [abc] 匹配 “a”、“b” 或 “c” 中的任意一个。

  6. 捕获组:用( )将模式组合成一个单元,可以获取匹配的子串。

在 C++ 的 <regex> 头文件中,常用的类有 std::regexstd::smatchstd::regex_match 等,通过这些类可以实现正则表达式的匹配、搜索和提取。例如,使用 std::regex_match 函数来检查一个字符串是否与指定的正则表达式匹配,使用 std::smatch 类来存储匹配的结果。

正则表达式在 C++ 中的基本语法和规则与其他语言中的正则表达式基本相同,但在具体的实现上可能会有一些差异。可查看官方介绍。
在这里插入图片描述

二、正则表达式的基本匹配

  1. 匹配单个字符

    • 使用普通字符进行匹配,例如正则表达式 a 可以匹配字符串中的单个字符 “a”。
    • 使用元字符.进行匹配任意单个字符,例如正则表达式 s. 可以匹配字符串中的 “sa”、“sb”、“sc” 等。
  2. 匹配多个字符:

    • 使用量词*匹配前面的字符出现零次或多次,例如正则表达式ab*可以匹配 “a”, “ab”, “abb”, “abbb” 等。
    • 使用量词+匹配前面的字符出现一次或多次,例如正则表达式ab+可以匹配 “ab”, “abb”, “abbb” 等。
    • 使用量词?匹配前面的字符出现零次或一次,例如正则表达式ab?可以匹配 “a”, “ab” 等。
    • 使用花括号{m,n}匹配前面的字符出现m到n次,例如正则表达式a{2,4}可以匹配 “aa”, “aaa”, “aaaa”。
  3. 匹配起始和结束位置:

    • 使用锚字符^匹配字符串的起始位置,例如正则表达式^start可以匹配以 “start” 开头的字符串。
    • 使用锚字符$匹配字符串的结束位置,例如正则表达式end$可以匹配以 “end” 结尾的字符串。

当使用正则表达式进行文本匹配时,需要匹配字符类(character class)和排除字符类(negated character class)。字符类用来匹配一个字符集合中的任何一个字符,而排除字符类则用来匹配除指定字符集合之外的任何字符。

在正则表达式中使用方括号[]来表示一个字符类,方括号内包含要匹配的字符集合。例如:

  • [aeiou] 可以匹配任何一个小写元音字母。
  • [A-Za-z] 可以匹配任何一个大写或小写字母。
  • [0-9] 可以匹配任何一个数字字符。

另外,可以在方括号内使用连字符-来表示一个范围,如[a-z]表示匹配任何一个小写字母。

相反,使用脱字符^在字符类内表示排除字符类。例如:

  • [^aeiou] 可以匹配除了小写元音字母之外的任何字符。

正则表达式支持匹配重复出现的模式,使用不同的量词来指定重复匹配的规则。

常用的量词:

  • *:匹配前面的模式零次或多次。
  • +:匹配前面的模式一次或多次。
  • ?:匹配前面的模式零次或一次。
  • {n}:匹配前面的模式恰好n次。
  • {n,}:匹配前面的模式至少n次。
  • {n,m}:匹配前面的模式至少n次且至多m次。

例如:

  • a* 可以匹配零个或多个 “a”。
  • a+ 可以匹配一个或多个 “a”。
  • a? 可以匹配零个或一个 “a”。
  • a{3} 可以匹配恰好三个 “a”。
  • a{2,4} 可以匹配两个到四个 “a”。

正则表达式还有两个重要的概念是锚点(anchors)和分组(groups)

锚点用来指定匹配的位置,常用的锚点:

  • ^:匹配字符串的开始位置。
  • $:匹配字符串的结束位置。
  • \b:匹配单词边界。
  • \B:匹配非单词边界。

例如:

  • ^abc 可以匹配以 “abc” 开头的字符串。
  • xyz$ 可以匹配以 “xyz” 结尾的字符串。
  • \bword\b 可以匹配单独的 “word” 单词。
  • \Bword\B 可以匹配 “word” 单词的内部。

分组则用来把对模式的匹配结果进行分组,并对每个分组进行单独的处理。分组用括号()表示。例如:

  • (ab)+ 可以匹配 “ab”、“abab”、“ababab” 等。
  • (a|b) 可以匹配 “a” 或者 “b”。

三、C++中使用正则表达式

  1. 在C++中使用正则表达式需要包含 <regex> 头文件,并使用 std 命名空间。
  2. 使用std::regex类来创建正则表达式对象。正则表达式对象可以用来存储和表示一个特定的正则表达式模式。
  3. 使用正则表达式来进行匹配和搜索。在C++中使用std::regex_search函数和std::regex_match函数来实现这些功能。

示例:

#include <iostream>
#include <regex>

int main() {
    std::string text = "Hello, this is a sample text with some numbers 12345.";
    std::regex pattern("\\d+"); // 匹配一个或多个数字

    std::smatch matches; // 用于存储匹配结果

    if (std::regex_search(text, matches, pattern)) {
        std::cout << "Found match: " << matches.str() << std::endl;
    } else {
        std::cout << "No match found." << std::endl;
    }

    return 0;
}

使用std::regex_search函数来搜索文本text,并且尝试找到与正则表达式模式pattern匹配的内容。还使用了std::smatch类来存储匹配的结果,并打印出匹配的内容。

还可以使用std::regex_match函数来检查整个字符串是否完全匹配正则表达式模式。

if (std::regex_match(text, pattern)) {
    std::cout << "Full match found" << std::endl;
} else {
    std::cout << "No full match found" << std::endl;
}

此外,可以使用C++中的正则表达式库来提取和替换匹配的部分。C++标准库中的std::regex类和std::regex_replace函数可以完成这些任务。

示例:

#include <iostream>
#include <regex>

int main() {
    std::string text = "The cat sat on the mat.";
    std::regex pattern("\\b(cat)\\b"); // 匹配整个单词"cat"

    std::sregex_iterator it(text.begin(), text.end(), pattern);
    std::sregex_iterator end;

    for (; it != end; ++it) {
        std::smatch match = *it;
        std::cout << "Match found: " << match.str() << " at position " << match.position() << std::endl;
    }

    // 替换匹配的部分
    std::string replaced_text = std::regex_replace(text, pattern, "dog");
    std::cout << "Replaced text: " << replaced_text << std::endl;

    return 0;
}

使用std::sregex_iterator来迭代查找匹配的结果,然后使用std::regex_replace函数来替换匹配的部分。这里还使用了position()函数来获取匹配的位置。

四、高级正则表达式

(1)较为复杂的模式匹配。C++的正则表达式库支持一系列功能强大的正则表达式语法,可以用于更复杂的模式匹配需求,实现更精细的文本匹配和提取。
示例:

#include <iostream>
#include <regex>

int main() {
    std::string text = "The cat sat on the mat. The dog sat on the rug.";
    std::regex pattern("\\b(\\w+)\\s+sat\\s+on\\s+the\\s+(\\w+)\\b"); // 匹配类似"xxx sat on the xxx"的句子

    std::sregex_iterator it(text.begin(), text.end(), pattern);
    std::sregex_iterator end;

    for (; it != end; ++it) {
        std::smatch match = *it;
        std::cout << "Match found: " << match.str() << std::endl;
        std::cout << "First captured group: " << match[1].str() << std::endl;
        std::cout << "Second captured group: " << match[2].str() << std::endl;
    }

    return 0;
}

(2)使用捕获组和回溯。捕获组允许在正则表达式中标记并捕获特定的部分,而回溯则允许在替换文本中引用捕获的内容。
示例:

#include <iostream>
#include <regex>

int main() {
    std::string text = "The price is $10.99. The total is $25.50.";
    std::regex pattern("\\$(\\d+\\.\\d+)"); // 匹配美元金额

    std::string replaced_text = std::regex_replace(text, pattern, "¥$1"); // 使用捕获组的内容进行替换
    std::cout << "Replaced text: " << replaced_text << std::endl;

    return 0;
}

使用了捕获组来匹配金额,并在替换文本中使用了$1来引用捕获的内容进行替换。这里的$1表示使用第一个捕获组的内容来替换匹配的部分。

(3)懒惰匹配与贪婪匹配。懒惰匹配和贪婪匹配用于描述量词的匹配方式。贪婪匹配尽可能多地匹配字符串,而懒惰匹配则尽可能少地匹配字符串。

在C++的正则表达式中使用?来表示懒惰匹配。示例:

#include <iostream>
#include <regex>

int main() {
    std::string text = "The cat sat on the mat. The dog sat on the rug.";
    std::regex greedy_pattern("s[a-z]+t"); // 贪婪匹配,尽可能多地匹配s和t之间的字母
    std::regex lazy_pattern("s[a-z]+?t");  // 懒惰匹配,尽可能少地匹配s和t之间的字母

    std::sregex_iterator it_greedy(text.begin(), text.end(), greedy_pattern);
    std::sregex_iterator end_greedy;
    for (; it_greedy != end_greedy; ++it_greedy) {
        std::smatch match = *it_greedy;
        std::cout << "Greedy Match found: " << match.str() << std::endl;
    }

    std::sregex_iterator it_lazy(text.begin(), text.end(), lazy_pattern);
    std::sregex_iterator end_lazy;
    for (; it_lazy != end_lazy; ++it_lazy) {
        std::smatch match = *it_lazy;
        std::cout << "Lazy Match found: " << match.str() << std::endl;
    }

    return 0;
}

贪婪匹配尽可能多地匹配了s和t之间的字母,而懒惰匹配尽可能少地匹配了s和t之间的字母。

(4)向前和向后查找。向前和向后查找提供了一种基于当前匹配位置的相对定位功能,能够查找在特定位置之前或之后的模式。这对于需要匹配特定上下文的情况非常有用。

示例:

#include <iostream>
#include <regex>

int main() {
    std::string text = "The quick brown fox jumps over the lazy dog";
    std::regex forward_pattern("\\b\\w+(?=\\sfox)"); // 向前查找,匹配fox之前的单词
    std::regex backward_pattern("(?<=brown\\s)\\w+\\b"); // 向后查找,匹配brown之后的单词

    std::smatch match;
    if (std::regex_search(text, match, forward_pattern)) {
        std::cout << "Forward match found: " << match.str() << std::endl;
    }

    if (std::regex_search(text, match, backward_pattern)) {
        std::cout << "Backward match found: " << match.str() << std::endl;
    }

    return 0;
}

向前查找使用 (?=\sfox) 来匹配 fox 之前的单词,向后查找使用 (?<=brown\s) 来匹配 brown 之后的单词。

五、实践示例

(1)数据验证与格式化。邮箱地址进行验证和格式化:

#include <iostream>
#include <regex>
#include <string>

bool isValidEmail(const std::string& email) {
    std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
    return std::regex_match(email, pattern);
}

std::string formatPhoneNumber(const std::string& phoneNumber) {
    std::regex pattern(R"(\b(\d{3})(\d{3})(\d{4})\b)");
    return std::regex_replace(phoneNumber, pattern, R"($1-$2-$3)");
}

int main() {
    // 邮箱验证
    std::string email = "2505756506@qq.com";
    if (isValidEmail(email)) {
        std::cout << "Email is valid" << std::endl;
    } else {
        std::cout << "Invalid email" << std::endl;
    }

    // 电话号码格式化
    std::string phoneNumber = "12345678901";
    std::string formattedNumber = formatPhoneNumber(phoneNumber);
    std::cout << "Formatted phone number: " << formattedNumber << std::endl;

    return 0;
}

验证是通过std::regex_match实现,而格式化是通过std::regex_replace实现。

(2文本提取与分析。提取文本中的数字并进行分析:

#include <iostream>
#include <regex>
#include <string>
#include <vector>

std::vector<int> extractNumbers(const std::string& input) {
    std::vector<int> numbers;
    std::regex pattern(R"(\d+)");
    std::sregex_iterator iter(input.begin(), input.end(), pattern);
    std::sregex_iterator end;

    for (; iter != end; ++iter) {
        numbers.push_back(std::stoi(iter->str()));
    }

    return numbers;
}

int main() {
    std::string text = "The price of the item is $250. The weight is 5.5 pounds.";
    std::vector<int> numbers = extractNumbers(text);

    std::cout << "Extracted numbers: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // 分析提取的数字
    int sum = 0;
    for (int num : numbers) {
        sum += num;
    }

    std::cout << "Sum of the numbers: " << sum << std::endl;

    return 0;
}

(3)日志文件分析。提取和分析日志文件中的关键信息,例如时间戳、IP地址、错误信息等:

#include <iostream>
#include <fstream>
#include <regex>
#include <string>

void analyzeLogFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cerr << "Error opening file " << filename << std::endl;
        return;
    }

    std::regex timePattern(R"((\d{2}:\d{2}:\d{2}))");
    std::regex ipPattern(R"((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))");
    std::regex errorPattern(R"(error|ERROR)");

    std::string line;
    while (std::getline(file, line)) {
        std::smatch timeMatch;
        std::smatch ipMatch;
        std::smatch errorMatch;

        if (std::regex_search(line, timeMatch, timePattern) && std::regex_search(line, ipMatch, ipPattern) && std::regex_search(line, errorMatch, errorPattern)) {
            std::cout << "Timestamp: " << timeMatch[0] << ", IP address: " << ipMatch[0] << ", Error: " << errorMatch[0] << std::endl;
        }
    }

    file.close();
}

int main() {
    analyzeLogFile("example.log");
    return 0;
}

(4)高级的文本处理应用。

#include <iostream>
#include <regex>
#include <string>

void advancedTextProcessing(const std::string& text) {
    // 通过正则表达式替换文本中的日期格式
    std::regex datePattern(R"(\b(\d{1,2})/(\d{1,2})/(\d{4})\b)");
    std::string processedText = std::regex_replace(text, datePattern, "$3-$1-$2");
    std::cout << "Processed text with date format replaced: " << processedText << std::endl;

    // 提取文本中的URL
    std::regex urlPattern(R"((https?://\S+))");
    std::sregex_iterator iter(text.begin(), text.end(), urlPattern);
    std::sregex_iterator end;

    std::cout << "Extracted URLs: ";
    for (; iter != end; ++iter) {
        std::cout << iter->str() << " ";
    }
    std::cout << std::endl;

    // 使用正则表达式分组提取文本中的标题和内容
    std::regex articlePattern(R"(<title>(.*?)</title>.*?<content>(.*?)</content>)", std::regex::dotall);
    std::smatch match;
    if (std::regex_search(text, match, articlePattern)) {
        std::cout << "Title: " << match[1].str() << std::endl;
        std::cout << "Content: " << match[2].str() << std::endl;
    }
}

int main() {
    std::string sampleText = "Today's date is 12/30/2023. Visit our website at https://www.baidu.com/ for more information. <title>Sample Title</title><content>This is a sample content.</content>";
    advancedTextProcessing(sampleText);
    return 0;
}

六、性能优化

6.1、编译正则表达式

  1. 预先编译正则表达式:对于会重复使用的正则表达式,建议在程序初始化阶段就进行编译,以避免在每次匹配时都重新编译。可以使用 std::regex 的构造函数来进行编译。

    std::regex regExpr(pattern); // 预先编译正则表达式
    
  2. 在可能的情况下,尽量使用简单的正则表达式模式,避免过于复杂和耗时的匹配规则。

  3. 在正则表达式中尽量使用非贪婪量词(*?+?{n, m}?)来进行匹配,以避免贪婪匹配导致的性能问题。

  4. 如果可能的话,尽量在正则表达式中使用具体的字符串,而不是通用的通配符,以减少匹配的复杂度。

  5. 如果程序需要频繁使用多个正则表达式,可以将它们预先编译并存储起来,以提高性能。

    std::unordered_map<std::string, std::regex> regexCache;
    regexCache["datePattern"] = std::regex(R"((\d{1,2})/(\d{1,2})/(\d{4}))");
    

6.2、避免过度使用回溯

在编写正则表达式时,避免过度使用回溯是非常重要的,因为回溯会导致正则表达式的性能下降,尤其是在处理长文本或复杂模式时。

  1. 尽量使用非贪婪量词(例如*?+?{n,m}?),以避免匹配过程中出现不必要的回溯。

  2. 避免在正则表达式中过度使用嵌套的重复,因为这可能导致回溯的增加。尽量简化模式,减少嵌套的深度。

  3. 使用原子组: 原子组可以避免回溯,因此可以使用它们来限制回溯发生的范围。

  4. 如果只需要匹配特定的固定字符串,最好直接使用字符串匹配函数,而不是使用正则表达式。

  5. 有些正则表达式引擎可以将正则表达式编译为确定性有限自动机(DFA),这种方法可以避免回溯,提高匹配性能。

  6. 预先编译正则表达式: 如前面所述,在程序初始化阶段就进行编译,可以避免在每次匹配时都重新编译,提高性能。

6.3、优化匹配算法

  1. 不同的算法在不同的场景下有不同的性能表现。例如,在处理大型文本时,基于有限自动机(DFA)的算法会比回溯算法更高效。

  2. 回溯是一种耗时的操作,尽量避免使得正则表达式需要进行大量回溯,可以通过优化正则表达式模式或使用非贪婪量词来减少回溯次数。

  3. 如果只需要匹配特定的固定字符串,直接使用字符串匹配函数(如 strstr 或其它语言的等效函数)可能比使用正则表达式更高效。

  4. 如果需要频繁匹配相同的正则表达式,可以缓存匹配结果以减少重复的匹配操作。

  5. 对输入文本进行预处理(例如,去除不需要进行匹配的部分)可以减少匹配的复杂度,提高匹配性能。

  6. 对于大量需要匹配的数据,使用多线程并行匹配来加快匹配速度。

七、总结

正则表达式应用方向:

  1. 输入验证:用于验证用户输入的数据是否符合特定的格式,如电子邮件地址、电话号码、日期、密码等。

  2. 数据提取:从文本中提取特定模式的数据,例如从网页中提取链接、从日志文件中提取特定格式的数据等。

  3. 替换和格式化:在文本处理中用于替换特定模式的字符串或格式化文本,例如将日期格式进行统一、删除不需要的空格等。

  4. URL路由:在web开发中用于定义和匹配URL路由规则,实现页面的跳转和参数的提取。

  5. 语法分析:在编译器和解释器中用于解析和处理特定语法和结构,如正则表达式引擎本身就是一个语法解析器的实现。

  6. 日志分析:用于分析和筛选大量日志数据中的特定模式和信息。

  7. 数据清洗:在数据处理和清洗中使用正则表达式来识别和处理不规范的数据格式。

  8. 敏感词过滤:用于在文本中过滤敏感词和不良内容。

  9. 字符串匹配:用于查找字符串中是否包含特定的模式或关键字。

在这里插入图片描述

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

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

相关文章

【如何选择Mysql服务器的CPU核数及内存大小】

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

【数据结构-单链表】(C语言版本)

今天分享的是数据结构有关单链表的操作和实践&#xff08;图解法&#xff0c;图变化更利于理解&#xff09; 记录宗旨&#x1f4dd;&#xff1a; 眼&#xff08;脑&#xff09;过千遍&#xff0c;不如手过一遍。 我们都知道单链表是一种常见的链表数据结构&#xff0c;由一系列…

关于标准那些事——第六篇 四象之“白虎”(要素的编写)

两仪生四象——东方青龙&#xff08;木&#xff09;、西方白虎&#xff08;金&#xff09;、南方朱雀&#xff08;火&#xff09;、北方玄武&#xff08;水&#xff09; 分别对应标准编写之四象——层次的编写、要素的编写、要素的表述、格式的编排。 今天来分享一下 要素的编…

【零基础入门TypeScript】TypeScript - 环境设置

目录 本地环境设置 文本编辑器 TypeScript 编译器 安装 Node.js 在 Windows 上安装 在 Mac OS X 上安装 IDE支持 视觉工作室代码 在 Windows 上安装 在 Mac OS X 上安装 在 Linux 上安装 括号 括号的 TypeScript 扩展 var message:string "Hello World"…

如何使用Node.js快速创建本地HTTP服务器并实现公网访问服务端

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

WPF+Halcon 培训项目实战(8-9):WPF+Halcon初次开发

文章目录 前言相关链接项目专栏运行环境匹配图片WPF Halcon组件HSmartWindowControlWPF绑定读取图片运行代码运行结果 抖动问题解决运行结果 绘制矩形绘制图像会消失 绘制对象绑定事件拖动事件 前言 为了更好地去学习WPFHalcon&#xff0c;我决定去报个班学一下。原因无非是想…

试用了所有热门的报表工具,终于找到这款好用的报表工具,太赞了

经常有朋友向我咨询&#xff0c;有没有哪个报表工具既简单易上手&#xff0c;又适合绝大多数普通职场人使用。经过我的一番研究&#xff0c;我发现大家在选择报表工具时&#xff0c;主要关注以下3点&#xff1a; 1. 简单易上手&#xff1a;大家希望报表工具的学习门槛低&#…

怎样才能找到合适的产品说明书模板?方法献上

制作一份专业而吸引人的产品手册对于企业来说至关重要。然而&#xff0c;对于许多企业和个人而言&#xff0c;制作产品手册可能是一个挑战&#xff0c;因为需要一定的设计和排版能力。为了帮助大家更轻松地制作出优质的产品手册&#xff0c;下面将向大家推荐三款优秀的产品手册…

杭州默医宠物医院:猫咪应激,铲屎官一定要重视!

“猫咪应激”铲屎官们都略有耳闻&#xff0c;甚至自家猫主子也有出现过&#xff0c;但很多铲屎官对猫咪应激不重视。猫咪应激的程度可能远超出我们的想象。 一、猫应激的原因有以下方面&#xff1a; ①外出 ②搬家 ③洗澡 ④猫群不合 ⑤强迫猫咪做某些行为 ⑥主人的一惊…

jenkins+pytest+allure

jenkinspytestallure allure下载地址 Releases allure-framework/allure2 GitHub allure环境变量配置 allure --version 查看版本(确定是否配置完成) python安装allure插件 pip install allure-pytest pytest的运行指令 pytest -sv test_demo.py 开发完毕后将代码上传到…

算法训练day56|动态规划part16

583. 两个字符串的删除操作 逆向思路&#xff1a;求最长公共子序列&#xff0c;在用总长度-2*公共子序列长度 正向思路&#xff1a;删除多少 1. dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结…

重读VIT:深入探索细节与影响

1. 模型架构 提起一个新模型&#xff0c;我想大家最关心的事就是&#xff1a;它到底长什么样&#xff1f;输入输出是什么&#xff1f;我要怎么用&#xff1f;所以&#xff0c;我们先来看模型架构。 1.1 Bert结构 前面说过&#xff0c;VIT几乎和Bert一致&#xff0c;我们来速扫…

隐退三年,身价4800亿元的Google创始人出面只为给他写代码?

随着 Google 发布迄今为止最强大、最通用、最灵活的大模型 Gemini 以此正面叫板 ChatGPT 之际&#xff0c;近日不少人开始细细研读 Gemini 背后的技术详解论文&#xff08;https://arxiv.org/abs/2312.11805&#xff09;&#xff0c;这一看不打紧&#xff0c;竟有许多令人意外的…

mac中excel条件格式找到每一列的最大值并标红

假设现在excel有A1:R24组数据&#xff0c;最终效果如下 先选择要处理数据的第一列&#xff0c;然后点击【条件格式】-【新建规则】 style选择【classic】以及【Use a formula to determine which cells to format】&#xff0c;输入规则【C3MAX(C$3:C$24)】 注意这里C$3前面没…

ARM CCA机密计算硬件架构之内存管理

实施了TrustZone安全扩展的Arm A-profile处理器呈现两个物理地址空间(PAS): 非安全物理地址空间安全物理地址空间Realm管理扩展增加了两个PAS: Realm物理地址空间Root物理地址空间下图显示了这些物理地址空间以及如何在工作系统中实施这些空间: 正如表格所示,根状态能够访…

干洗店洗鞋店小程序核心功能有哪些?

在繁忙的生活中&#xff0c;我们的鞋子常常承载着风尘仆仆的故事。而洗鞋小程序&#xff0c;就是那个让您的鞋子焕然一新的魔法师。通过这个小程序&#xff0c;您可以在线预约、支付&#xff0c;查询洗鞋订单&#xff0c;并与洗鞋店铺进行互动&#xff0c;轻松享受专业的洗鞋服…

【嵌入式学习笔记-01】什么是UC,操作系统历史介绍,计算机系统分层,环境变量(PATH),错误

【嵌入式学习笔记】什么是UC&#xff0c;操作系统历史介绍&#xff0c;计算机系统分层&#xff0c;环境变量&#xff08;PATH&#xff09;&#xff0c;错误 文章目录 什么是UC?计算机系统分层什么是操作系统&#xff1f; 环境变量什么是环境变量&#xff1f;环境变量的添加&am…

Redis:原理+项目实战——Redis实战1(session实现短信登录(并剖析问题))

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis的Java客户端 &#x1f4da;订阅专栏&#xff1a;Redis速成 希望文章对你们有所帮助…

Apache Doris (五十八): Doris - Join优化原理

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. Runtime Filter Join优…