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

C语言从固定格式文件提取可变长度子串的技术问题

问题:提取行中以"Name: "开头的可变长度子串(含空格)

从文件中读取到如下格式的行:

Name:   variable_length_string

需要提取子串variable_length_string,该子串可能包含空格(比如variable length string),且以\n结尾,行始终以Name: 开头。

初始实现代码:

char* getProcStatus(const char* path) {
    printf("path: %s", path);
    char* chrptr_ProcessStatus = NULL;
    FILE* fd_status = fopen (path, "rt");
    char line[300];
    char name[5];
 
    char* procName = NULL;
    if ( fd_status ) {
        if (fgets(line, sizeof(line), fd_status) != NULL) {
            sscanf(line, "%s%s", name, procName);
            if (procName != NULL) {
                printf("%s", procName);
                fclose(fd_status);
                return procName;
            }
        }
    }

    return procName;
}

遇到的问题:

  • 最初if (procName != NULL)分支从未执行,发现是未给procName分配内存,添加procName = malloc(200);后修复。
  • 仍无法提取含空格的完整子串,希望了解sscanf是否支持类似正则表达式的匹配(比如[a-zA-Z\-\/]*$)。

解决方案

1. 直接定位前缀后提取内容(推荐)

因为行固定以Name: 开头,可先跳过前缀及后续空格,再提取到换行符前的所有内容,这种方式更直观且避免格式符的坑:

char* getProcStatus(const char* path) {
    printf("path: %s", path);
    FILE* fd_status = fopen(path, "rt");
    char line[300];
    char* procName = NULL;

    if (fd_status) {
        if (fgets(line, sizeof(line), fd_status) != NULL) {
            const char* prefix = "Name: ";
            size_t prefix_len = strlen(prefix);
            // 跳过前缀
            char* content_ptr = line + prefix_len;
            
            // 跳过前缀后的所有空格
            while (*content_ptr == ' ') {
                content_ptr++;
            }
            
            // 计算内容长度(到换行符为止)
            size_t content_len = strcspn(content_ptr, "\n");
            // 分配内存并复制内容
            procName = malloc(content_len + 1);
            if (procName) {
                strncpy(procName, content_ptr, content_len);
                procName[content_len] = '\0'; // 手动添加字符串结束符
                printf("%s", procName);
            }
        }
        // 无论读取是否成功,都要关闭文件
        fclose(fd_status);
    }

    return procName;
}

2. 用sscanf实现提取

sscanf支持%[^\n]格式符,用于匹配直到换行符的所有字符,结合跳过前缀的写法实现:

char* getProcStatus(const char* path) {
    printf("path: %s", path);
    FILE* fd_status = fopen(path, "rt");
    char line[300];
    char* procName = malloc(200); // 可根据实际需求调整内存大小

    if (fd_status && procName) {
        if (fgets(line, sizeof(line), fd_status) != NULL) {
            // %*s 跳过第一个字符串(即"Name:"),%[^\n]读取到换行前的所有内容
            sscanf(line, "%*s %[^\n]", procName);
            
            // 去掉内容开头的空格
            char* trim_ptr = procName;
            while (*trim_ptr == ' ') {
                trim_ptr++;
            }
            // 将内容移到字符串开头
            if (trim_ptr != procName) {
                memmove(procName, trim_ptr, strlen(trim_ptr) + 1);
            }
            
            printf("%s", procName);
        }
        fclose(fd_status);
    }

    return procName;
}

3. 关于sscanf的"类正则"支持

sscanf的格式符支持字符集匹配,比如%[a-zA-Z\-\/\ ]可以匹配字母、连字符、斜杠和空格,但不支持正则中的锚点(如$)或复杂逻辑。如果你的子串仅包含特定字符,可使用对应字符集;如果要匹配换行前的所有内容,%[^\n]是最直接的方案。

注意事项

  • 调用getProcStatus后,记得用free()释放返回的procName,避免内存泄漏。
  • fgets会把换行符读入line,所以用strcspn或%[^\n]可以自动排除换行符。
  • 建议根据实际内容长度动态分配内存(如第一种方案),避免固定大小内存不足或浪费。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:25:08