我有一个可能相当常见的问题,可能有一个我不知道的美丽黑客。如果有人能开导我,我将不胜感激!
我使用C的sscanf()函数来解析输入,格式是 “%d%d%d%s%d%s%d ...” 其中前两个%d是字符串的随机ID整数(无意义),第三个是要跟随的%d%s组合数的计数。
例如,“12 34 2 3是2否”可以是一个字符串,其中12和34随机是ID(对问题不重要),2指定'3 yes'和'2 no'之后的两个组合。前面的3是'yes'指定后面的字符串的长度,对于前面带有2的'no'也是如此。我们可以在下面使用可变数量的这些组合,我们希望用sscanf捕获它们。
有没有人知道用sscanf做任何事情?
非常感谢!
答案 0 :(得分:3)
只需在两次(或多次)传递中解析字符串。这使用%n
格式说明符来写入处理的字节数,因此我们知道在后续传递中的位置:
int a, b, n, pos;
const char *buf = "12 34 2 3 yes 2 no";
assert(sscanf(buf, "%d %d %d %n", &a, &b, &n, &pos) == 3);
for(int i=0; i<n; i++) {
int cur;
int x;
char y[20];
assert(sscanf(buf+pos, "%d %19s %n", &x, y, &cur) == 2);
printf("%d %s\n", x, y);
pos += cur;
}
输出
3 yes
2 no
答案 1 :(得分:1)
仅使用sscanf
没有方便的方法。在将格式字符串传递给sscanf
之前,您需要动态生成格式字符串。
您可能要考虑为此编写专门的解析例程,在循环中调用sscanf
,或者更优选地(因为您指定C ++标记)在循环中使用std::istringstream
。< / p>
答案 2 :(得分:0)
首先,ssprintf()用于生成字符串,而不是解析它。你应该使用sscanf。我不知道在一个sscanf()中完成它。但你可以在循环中做到:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int choice_id, count;
char choice[20],id_1[20],id_2[20], count_str[20], choice_id_str[20];
int index;
char *input = "12 34 2 3 yes 2 no";
sscanf(input, "%s %s %s", id_1, id_2, count_str);
input += strlen(id_1)+strlen(id_2)+strlen(count_str)+2;
count = atoi(count_str);
for(index = 0; index< count; ++index){
sscanf(input, " %s %s", choice_id_str, choice );
choice_id = atoi(choice_id_str);
// Process or store the record
printf("%d: %s\n",choice_id, choice);
input += strlen(choice_id_str) + strlen(choice) + 2;
}
return 0;
}
使用gcc(GCC)4.1.2编译,并使用Linux运行。输出是:
-bash-3.2$ ./a.out
3: yes
2: no
答案 3 :(得分:0)
初始“%d%d%d”标题后面的%d%s对的数量是否有最大值? 必须有,因为你把价值放在某个地方,也许是在 struct {int i; char s [j]; a [n]; 适当的j和n尺寸。
(顺便说一句,你的例子使用“%d%d%d%s%d%s%d ...”当描述表明它应该是“%d%d%d%d%s%d%s %d%s ...“,3位小数,后跟小数/字符串对)
如果有最大值,只需创建一个最大化模板并测试来自sscanf的返回码,它应指示成功匹配和分配的输入项的数量,是第3个值减去3个标题项。 如果与第3个int相比返回代码不正确,则报告格式错误的行。
我曾经做过类似这样的函数,所以a [n]自动离开堆栈,然后函数从堆中为sscanf-ed项分配了一个链表,并返回指向第一项的指针。