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

C语言如何使用sscanf拆分含$标识的字符串并处理缺省情况

sscanf拆分含$标识字符串的实现方案

原有代码问题分析

原有格式化串存在两个核心缺陷:

  • %m[^$]为否定匹配集,要求$前至少存在1个非$字符才会匹配成功。当输入以$开头(如$HOME)时,第一步匹配直接失败,sscanf直接终止执行,后续所有参数都不会被赋值,最终拿到的是未初始化的野指针。
  • 末尾的%*m属于非法写法:m修饰符的作用是要求库函数动态申请内存存储匹配结果,必须传入对应的char**参数接收指针,搭配*抑制赋值属于未定义行为,无法正确获取后缀内容。

解决方案

我们可以通过匹配返回值判断+偏移量记录的方式兼容所有场景,代码实现如下:

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

void split_env_str(const char *input) {
    // 所有接收指针先初始化为NULL,不存在的分段默认就是NULL
    char *prefix = NULL, *env_name = NULL, *suffix = NULL;
    int match_offset = 0;
    int match_cnt;

    // 先尝试匹配有前缀的场景:[前缀]$[变量名]
    match_cnt = sscanf(input, "%m[^$]$%m[_a-zA-Z0-9]%n", &prefix, &env_name, &match_offset);
    // 匹配失败的话尝试匹配无前缀(开头就是$)的场景
    if (match_cnt < 2 && input[0] == '$') {
        match_cnt = sscanf(input + 1, "%m[_a-zA-Z0-9]%n", &env_name, &match_offset);
        match_offset += 1; // 补回开头$的长度偏移
    }

    // 提取剩余后缀内容
    if (match_cnt >= 1 && input[match_offset] != '\0') {
        suffix = strdup(input + match_offset);
    }

    // 此处为测试输出逻辑,实际使用可根据需求返回三个指针
    printf("前缀:%s\n", prefix ? prefix : "NULL");
    printf("变量名:%s\n", env_name ? env_name : "NULL");
    printf("后缀:%s\n", suffix ? suffix : "NULL");

    // 使用完后必须释放动态申请的内存
    free(prefix);
    free(env_name);
    free(suffix);
}

适配场景验证

上述代码可覆盖所有你提到的输入场景:

  • 输入something$HOME/something2:前缀为something,变量名为HOME,后缀为/something2
  • 输入$HOME:前缀为NULL,变量名为HOME,后缀为NULL
  • 输入$HOME/something:前缀为NULL,变量名为HOME,后缀为/something
  • 输入something$HOME:前缀为something,变量名为HOME,后缀为NULL

注意事项

  • 代码用到的m修饰符为POSIX标准扩展,如果需要兼容纯C标准平台,可以自行替换为固定大小缓冲区+长度限制的写法
  • 所有通过m修饰符和strdup申请的内存,使用完成后必须调用free释放,避免内存泄漏

内容的提问来源于stack exchange,提问作者user15890225

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 09:06:07