【掌握C++ string 类】——【高效字符串操作】的【现代编程艺术】

专栏:C++学习笔记 

上一篇:【C++】——【 STL简介】——【详细讲解】

1. 为什么要学习 string 类?

1.1 C 语言中的字符串

在 C 语言中,字符串是以 '\0' 结尾的字符集合。如下所示:

#include <stdio.h>

int main() {
    char str[] = "Hello, World!";
    printf("%s\n", str);
    return 0;
}

需要记住的知识点:

  1. C 风格字符串是以 '\0' 结尾的字符数组。
  2. 使用 char 类型数组表示字符串。
  3. C 库提供的字符串操作函数与字符串本身是分离的。

小李的理解 C 语言中的字符串处理很基础,使用字符数组来存储,但需要手动管理内存,很容易出错。

1.2 两个面试题

字符串转整形数字

题目描述:将字符串表示的数字转换为整形数字,例如将 "12345" 转换为 12345

实现方法:可以使用 std::stoi 函数将字符串转换为整形数字。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string str = "12345";
    try {
        int num = std::stoi(str); // 将字符串转换为整形数字
        std::cout << "字符串 \"" << str << "\" 转换为整形数字: " << num << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cout << "无效的输入: " << str << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "输入超出范围: " << str << std::endl;
    }
    return 0;
}

 

需要记住的知识点

  1. 使用 std::stoi 函数将字符串转换为整形数字。
  2. std::stoi 在转换失败时会抛出异常,可以根据需要进行异常处理。

小李的理解

使用 std::stoi 函数非常方便,可以直接将表示数字的字符串转换为整形数字。这在处理用户输入或文件读取的数据时非常有用。

字符串相加

题目描述:将两个字符串拼接成一个字符串,例如将 "Hello, ""World!" 拼接成 "Hello, World!"

实现方法:可以使用 + 运算符或者 append 方法将两个字符串拼接。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string str1 = "Hello, ";
    std::string str2 = "World!";
    
    // 方法1:使用 + 运算符拼接
    std::string result1 = str1 + str2;
    std::cout << "使用 + 运算符拼接: " << result1 << std::endl;

    // 方法2:使用 append 方法拼接
    std::string result2 = str1;
    result2.append(str2);
    std::cout << "使用 append 方法拼接: " << result2 << std::endl;

    return 0;
}

需要记住的知识点

  1. 使用 + 运算符可以方便地将两个字符串拼接。
  2. 使用 append 方法也可以实现字符串拼接,适用于更复杂的字符串操作。

小李的理解

C++ 中提供了多种字符串拼接方法,+ 运算符简单直观,适合拼接固定数量的字符串。append 方法则适合在循环或更复杂的逻辑中使用。

详细运行结果分析

字符串转整形数字

#include <iostream>
#include <string>

int main() {
    std::string str = "12345";
    try {
        int num = std::stoi(str); // 将字符串转换为整形数字
        std::cout << "字符串 \"" << str << "\" 转换为整形数字: " << num << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cout << "无效的输入: " << str << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "输入超出范围: " << str << std::endl;
    }
    return 0;
}

异常处理

  • std::invalid_argument:如果输入的字符串不是一个有效的整数,则会抛出此异常。
  • std::out_of_range:如果输入的字符串表示的整数超出了整形数字的范围,则会抛出此异常。

需要注意的地方std::stoi 在处理非常大的数字时,可能会抛出 std::out_of_range 异常。

补充代码:处理无效输入和超出范围的情况

#include <iostream>
#include <string>

int main() {
    std::string str1 = "12345";
    std::string str2 = "12345abc";
    std::string str3 = "99999999999999999999999999";

    try {
        int num1 = std::stoi(str1); // 正确转换
        std::cout << "字符串 \"" << str1 << "\" 转换为整形数字: " << num1 << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cout << "无效的输入: " << str1 << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "输入超出范围: " << str1 << std::endl;
    }

    try {
        int num2 = std::stoi(str2); // 转换失败
        std::cout << "字符串 \"" << str2 << "\" 转换为整形数字: " << num2 << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cout << "无效的输入: " << str2 << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "输入超出范围: " << str2 << std::endl;
    }

    try {
        int num3 = std::stoi(str3); // 转换失败
        std::cout << "字符串 \"" << str3 << "\" 转换为整形数字: " << num3 << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cout << "无效的输入: " << str3 << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "输入超出范围: " << str3 << std::endl;
    }

    return 0;
}

 字符串相加

#include <iostream>
#include <string>

int main() {
    std::string str1 = "Hello, ";
    std::string str2 = "World!";
    
    // 方法1:使用 + 运算符拼接
    std::string result1 = str1 + str2;
    std::cout << "使用 + 运算符拼接: " << result1 << std::endl;

    // 方法2:使用 append 方法拼接
    std::string result2 = str1;
    result2.append(str2);
    std::cout << "使用 append 方法拼接: " << result2 << std::endl;

    return 0;
}

细节分析

  1. 使用 + 运算符拼接时,会生成一个新的字符串对象。
  2. 使用 append 方法拼接时,会在原有字符串对象上进行修改,适合在需要多次拼接的情况下使用以减少不必要的对象创建。

补充代码:使用多次拼接的情况

#include <iostream>
#include <string>

int main() {
    std::string str1 = "Hello, ";
    std::string str2 = "World!";
    std::string str3 = " How are you?";

    // 多次使用 + 运算符拼接
    std::string result1 = str1 + str2 + str3;
    std::cout << "多次使用 + 运算符拼接: " << result1 << std::endl;

    // 多次使用 append 方法拼接
    std::string result2 = str1;
    result2.append(str2).append(str3);
    std::cout << "多次使用 append 方法拼接: " << result2 << std::endl;

    return 0;
}

 

通过这些详细的代码示例和运行结果分析,相信你能更好地理解如何在 C++ 中进行字符串转整形数字和字符串相加操作,并在实际应用中灵活使用这些方法。

2. 标准库中的 string

2.1 string 类的基本介绍

文档介绍

  1. string 是一个表示字符序列的类。
  2. string 类提供了丰富的接口,类似于标准容器(如 vector),但还添加了专门用于操作单字节字符字符串的设计特性。
  3. stringbasic_string 模板类的一个实例,使用 charchar_traitsallocator 作为模板参数。
  4. string 类独立于编码处理字节。

需要记住的知识点

  1. string 类表示字符序列。
  2. 提供类似于标准容器的接口。
  3. string 实际上是 basic_string<char, char_traits, allocator> 的实例。

小李的理解string 类封装了字符串操作,提供了很多方便的函数,不需要我们手动管理内存。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";
    std::cout << str << std::endl;
    return 0;
}

2.2 string 类的常用接口

构造函数

string():构造一个空的 string 对象。

#include <iostream>
#include <string>

int main() {
    std::string s;
    std::cout << "Empty string: '" << s << "'" << std::endl;
    return 0;
}

 string(const char* s):用 C 风格字符串构造 string 对象。

#include <iostream>
#include <string>

int main() {
    std::string s("Hello, World!");
    std::cout << s << std::endl;
    return 0;
}

string(size_t n, char c):构造一个包含 n 个字符 cstring 对象。 

#include <iostream>
#include <string>

int main() {
    std::string s(10, 'a');
    std::cout << s << std::endl;
    return 0;
}

string(const string& s):拷贝构造函数,用另一个 string 对象构造新对象。

#include <iostream>
#include <string>

int main() {
    std::string s1 = "Hello";
    std::string s2(s1);
    std::cout << s2 << std::endl;
    return 0;
}

 

容量操作

size() / length():返回字符串的有效字符长度。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    std::cout << "Size: " << s.size() << std::endl;
    std::cout << "Length: " << s.length() << std::endl;
    return 0;
}

capacity():返回字符串的总容量。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    std::cout << "Capacity: " << s.capacity() << std::endl;
    return 0;
}

 empty():检测字符串是否为空,空则返回 true,否则返回 false

#include <iostream>
#include <string>

int main() {
    std::string s;
    if (s.empty()) {
        std::cout << "String is empty" << std::endl;
    }
    return 0;
}

clear():清空字符串中的有效字符。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    s.clear();
    std::cout << "String after clear: '" << s << "'" << std::endl;
    return 0;
}

reserve(size_t res_arg=0):为字符串预留空间,不改变有效字符个数。

#include <iostream>
#include <string>

int main() {
    std::string s;
    s.reserve(100);
    std::cout << "Reserved capacity: " << s.capacity() << std::endl;
    return 0;
}

resize(size_t n) / resize(size_t n, char c):将有效字符个数改为 n,多出的空间用字符 c 填充。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    s.resize(10, 'x');
    std::cout << "Resized string: " << s << std::endl;
    return 0;
}

访问及遍历操作

operator[]:返回指定位置的字符。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    std::cout << "Character at index 1: " << s[1] << std::endl;
    return 0;
}

begin() / end():返回字符串的起始迭代器和结束迭代器。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    for (auto it = s.begin(); it != s.end(); ++it) {
        std::cout << *it << ' ';
    }
    std::cout << std::endl;
    return 0;
}

 rbegin() / rend():返回反向迭代器。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    for (auto it = s.rbegin(); it != s.rend(); ++it) {
        std::cout << *it << ' ';
    }
    std::cout << std::endl;
    return 0;
}

 范围 for 循环:C++11 引入的简洁遍历方式。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    for (char c : s) {
        std::cout << c << ' ';
    }
    std::cout << std::endl;
    return 0;
}
修改操作

1.push_back(char c):在字符串末尾添加字符 c

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    s.push_back('!');
    std::cout << s << std::endl;
    return 0;
}

2.append(const string& str):在字符串末尾追加字符串 str。 

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    s.append(" World");
    std::cout << s << std::endl;
    return 0;
}

3.operator+=:在字符串末尾追加字符串。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    s += " World";
    std::cout << s << std::endl;
    return 0;
}

 

4.c_str():返回 C 风格字符串。

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    const char* c_str = s.c_str();
    std::cout << c_str << std::endl;
    return 0;
}

 

5.find(char c, size_t pos=0):从指定位置开始查找字符 c

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    size_t pos = s.find('l');
    if (pos != std::string::npos) {
        std::cout << "Character 'l' found at position: " << pos << std::endl;
    } else {
        std::cout << "Character not found" << std::endl;
    }
    return 0;
}

 

6.rfind(char c, size_t pos=npos):从指定位置开始反向查找字符 c

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    size_t pos = s.rfind('l');
    if (pos != std::string::npos) {
        std::cout << "Character 'l' found at position: " << pos << std::endl;
    } else {
        std::cout << "Character not found" << std::endl;
    }
    return 0;
}

 

7.substr(size_t pos=0, size_t n=npos):返回从指定位置开始的子字符串。 

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello, World!";
    std::string sub = s.substr(7, 5); // 从第7个位置开始,取5个字符
    std::cout << "Substring: " << sub << std::endl;
    return 0;
}

非成员函数

1.operator+:字符串拼接。

#include <iostream>
#include <string>

int main() {
    std::string s1 = "Hello";
    std::string s2 = " World";
    std::string s3 = s1 + s2;
    std::cout << s3 << std::endl;
    return 0;
}

 

2.operator>>:输入运算符重载。 

#include <iostream>
#include <string>

int main() {
    std::string s;
    std::cout << "Enter a string: ";
    std::cin >> s; // 从输入读取字符串,遇到空格结束
    std::cout << "You entered: " << s << std::endl;
    return 0;
}

3.operator<<:输出运算符重载。 

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello, World!";
    std::cout << s << std::endl; // 输出: Hello, World!
    return 0;
}

4.getline:读取一行字符串。 

#include <iostream>
#include <string>

int main() {
    std::string line;
    std::cout << "Enter a line of text: ";
    std::getline(std::cin, line); // 从输入读取一行字符串
    std::cout << "You entered: " << line << std::endl;
    return 0;
}

5.关系运算符:字符串比较。 

#include <iostream>
#include <string>

int main() {
    std::string s1 = "Hello";
    std::string s2 = "World";
    if (s1 < s2) {
        std::cout << s1 << " is less than " << s2 << std::endl;
    } else {
        std::cout << s1 << " is not less than " << s2 << std::endl;
    }
    return 0;
}

3. 扩展阅读

需要记住的知识点

  1. string 类是 basic_string 模板类的实例。
  2. 提供丰富的接口,简化字符串操作。
  3. 内存管理由 string 类自动处理,避免了手动管理内存的复杂性和风险。

小李的理解 string 类让字符串操作变得简单而安全。通过理解 string 类的各种接口和功能,可以更高效地编写 C++ 程序。

示例代码

找字符串中第一个只出现一次的字符

#include <iostream>
#include <string>

class Solution {
public:
    int firstUniqChar(const std::string& s) {
        int count[256] = {0};
        for (char c : s) {
            count[c]++;
        }
        for (size_t i = 0; i < s.size(); ++i) {
            if (count[s[i]] == 1) {
                return i;
            }
        }
        return -1;
    }
};

int main() {
    Solution solution;
    std::string s = "leetcode";
    int index = solution.firstUniqChar(s);
    if (index != -1) {
        std::cout << "The first unique character is at index: " << index << std::endl;
    } else {
        std::cout << "No unique character found" << std::endl;
    }
    return 0;
}

 

验证一个字符串是否是回文 

#include <iostream>
#include <string>
#include <algorithm>

class Solution {
public:
    bool isPalindrome(const std::string& s) {
        std::string filtered;
        for (char c : s) {
            if (isalnum(c)) {
                filtered += tolower(c);
            }
        }
        std::string reversed = filtered;
        std::reverse(reversed.begin(), reversed.end());
        return filtered == reversed;
    }
};

int main() {
    Solution solution;
    std::string s = "A man, a plan, a canal: Panama";
    bool result = solution.isPalindrome(s);
    if (result) {
        std::cout << "\"" << s << "\" is a palindrome" << std::endl;
    } else {
        std::cout << "\"" << s << "\" is not a palindrome" << std::endl;
    }
    return 0;
}

总结 

1. 为什么要学习 string 类?

C 语言中的字符串

  • C 风格字符串是以 '\0' 结尾的字符数组,使用 char 类型数组表示。
  • C 库提供的字符串操作函数与字符串本身是分离的,需要手动管理内存,容易出错。

字符串转整形数字

  • 使用 std::stoi 函数可以方便地将字符串转换为整形数字。
  • std::stoi 在转换失败时会抛出异常,可以进行异常处理。

字符串相加

  • 使用 + 运算符和 append 方法可以轻松实现字符串拼接。
  • + 运算符适合拼接固定数量的字符串,append 方法适合在循环或复杂逻辑中使用。

2. 标准库中的 string

基本介绍

  • string 类表示字符序列,提供类似于标准容器的接口。
  • string 实际上是 basic_string<char, char_traits, allocator> 的实例,封装了字符串操作,提供方便的函数和自动内存管理。

常用接口

构造函数
  • string():构造一个空的 string 对象。
  • string(const char* s):用 C 风格字符串构造 string 对象。
  • string(size_t n, char c):构造一个包含 n 个字符 cstring 对象。
  • string(const string& s):拷贝构造函数,用另一个 string 对象构造新对象。
容量操作
  • size() / length():返回字符串的有效字符长度。
  • capacity():返回字符串的总容量。
  • empty():检测字符串是否为空。
  • clear():清空字符串中的有效字符。
  • reserve(size_t res_arg=0):为字符串预留空间。
  • resize(size_t n) / resize(size_t n, char c):将有效字符个数改为 n,多出的空间用字符 c 填充。
访问及遍历操作
  • operator[]:返回指定位置的字符。
  • begin() / end():返回字符串的起始迭代器和结束迭代器。
  • rbegin() / rend():返回反向迭代器。
  • 范围 for 循环:C++11 引入的简洁遍历方式。
修改操作
  • push_back(char c):在字符串末尾添加字符 c
  • append(const string& str):在字符串末尾追加字符串 str
  • operator+=:在字符串末尾追加字符串。
  • c_str():返回 C 风格字符串。
  • find(char c, size_t pos=0):从指定位置开始查找字符 c
  • rfind(char c, size_t pos=npos):从指定位置开始反向查找字符 c
  • substr(size_t pos=0, size_t n=npos):返回从指定位置开始的子字符串。
非成员函数
  • operator+:字符串拼接。
  • operator>>:输入运算符重载。
  • operator<<:输出运算符重载。
  • getline:读取一行字符串。
  • 关系运算符:字符串比较。

3. 扩展阅读

  • string 类是 basic_string 模板类的实例,提供丰富的接口,简化字符串操作。
  • 内存管理由 string 类自动处理,避免了手动管理内存的复杂性和风险。

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

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

相关文章

git常用命令速查表

Git相关概念简述 版本库&#xff1a;git在本地开辟的一个存储空间&#xff0c;一般在 .git 文件里。工作区(workspace)&#xff1a; 就是编辑器里面的代码&#xff0c;我们平常开发直接操作的就是工作区。暂存区&#xff08;index/stage&#xff09;&#xff1a;暂时存放文件的…

java设计模式(十二)享元模式(Flyweight Pattern)

1、模式介绍&#xff1a; 享元模式是一种结构型设计模式&#xff0c;旨在通过共享对象来有效支持大量细粒度的对象。它通过将对象的状态分为内部状态&#xff08;可共享&#xff09;和外部状态&#xff08;不可共享&#xff09;来减少内存消耗和提高性能。内部状态存储在享元对…

webstorm 高效查看不同分支差异 摒弃你的git diff手动操作

背景 每次代码冲突或者版本发生异常时&#xff0c;排查不同版本时就是一个头大的问题&#xff0c;头大的点在于用 vscode 的 git diff 一点点地排查和比较&#xff0c;耗时耗力&#xff0c;版面展不开&#xff0c;commit 差异看不出来&#xff0c;每个页面的代码不同也不能快速…

为本地化准备营销材料的几个步骤

为本地化准备营销材料涉及几个关键步骤&#xff0c;以确保内容在文化上合适、语言上准确&#xff0c;并与目标受众相关。以下是五个基本步骤&#xff1a; 进行市场调查 了解目标市场至关重要。进行深入研究&#xff0c;以收集有关目标地区受众的文化细微差别、消费者行为、地…

一键安装部署,在 Ubuntu 服务器上快速搭建基于 Ghost CMS的网站

我们在上一篇内容中讲过&#xff0c;如何使用 Helm 在 Kubernetes 集群上安装 WordPress&#xff0c;创建高可用性网站。而这次我们将基于另一个流行的内容管理系统 Ghost CMS 在 DigitalOcean 云主机进行建站。 Ghost 也是开源的内容管理系统&#xff08;CMS&#xff09;&…

权限控制权限控制权限控制权限控制权限控制

1.权限的分类 视频学习&#xff1a;https://www.bilibili.com/video/BV15Q4y1K79c/?spm_id_from333.337.search-card.all.click&vd_source386b4f5aae076490e1ad9b863a467f37 1.1 后端权限 1. 后端如何知道该请求是哪个用户发过来的 可以根据 cookie、session、token&a…

昇思25天学习打卡营第15天 | Vision Transformer图像分类

内容介绍&#xff1a; 近些年&#xff0c;随着基于自注意&#xff08;Self-Attention&#xff09;结构的模型的发展&#xff0c;特别是Transformer模型的提出&#xff0c;极大地促进了自然语言处理模型的发展。由于Transformers的计算效率和可扩展性&#xff0c;它已经能够训练…

【机器学习】机器学习与图像识别的融合应用与性能优化新探索

文章目录 引言第一章&#xff1a;机器学习在图像识别中的应用1.1 数据预处理1.1.1 数据清洗1.1.2 数据归一化1.1.3 数据增强 1.2 模型选择1.2.1 卷积神经网络1.2.2 迁移学习1.2.3 混合模型 1.3 模型训练1.3.1 梯度下降1.3.2 随机梯度下降1.3.3 Adam优化器 1.4 模型评估与性能优…

Docker镜像加速配置

由于当前运营商网络问题&#xff0c;可能会导致您拉取 Docker Hub 镜像变慢&#xff0c;索引可以配置阿里云镜像加速器。阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 每个人镜像地址都不一样&#xff0c;需要登陆阿里云自行查看&#xff0c;地址在上面&a…

ctfshow-web入门-文件包含(web78、web79、web80、web81)

目录 1、web78 2、web79 3、web80 4、web81 1、web78 存在文件包含函数&#xff1a;include 直接上 php 伪协议&#xff0c;用 php://filter 读文件&#xff08;flag.php&#xff09;的源码&#xff0c;payload&#xff1a; ?filephp://filter/readconvert.base64-encode…

轻松实现百度大模型ERNIE对话

该代码直接可用&#xff0c;实现了流式输出&#xff0c;只需要在你自己的开发环境配置百度申请的QIANFAN_AK和QIANFAN_SK即可使用啦。// # 在.env文件中&#xff0c;设置以下内容&#xff0c;安全认证Access Key替换your_iam_ak&#xff0c;Secret Key替换your_iam_sk 不过需要…

Linux Ubuntu 将指定ip添加到DNS

请严格按照如下步骤操作 以ip地址&#xff1a;202.96.134.133 为例 1.修改 /etc/resolv.conf 文件 sudo gedit /etc/resolv.conf 添加 nameserver 8.8.8.8 和 nameserver 202.96.134.133&#xff0c; 如下图方框指定内容&#xff1a; 2.修改 /etc/resolvconf/resolv.conf.d…

Python28-7.1降维算法之LDA线性判别分析

线性判别分析&#xff08;Linear Discriminant Analysis, LDA&#xff09;是一种用于模式识别和机器学习的分类和降维技术。LDA通过找到能最大化类别间方差和最小化类别内方差的投影方向&#xff0c;实现样本的降维和分类。 LDA的基本思想 LDA的核心思想是通过线性变换将数据…

Docker学习笔记(一)概念理解

一、什么是docker容器 Docker容器是一种轻量级、可移植的软件封装技术&#xff0c;它允许开发者将应用程序及其依赖、配置文件、运行环境等打包到一个独立的、自包含的执行单元中。容器与虚拟机相似&#xff0c;都提供了隔离的运行环境&#xff0c;但容器更加轻量级&#xff0c…

Echarts折线+柱状图的多y轴

实现效果&#xff1a; 代码&#xff1a; <template><div class"test-echart"><div id"barLineChart" ref"barLineChart" :style"barLineStyle"></div></div> </template> <script> // imp…

MySQL之MHA高可用集群及故障切换

一、MHA概述 MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的mysql高可用环境下故障切换和主从复制的软件。MHA的出现就是为了解决mysql单点故障。Mysql故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障性切换操作。MHA能在故障切换的过程中最大程度…

【路由交换技术】Cisco Packet Tracer基础入门教程(五)

这一期我们来学习端口聚合&#xff0c;这是针对交换机的技术 前言 不知道大家有没有注意到&#xff0c;我们之前的实验在交换机与交换机之间只用一条线连接&#xff0c;像这样 通过今天的学习&#xff0c;我们要用两条线来连接交换机&#xff0c;就像这样&#xff08;为了能…

3D问界—法线空间与应用举例

问题提出&#xff1a;什么是法线空间&#xff0c;有哪些应用的场景&#xff1f; 法线空间&#xff08;Normal Space&#xff09;在计算机图形学中是一个重要的概念&#xff0c;特别是在处理表面法线&#xff08;Normal&#xff09;时常被提及。 1. 法线空间的分类 法线空间是相…

“工控机”是什么?和普通电脑有区别嘛!

在现代工业生产中,有一种特殊的计算机,它不像普通电脑那样被放置于明亮的办公室内,而是常常藏身于机器轰鸣、环境恶劣的工厂车间里,这就是工控机——工业控制计算机的简称。作为工业自动化领域不可或缺的核心设备,工控机不仅承载着监控与数据采集(SCADA)、过程控制、数据…

python 实现docx指定语言翻译(不丢失格式)

我这边有个需求需要把一份docx翻译成指定语言的文档并且保存&#xff0c;研究了下&#xff0c;记录。 首先先安装依赖 pip install python-docx1.1.2 googletrans4.0.0rc1 python-docx是用来读取docx的&#xff0c;googletrans使用来翻译的。 googletrans PyPI 这个是官方文…