C语言如何使用sscanf读取命令剩余整行内容到字符串
问题原因
sscanf的%s格式符匹配规则是:先跳过前导空白,再读取连续的非空白字符,碰到任意空白字符(空格、制表符、换行等)就终止读取,所以只能拿到*后面的第一个单词,无法获取带空格的整段剩余内容。
解决方法
调整sscanf格式串即可满足需求,核心改动逻辑:
- 在读取
line_num的%d后加空格,自动跳过数字和*之间的任意数量空白,满足忽略间隔空白的要求 - 格式串中直接写入字面量
*,强制匹配星号,匹配不到则直接判定输入非法,省掉后续单独判断星号的步骤 - 把最后读取内容的
%s替换为%[^\n],该格式符会读取从当前位置开始直到换行(或字符串结尾)的所有字符,包括中间的空格、制表符,正好拿到*之后的全部剩余内容
修正后的代码如下:
int run_add_line_after(Document *doc, char *command) { int paragraph_num, line_num; char com[MAX_STR_SIZE + 1], extra[MAX_STR_SIZE + 2], line[MAX_STR_SIZE + 1]; if (sscanf(command, " %s %d %d *%[^\n]", com, ¶graph_num, &line_num, extra) == 4 && paragraph_num > 0 && line_num >= 0) { // *已经被格式串匹配消费,extra直接存储*后的内容,无需偏移1位 if (add_line_after(doc, paragraph_num, line_num, extra) == FAILURE) { printf("add_line_after failed\n"); } return SUCCESS; } return FAILURE; }
格式说明
- 格式串中的空白字符不是匹配单个空格,而是匹配0到任意多个连续空白(空格、制表符均算),因此数字和*之间不管间隔多少个空格都能正常跳过。
%[^\n]不会自动跳过前导空白,后面紧跟的空格会被完整读入extra,符合“仅忽略数字和之间空白,其余内容全保留”的要求。- 若
command是提前去除了结尾换行符的字符串,%[^\n]碰到字符串结束符\0会自动终止读取,不会出现越界问题。
更鲁棒的兼容写法(支持空行场景)
如果业务允许*后面为空(即插入空行),上述sscanf写法会因为%[^\n]匹配不到内容返回失败,这种场景推荐用手动偏移的方式处理,没有格式匹配的边界问题:
// 引入<ctype.h>可使用isspace函数,不想引入可自行替换为*p == ' ' || *p == '\t'判断 #include <ctype.h> int run_add_line_after(Document *doc, char *command) { int paragraph_num, line_num, offset; char com[MAX_STR_SIZE + 1], line[MAX_STR_SIZE + 1]; // 读完前三个字段后,用%n记录当前读取到的偏移位置 if (sscanf(command, " %s %d %d %n", com, ¶graph_num, &line_num, &offset) == 3 && paragraph_num > 0 && line_num >= 0) { char *p = command + offset; // 跳过数字后的所有空白 while (*p && isspace(*p)) p++; // 校验第一个非空白字符必须是* if (*p != '*') return FAILURE; p++; // 跳过*字符 // 直接拷贝*后的全部内容到line,无需extra数组中转 strcpy(line, p); if (add_line_after(doc, paragraph_num, line_num, line) == FAILURE) { printf("add_line_after failed\n"); } return SUCCESS; } return FAILURE; }
内容的提问来源于stack exchange,提问作者DemonPotato4411
相关产品推荐
相关产品推荐

