使用sscanf解析并动态分配长度不固定子串的C语言实现问题
解决方案
方案1:使用支持动态分配的sscanf格式符(POSIX环境适用)
POSIX.1-2008标准为scanf系列函数新增了m分配修饰符,遇到%s、%[、%c这类字符串格式符时,会自动计算匹配内容的长度,申请对应大小的内存并将地址写入传入的指针参数,只需要传入char**类型的参数即可。
修改后的代码示例:
#include <stdio.h> #include <stdlib.h> // 替换为你自己的read_line声明或对应头文件 char* read_line(); int main (){ char* line = read_line(); char operation[4]; char* first_number_buffer; char* second_number_buffer; // %s前加m修饰符,参数传指针的地址 sscanf(line, "%3s %ms %ms", operation, &first_number_buffer, &second_number_buffer); printf("操作:%s\n数字1:%s\n数字2:%s\n", operation, first_number_buffer, second_number_buffer); // 用完必须手动释放申请的内存 free(first_number_buffer); free(second_number_buffer); free(line); return 0; }
注意:
%3s是为了限制操作名的最大长度,避免输入过长溢出4字节的operation缓冲区,是安全编码的必要处理。
方案2:纯标准C可移植实现(手动拆分字符串)
如果需要兼容不支持%ms的编译环境(比如部分嵌入式场景、老版本Windows编译器),可以直接对已经读入的完整行做拆分,不需要依赖sscanf的分配能力:
- 遍历字符串找到两个空格的位置,确定操作名、两个数字串的起止偏移和长度
- 按长度为每个子串申请内存,拷贝对应内容即可
也可以用标准库的strtok函数快速实现拆分,示例代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> char* read_line(); int main (){ char* line = read_line(); char operation[4]; char* first_number_buffer; char* second_number_buffer; // 第一次拆分取操作名 char* token = strtok(line, " "); strncpy(operation, token, 3); operation[3] = '\0'; // 确保字符串合法结束 // 第二次拆分取第一个数字 token = strtok(NULL, " "); first_number_buffer = malloc(strlen(token) + 1); strcpy(first_number_buffer, token); // 第三次拆分取第二个数字 token = strtok(NULL, " "); second_number_buffer = malloc(strlen(token) + 1); strcpy(second_number_buffer, token); printf("操作:%s\n数字1:%s\n数字2:%s\n", operation, first_number_buffer, second_number_buffer); // 释放所有申请的内存 free(first_number_buffer); free(second_number_buffer); free(line); return 0; }
注意:
strtok会修改原字符串的内容,如果你后续还需要使用原始的line内容,可以先拷贝一份副本再做拆分。
内容的提问来源于stack exchange,提问作者nluizsoliveira
相关产品推荐
相关产品推荐

