跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ string 类进阶:成员函数与全局操作实战指南

C++ string 类进阶讲解涵盖 c_str/data 转换、find 系列查找、substr 截取及 getline 输入。重点对比了不同查找函数的适用场景与边界处理,强调 C++11 后 data 与 c_str 等价性,以及 getline 读取整行与 cin>> 的区别。提供实际代码示例辅助理解字符串操作的核心逻辑与常见陷阱。

月光旅人发布于 2026/3/21更新于 2026/8/2338 浏览
C++ string 类进阶:成员函数与全局操作实战指南

文章配图

💡 核心提示:本文基于 C++ string 类(二)的内容进行补充,重点讲解常用成员函数及全局操作。

string 类中的一些成员函数

文章配图

下面分别详解几个高频使用的函数,compare 由于使用频率较低,感兴趣的同学可自行查阅文档。

c_str()

c_str() 会返回一个指向 std::string 内部字符数组的只读 const char* 指针,且该数组以 \0(空字符)结尾 —— 完全符合 C 语言风格字符串的规范。

当你需要把 std::string 传给仅支持 C 风格字符串(char*/const char*)的函数时,必须用 c_str()。比如调用 C 标准库文件操作函数 fopen 或打印函数 printf 时:

#include <iostream>
#include <string>
using namespace std;

int main() {
    string filename("Test.cpp");
    FILE* fout = fopen(filename.c_str(), "r");
    if (fout) {
        cout << "打开文件成功" << endl;
        fclose(fout);
    }
    return 0;
}

💡 核心要点:

  • 作用:将 C++ 的 std::string 转换为 C 风格的 const char* 字符串。
  • 场景:调用 C 语言标准库函数(如 fopen、printf、strlen)时传参。
  • 禁忌:不修改返回的指针内容,不单独保存指针(需与原 std::string 对象同生命周期)。

data()

data() 的核心功能和 c_str() 几乎一致:返回一个指向 std::string 内部字符数组的只读 const char* 指针,指向字符串的首字符。

但它的行为在 C++11 前后有个关键变化,这是理解它的核心:

  • C++11 及以后:data() 和 c_str() 完全等价 —— 返回的字符数组也以 \0 结尾,本质上是同一个函数的两种写法。
  • C++11 之前:data() 只返回指向字符数组的指针,不保证末尾有 \0(仅包含有效字符),而 c_str() 必须保证末尾有 \0。
#include <iostream>
#include <string>
#include <cstdio>

int main() {
    std::string str = "hello";
    // C++11 后,这两行代码效果完全一样
    FILE* f1 = fopen(str.c_str(), "w");
    FILE* f2 = fopen(str.data(), "w");

    // 打印字符数据(无需 \0 的场景,data() 更贴合语义)
    const char* ptr = str.data();
    for (int i = 0; i < str.size(); ++i) {
        std::cout << ptr[i]; // 输出:hello
    }
    if (f1) fclose(f1);
    if (f2) fclose(f2);
    return 0;
}

💡 核心要点:

  • 区别:仅存在于 C++11 前的 \0 结尾保证,C++11 后无差异。
  • 选择:适配 C 函数用 c_str()(语义更清),仅访问字符数据用 data(),C++11 后两者可互换。

get_allocator()

简单来说:std::string 内部的字符数组并不是直接用 new 分配的,而是通过分配器(allocator) 来管理内存申请 / 释放。get_allocator() 就是返回这个分配器对象,让你能'复用'和 std::string 相同的内存分配规则。

分配器的本质是一个'内存管理工具',STL 容器默认用 std::allocator<char>,它的行为和普通的 new/delete 几乎一致,但提供了更灵活的内存管理接口。目前这部分不需要深入理解,了解即可。

copy()

copy() 的核心是:把 std::string 中指定范围的字符,拷贝到你提供的外部字符数组中。和 strcpy/c_str() 不同的是:它不自动在目标数组末尾加 \0(需手动处理);可以只拷贝字符串的一部分;直接操作字符数组,无需先转 C 风格字符串。

参数说明:

  • dest:目标字符数组(你需要提前分配好内存)。
  • count:要拷贝的字符个数。
  • pos:从原字符串的第 pos 个位置开始拷贝(默认从 0 开始)。
  • 返回值:实际拷贝的字符数。
#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, C++ string!";
    char buf[20] = {0}; // 初始化数组,避免垃圾值

    // 示例 1:拷贝前 5 个字符到 buf
    size_t copied = str.copy(buf, 5); // 从 pos=0 开始,拷贝 5 个字符
    buf[copied] = '\0'; // 手动加 \0,否则打印会乱码
    std::cout << "示例 1:" << buf << std::endl; // 输出:Hello

    // 示例 2:从 pos=7 开始,拷贝 5 个字符("C++ s")
    str.copy(buf, 5, 7);
    buf[5] = '\0';
    std::cout << "示例 2:" << buf << std::endl; // 输出:C++ s

    // 示例 3:拷贝超出字符串长度的情况(自动截断)
    size_t copied2 = str.copy(buf, 100, 0);
    buf[copied2] = '\0';
    std::cout << "示例 3:" << buf << "(实际拷贝" << copied2 << "个)" << std::endl;
    return 0;
}

💡 核心要点:

  • 特点:不自动加 \0、可指定拷贝起始位置和长度、越界自动截断。
  • 避坑:手动补 \0、保证目标数组内存足够。
  • 建议:日常提取子串优先用 substr(),仅在需要写入裸 char 数组时才用 copy()。

find 系列(重点)

1. find()

find() 的核心是:从指定起始位置开始,在原字符串中查找第一个匹配的'字符 / 子串',返回其起始下标;如果没找到,返回 std::string::npos。简单说,它就是字符串的'搜索定位器'。

#include <iostream>
#include <string>
using namespace std;

int main() {
    string filename("Testaxxx.cpp");
    size_t pos = filename.find('.'); // 找到了返回第一次匹配字符的位置,没找到返回 string::npos
    if (pos != string::npos) {
        string suffix = filename.substr(pos);
        cout << suffix << endl;
    }
    return 0;
}

💡 核心要点:

  • 用法:find(目标,起始位置),支持字符、string、C 风格字符串三种查找目标。
  • 判断:用 != npos 判断是否找到。
  • 场景:字符串匹配、分割、替换(比如找到子串位置后用 substr 截取)。
2. rfind()

rfind() 的核心是:从指定的'结束位置'开始,从右向左查找第一个匹配的字符 / 子串(即原字符串中最后一个出现的匹配项),找到返回其起始下标,没找到返回 std::string::npos。简单说:find() 找'第一个',rfind() 找'最后一个'。

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, C++! C++ is fun.";
    
    // 场景 1:默认 pos=npos(查找整个字符串,找最后一个匹配)
    size_t pos1 = str.rfind("C++");
    if (pos1 != std::string::npos) {
        std::cout << "场景 1:最后一个\"C++\"在位置" << pos1 << std::endl; // 输出:12
    }

    // 场景 2:指定 pos(只在 [0, pos] 范围内找最后一个)
    size_t pos2 = str.rfind("C++", 10);
    if (pos2 != std::string::npos) {
        std::cout << "场景 2:[0,10] 内最后一个\"C++\"在位置" << pos2 << std::endl; // 输出:7
    }

    // 场景 3:查找不存在的内容(返回 npos)
    size_t pos4 = str.rfind("Java");
    if (pos4 == std::string::npos) {
        std::cout << "场景 4:未找到\"Java\"" << std::endl;
    }
    return 0;
}

💡 核心要点:

  • 差异:和 find() 比,查找方向相反、pos 参数是'结束范围'而非'起始位置'。
  • 场景:找最后一个分隔符(小数点、斜杠、逗号等)、提取后缀 / 文件名。
3. find_first_of()

find_first_of() 的核心是:从指定起始位置开始,在原字符串中找第一个属于'目标字符集合'的字符,返回其下标;没找到则返回 npos。

简单对比理解:find("abc") 找完整的子串"abc",必须连续 3 个字符完全匹配;find_first_of("abc") 找第一个是 a/b/c 中任意一个的字符,只要匹配其中一个就停止。

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello123World456!";
    
    // 场景 1:找第一个数字字符(字符集合是"0123456789")
    size_t pos1 = str.find_first_of("0123456789");
    if (pos1 != std::string::npos) {
        std::cout << "场景 1:第一个数字在位置" << pos1 << ",字符是" << str[pos1] << std::endl; // 输出:5,字符 1
    }

    // 场景 2:找第一个标点/特殊字符(集合是"!@#$%")
    size_t pos2 = str.find_first_of("!@#$%");
    if (pos2 != std::string::npos) {
        std::cout << "场景 2:第一个特殊字符在位置" << pos2 << ",字符是" << str[pos2] << std::endl; // 输出:14,字符!
    }

    // 场景 3:指定起始位置查找(从 pos=6 开始找数字)
    size_t pos3 = str.find_first_of("0123456789", 6);
    if (pos3 != std::string::npos) {
        std::cout << "场景 3:从 6 开始第一个数字在位置" << pos3 << ",字符是" << str[pos3] << std::endl; // 输出:6,字符 2
    }
    return 0;
}

💡 核心要点:

  • 区别:find 匹配完整子串,find_first_of 匹配字符集合中的任意字符。
  • 场景:找第一个数字 / 字母 / 特殊符号等'特征字符'。
4. find_last_of()

find_last_of() 的核心是:从指定的'结束位置'开始,从右向左查找第一个属于'目标字符集合'的字符(即原字符串中最后一个匹配该集合的字符),找到返回其下标,没找到返回 std::string::npos。

简单对比记忆:find_first_of() 从左找「第一个」属于字符集合的字符;find_last_of() 从右找「最后一个」属于字符集合的字符;rfind() 从右找「最后一个」完整子串(需连续匹配)。

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello123World456!";
    
    // 场景 1:默认 pos=npos(找整个字符串中最后一个数字)
    size_t pos1 = str.find_last_of("0123456789");
    if (pos1 != std::string::npos) {
        std::cout << "场景 1:最后一个数字在位置" << pos1 << ",字符是" << str[pos1] << std::endl; // 输出:13,字符 6
    }

    // 场景 2:指定 pos(只在 [0, 10] 范围内找最后一个数字)
    size_t pos2 = str.find_last_of("0123456789", 10);
    if (pos2 != std::string::npos) {
        std::cout << "场景 2:[0,10] 内最后一个数字在位置" << pos2 << ",字符是" << str[pos2] << std::endl; // 输出:7,字符 3
    }

    // 场景 3:找最后一个字母(字符集合是大小写字母)
    size_t pos3 = str.find_last_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
    if (pos3 != std::string::npos) {
        std::cout << "场景 3:最后一个字母在位置" << pos3 << ",字符是" << str[pos3] << std::endl; // 输出:10,字符 d
    }
    return 0;
}

💡 核心要点:

  • 区别:和 rfind() 比,它匹配'单个字符(集合)',而非'完整子串'。
  • 场景:找最后一个数字 / 分隔符 / 字母等'特征字符'(如提取文件名、最后一个分隔项)。
5. find_first_not_of()

find_first_not_of() 的核心是:从指定起始位置开始,在原字符串中找第一个「不属于」目标字符集合的字符,找到返回其下标,没找到返回 std::string::npos。

简单对比记忆:find_first_of() 找「第一个属于」字符集合的字符;find_first_not_of() 找「第一个不属于」字符集合的字符;比如字符集合是"0123456789",前者找第一个数字,后者找第一个非数字。

#include <iostream>
#include <string>

int main() {
    // 场景 1:找第一个非数字字符(验证是否是纯数字字符串)
    std::string num_str = "12345a6789";
    size_t pos1 = num_str.find_first_not_of("0123456789");
    if (pos1 != std::string::npos) {
        std::cout << "场景 1:第一个非数字在位置" << pos1 << ",字符是" << num_str[pos1] << std::endl; // 输出:5,字符 a
    } else {
        std::cout << "场景 1:字符串全是数字" << std::endl;
    }

    // 场景 2:找第一个非字母字符(过滤字母前的特殊符号)
    std::string str = "###HelloWorld123!";
    size_t pos2 = str.find_first_not_of("!@#$%^&*()"); // 字符集合是常见特殊符号
    if (pos2 != std::string::npos) {
        std::cout << "场景 2:第一个非特殊符号在位置" << pos2 << ",字符是" << str[pos2] << std::endl; // 输出:3,字符 H
        // 截取从第一个非特殊符号开始的字符串(得到"HelloWorld123!")
        std::string clean_str = str.substr(pos2);
        std::cout << " 清洗后字符串:" << clean_str << std::endl;
    }

    // 场景 3:找第一个不是空格的字符(比如找第一个不是空格的字符)
    std::string space_str = " test string";
    size_t pos3 = space_str.find_first_not_of(" ");
    if (pos3 != std::string::npos) {
        std::cout << "场景 3:第一个非空格字符在位置" << pos3 << ",字符是" << space_str[pos3] << std::endl; // 输出:3,字符 t
    }
    return 0;
}

💡 核心要点:

  • 区别:和 find_first_of() 是'反向'逻辑(一个找'不属于',一个找'属于')。
  • 场景:字符串校验(纯数字 / 纯字母)、开头字符清洗(去空格 / 特殊符号)、非法字符检测。
6. find_last_not_of()

find_last_not_of() 的核心是:从指定的'结束位置'开始,从右向左查找第一个「不属于」目标字符集合的字符(即原字符串中最后一个不符合该集合的字符),找到返回其下标,没找到返回 std::string::npos。

#include <iostream>
#include <string>

int main() {
    // 场景 1:找最后一个非数字字符(验证字符串末尾是否是数字)
    std::string num_str = "12345a6789";
    size_t pos1 = num_str.find_last_not_of("0123456789");
    if (pos1 != std::string::npos) {
        std::cout << "场景 1:最后一个非数字在位置" << pos1 << ",字符是" << num_str[pos1] << std::endl; // 输出:5,字符 a
    } else {
        std::cout << "场景 1:字符串全是数字" << std::endl;
    }

    // 场景 2:找最后一个非字母字符(提取字母部分的结尾)
    std::string str = "HelloWorld123!";
    size_t pos2 = str.find_last_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
    if (pos2 != std::string::npos) {
        std::cout << "场景 2:最后一个非字母在位置" << pos2 << ",字符是" << str[pos2] << std::endl; // 输出:10,字符 1
        // 截取从开头到最后一个字母的字符串(得到"HelloWorld")
        std::string alpha_part = str.substr(0, pos2);
        std::cout << " 纯字母部分:" << alpha_part << std::endl;
    }

    // 场景 3:找最后一个不是空格的字符(去除末尾空格)
    std::string space_str = "test string ";
    size_t pos3 = space_str.find_last_not_of(" ");
    if (pos3 != std::string::npos) {
        std::cout << "场景 3:最后一个非空格字符在位置" << pos3 << ",字符是" << space_str[pos3] << std::endl; // 输出:10,字符 g
        // 去除末尾空格
        std::string trim_str = space_str.substr(0, pos3 + 1);
        std::cout << " 去末尾空格后:" << trim_str << "(长度:" << trim_str.size() << ")" << std::endl;
    }
    return 0;
}

💡 核心要点:

  • 区别:和 find_first_not_of() 是'反向'逻辑(一个找最后一个不符合,一个找第一个不符合)。
  • 场景:去除末尾空格 / 特殊符号、校验字符串末尾字符类型、提取尾部有效内容。

substr()

substr() 的核心是:从原 std::string 中截取指定范围的字符,返回一个全新的 std::string 对象。它完全围绕 C++ 的 std::string 对象操作,不需要手动处理字符数组、不需要补 \0,是提取子串的'首选工具'。

我们可以简单理解为取后缀:

// substr -- 取后缀
#include <iostream>
#include <string>
using namespace std;

int main() {
    string filename("Test.cpp");
    FILE* fout = fopen(filename.c_str(), "r");
    if (fout) {
        cout << "打开文件成功" << endl;
        fclose(fout);
        // 从 pos 位置开始取 len 个字符
        string suffix = filename.substr(4, 4); // 相当于从第四个位置 (从 0 开始计算的) 开始取四个字符
        // 如果给出的数字太大就是有多少取多少,所以第二个参数可以不给,默认直接取到结尾
        cout << suffix << endl;
    }
    return 0;
}

⚠️ 补充:npos 是 std::string 的静态常量,代表'最大无符号整数',可以理解为'直到末尾'。

💡 核心要点:

  • 用法:substr(pos)(截到末尾)、substr(pos, count)(精准截取)。
  • 避坑:pos 不能越界、不能传负数、返回的是独立新对象。
  • 原则:日常提取子串优先用 substr(),仅需写入裸 char 数组时才用 copy()。

string 类中的一些全局函数

文章配图

这里有些之前的内容为大家解释过了,但我想要系统性为大家再解释一遍,这样也方便大家后续学习,不需要翻之前的博客减少负担。

operator+

operator+ 是 C++ 对 + 运算符的重载,专门用于字符串拼接,支持以下组合(覆盖所有常见场景):

  • std::string + std::string
  • std::string + 单个字符(char)
  • std::string + C 风格字符串(const char*)
  • C 风格字符串 + std::string
  • 单个字符 + std::string

核心特点:拼接后返回新字符串,原字符串不会被修改(因为是全局函数,操作的是值传递的副本)。

#include <iostream>
#include <string>
using namespace std;

int main() {
    string str1 = "Hello";
    string str2 = "World";
    const char* c_str = " C++";
    char ch = '!';

    // 场景 1:string + string
    string res1 = str1 + str2;
    cout << "场景 1:" << res1 << endl; // 输出:HelloWorld

    // 场景 2:string + C 风格字符串
    string res2 = str1 + c_str;
    cout << "场景 2:" << res2 << endl; // 输出:Hello C++

    // 场景 3:C 风格字符串 + string
    string res3 = "Hi " + str1;
    cout << "场景 3:" << res3 << endl; // 输出:Hi Hello

    // 场景 4:string + 单个字符
    string res4 = str1 + ch;
    cout << "场景 4:" << res4 << endl; // 输出:Hello!

    // 场景 5:单个字符 + string
    string res5 = ch + str2;
    cout << "场景 5:" << res5 << endl; // 输出:!World

    // 场景 6:连续拼接(结合多个重载)
    string res6 = str1 + " " + str2 + ch;
    cout << "场景 6:" << res6 << endl; // 输出:Hello World!
    return 0;
}

💡 核心要点:

  • 作用:重载 + 运算符,实现 std::string 与字符串 / 字符的拼接,返回新字符串。
  • 避坑:不能直接拼两个 C 风格字符串、频繁拼接优先用 append()。
  • 场景:一次性拼接 2~3 个字符串 / 字符(比如拼接提示语、路径)。

getline()

std::getline() 的核心是:从输入流(cin / 文件流)中读取字符,直到遇到指定的终止符(默认是换行符 \n)为止,将读取的内容存入 std::string 对象(不包含终止符本身)。

核心特点:支持读取带空格、制表符的完整一行;终止符可自定义(默认 \n);不会自动跳过开头的空白字符(和 operator>> 最大区别之一)。

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

int main() {
    // 场景 1:读取控制台整行(含空格,默认终止符 \n)
    std::string line1;
    std::cout << "请输入带空格的整行内容:";
    std::getline(std::cin, line1); // 输入:Hello World! 123 → 完整读取
    std::cout << "场景 1 读取结果:" << line1 << std::endl;

    // 场景 2:自定义终止符(以逗号分割)
    std::string line2;
    std::cout << "请输入用逗号分割的内容:";
    std::getline(std::cin, line2, ','); // 输入:apple,banana,orange → 读取到","前的"apple"
    std::cout << "场景 2 读取结果:" << line2 << std::endl;

    // 场景 3:从文件读取整行(逐行读取)
    // 假设 test.txt 内容:
    // Hello C++
    // Programming is fun
    std::ifstream file("test.txt");
    if (file.is_open()) {
        std::string file_line;
        std::cout << "\n场景 3:读取文件整行:" << std::endl;
        while (std::getline(file, file_line)) { // 循环读取直到文件末尾
            std::cout << file_line << std::endl;
        }
        file.close();
    }
    return 0;
}
getline () vs operator>> 核心对比
特性std::getline()operator>>(流提取)
终止符默认 \n(可自定义)任意空白字符(空格 / 制表 / 换行)
能否读取带空格内容能(整行)不能(仅无空格单词)
是否跳过开头空白否(默认读取所有开头空白)是(自动跳过开头空白)
典型场景读取整行文本(如地址、描述)读取无空格单词(如用户名、数值)
配合使用注意需用 cin.ignore() 跳过残留换行无此问题

💡 核心要点:

  • 作用:读取输入流的整行内容(含空格),默认以 \n 终止,可自定义终止符。
  • 避坑:和 cin >> 配合时,必须用 cin.ignore() 跳过残留的换行符。
  • 对比:getline() 读'整行',operator>> 读'单词',两者互补。
  • 场景:读取带空格的文本(如地址、描述、整行配置)、逐行读取文件。

简单说,getline() 是处理'带空格文本输入'的核心工具,只要需要读取整行内容,优先用它。可以简单理解,cin 是输入那些完整的比如 helloworld,但是如果要输入 hello world 就要使用 getline。

注:operator>> 和 operator<< 分别是流插入和流提取,是运算符的重载,而 swap 比较复杂,目前大家就知道他是交换函数就好,后续内容再为大家详细解释。

目录

  1. string 类中的一些成员函数
  2. c_str()
  3. data()
  4. get_allocator()
  5. copy()
  6. find 系列(重点)
  7. 1. find()
  8. 2. rfind()
  9. 3. findfirstof()
  10. 4. findlastof()
  11. 5. findfirstnot_of()
  12. 6. findlastnot_of()
  13. substr()
  14. string 类中的一些全局函数
  15. operator+
  16. getline()
  17. getline () vs operator>> 核心对比
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 国产 AI 编程助手全景:谁最像 Claude Code?差异与成本解析
  • 无人机视觉任务常用数据集汇总:检测与分割资源整理
  • 免费 Trae 编辑器体验:i18n 任务排队与模型调度机制分析
  • Rspack:基于 Rust 的高性能 Web 构建工具详解
  • C++ 红黑树深度解析:原理、旋转与完整实现
  • 基于 FPGA 的高速串行通信模块设计与验证
  • 鸿蒙金融理财全栈项目:运维监控、性能优化与安全加固
  • VR 与 AR 技术全景:从原理架构到未来趋势
  • JavaWeb 基础:动静 Web、URL 结构与 HTTP 协议
  • 数据结构:哈希表原理与冲突解决
  • Open WebUI 下载模型文件的默认存储位置
  • OpenCode 实战:用终端打造项目级 AI 工程师
  • 软件测试引入人工智能:核心场景、工具与落地实践
  • 双指针算法实战:快乐数与盛水最多的容器
  • Vivado AXI4-Stream Data FIFO 核配置与测试详解
  • AI 时代如何脱颖而出:商业认知与实战策略
  • 数据结构实战:双向链表原理与 C 语言实现
  • Flutter 跨平台开发:利用 objectid 构建离线分布式高可用 ID 引擎
  • Linux 信号捕捉原理与实现
  • 无人机视角山区泥石流和滑坡图像识别数据集

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online