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 %s", com, ¶graph_num, &line_num, extra)
== 4 && paragraph_num > 0 && line_num >= 0 && extra[0] == '*') {
strcpy(line, &(extra[1]));
if (add_line_after(doc, paragraph_num, line_num, line) == FAILURE) {
printf("add_line_after failedn");
}
return SUCCESS;
}
return FAILURE;
}
我想让sscanf
读取command
到extra
中剩下的所有内容,但它只取第一个单词。例如,如果我有:
- 命令:"add_line_after 1 0 *文档的第一行">
I want to see:
- com:"add_line_after"
- paragraph_num: 1
- line_num: 0
- extra: "文档的第一行">
但是我得到:
- com:"add_line_after"
- paragraph_num: 1
- line_num: 0
- 额外:"至上">
因为%s
在到达空格时停止。我如何阅读其余的行,同时仍然忽略'0'
和'*'
之间的任何空白?
作为参考,MAX_STR_SIZE
是80和command
是一个1025字符数组(虽然我不认为这很重要)。假设extra
足够大,可以容纳行其余部分。
sscanf
在这里确实是错误的工具。这是可以做到的,但可能不应该用你正在尝试的方式。幸运的是,您没有将com
传递给add_line_after
,这意味着没有必要确保com
是一个正确的以null结尾的字符串,这允许您避免所有不必要的字符串复制。(如果你要传递com
,你要么复制它,要么在command
中写一个空终止符。)您根本不希望或不需要使用sscanf
来移动数据。您可以使用它来解析数值。我不清楚是否要丢弃*
后面的任何空白,而此代码没有。如果您想这样做,删除空白是微不足道的,留给读者作为练习:
int
run_add_line_after(struct document *doc, const char *command)
{
int paragraph_num, line_num, n;
const char *line;
if( 2 == sscanf(command, "%*s %d %d %n", ¶graph_num, &line_num, &n)
&& paragraph_num > 0 && line_num >= 0 && command[n] == '*' )
{
line = command + n + 1;
if( add_line_after(doc, paragraph_num, line_num, line) == FAILURE) {
fprintf(stderr, "add_line_after failedn");
} else {
return SUCCESS;
}
}
return FAILURE;
}
这里的想法是简单地使用sscanf
来找出extra
数据在字符串中的位置,并解析整数值。这绝对是一个错误的工具(scanf
系列(几乎)总是错误的工具),这里只用于演示。
—edit—
但是,当然,这并不完全是您想要的。将一些功能移到add_line_after
中来处理换行符会简洁得多,但由于还需要删除换行符,因此有必要执行以下操作:
int
run_add_line_after(struct document *doc, char *command)
{
int paragraph_num, line_num, n;
char *line;
if( 2 == sscanf(command, "%*s %d %d %n", ¶graph_num, &line_num, &n)
&& paragraph_num > 0 && line_num >= 0 && command[n] == '*' )
{
line = command + n + 1;
line[strcspn(line, "n")] = ' ';
if( add_line_after(doc, paragraph_num, line_num, line) == FAILURE) {
fprintf(stderr, "add_line_after failedn");
} else {
return SUCCESS;
}
}
return FAILURE;
}
这并不理想。如果你修改API,这样你就可以避免复制数据和修改给定的字符串。
明白了。格式字符串应该是" %s %d %d %[^n]s"
。它将继续读取最后一个字符串变量,直到它按下回车键。