You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C语言中使用pcre2.h库分割字符串(采用GPT-2分词器正则表达式)

如何在C语言中使用pcre2.h库分割字符串(采用GPT-2分词器正则表达式)

嘿,我来帮你搞定用PCRE2结合GPT-2分词正则分割字符串的事儿!你的代码已经有了开头,我来帮你补全并解释每一步该怎么做。

首先,先明确GPT-2的分词正则完整模式,你之前写的pattern没写完,完整的应该是(注意C字符串里的转义字符要多加一个反斜杠):

const char* pattern = "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+";

接下来是完整的可运行代码,我会在代码里加上注释,之后再逐点解释:

#define PCRE2_CODE_UNIT_WIDTH 8
#define PCRE2_STATIC
#include "pcre2.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    pcre2_code* re;
    PCRE2_SIZE erroffset;
    int errcode;
    PCRE2_UCHAR8 error_buffer[128];

    // GPT-2分词完整正则表达式
    const char* pattern = "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+";
    PCRE2_UCHAR8* subject = (PCRE2_UCHAR8*)"Hello, world! I'm using GPT-2 tokenizer in C with PCRE2.";

    // 编译正则表达式
    re = pcre2_compile(
        (PCRE2_UCHAR8*)pattern,
        PCRE2_ZERO_TERMINATED,
        0,  // 选项:默认即可,无需特殊设置
        &errcode,
        &erroffset,
        NULL);  // 编译上下文:用默认的NULL即可

    if (re == NULL) {
        // 编译失败时打印错误信息
        pcre2_get_error_message(errcode, error_buffer, sizeof(error_buffer));
        printf("正则编译失败,错误位置:%zu,错误信息:%s\n", erroffset, error_buffer);
        return 1;
    }

    // 创建匹配上下文
    pcre2_match_context* match_ctx = pcre2_match_context_create(NULL);
    if (match_ctx == NULL) {
        printf("创建匹配上下文失败\n");
        pcre2_code_free(re);
        return 1;
    }

    // 分配ovector:每个匹配需要2个元素存起止位置,PCRE2要求至少3个元素
    PCRE2_SIZE ovector[3];
    PCRE2_SIZE subject_length = pcre2_get_string_length(subject);
    PCRE2_SIZE start_offset = 0;
    int rc;

    printf("分词结果:\n");
    // 循环匹配,直到遍历完整个字符串
    while ((rc = pcre2_match(
        re,
        subject,
        subject_length,
        start_offset,
        0,  // 匹配选项:默认
        ovector,
        sizeof(ovector)/sizeof(ovector[0]),
        match_ctx)) >= 0) {

        // 提取当前匹配的token起止位置
        PCRE2_SIZE start = ovector[0];
        PCRE2_SIZE end = ovector[1];
        PCRE2_SIZE token_length = end - start;

        // 打印当前token
        printf("- ");
        fwrite(subject + start, 1, token_length, stdout);
        printf("\n");

        // 移动起始位置到当前匹配的末尾,继续下一次匹配
        start_offset = end;

        // 到达字符串末尾就退出循环
        if (start_offset >= subject_length) {
            break;
        }
    }

    // 处理匹配结束的情况
    if (rc == PCRE2_ERROR_NOMATCH) {
        printf("已完成所有分词\n");
    } else {
        pcre2_get_error_message(rc, error_buffer, sizeof(error_buffer));
        printf("匹配出错:%s\n", error_buffer);
    }

    // 释放所有资源,避免内存泄漏
    pcre2_match_context_free(match_ctx);
    pcre2_code_free(re);

    return 0;
}

关键步骤说明

  • 正则编译:pcre2_compile把正则字符串转换成PCRE2可处理的二进制结构,编译失败一定要检查错误信息,大概率是正则语法写错了。
  • 匹配上下文:用来设置匹配的额外参数,这里用默认配置就行,不用额外调整。
  • ovector数组:存储每个匹配的起始和结束偏移量,PCRE2要求数组长度至少是3,即使你不需要捕获分组。
  • 循环匹配:每次匹配成功后提取token,然后把起始位置移到当前匹配的末尾,直到遍历完整个字符串。
  • 资源释放:PCRE2的动态资源要手动释放,比如编译后的正则代码、匹配上下文,不然会有内存泄漏。

编译注意事项

编译的时候要链接PCRE2库,比如用gcc的话,命令是:

gcc your_code.c -o tokenizer -lpcre2-8

-lpcre2-8对应我们设置的PCRE2_CODE_UNIT_WIDTH 8,也就是UTF-8编码,能正常处理中文等Unicode字符。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:30:31