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
相关产品推荐
相关产品推荐

