说我有字符串:
char* foo = " blah blee bleck ";
现在说我想阅读并丢掉前两个词:
int bar = 0;
sscanf(foo, "%*s%n", &bar);
foo += bar;
if(bar > 0) sscanf(foo, "%*s%n, &bar);
我的问题是如何判断第二个sscanf
是否有任何内容?
我是否需要在每次读取之间输出0 bar
以确定是否实际读取了字符串,还是有更好的方法?
修改
检查sscanf
返回值无效,因为%* s和%n不会增加sscanf
的返回值:
printf("%d ", sscanf(foo, "%*s%n", &bar));
printf("%d ", bar);
printf("%d ", sscanf(foo + bar, "%*s%n", &bar));
printf("%d\n", bar);
将输出:
0 6 0 6
答案 0 :(得分:2)
检查sscanf调用的返回值,因为文档离子声明将返回一个整数值。
int sscanf( const char *buffer, const char *format, ... ); (C99)
我在我的机器上试了一小段代码,类似于你的查询,实际上sscanf为不成功的操作返回负值。
测试代码:
#include <stdio.h>
void main(void)
{
char* foo = " blah bleee bleckk ";
//char* foo = " blah";
int bar = 0;
int ret = -10;
printf("#m1 foo:%s\n",foo);
printf("#m1 bar:%d\n",bar);
printf("#m1 ret:%d\n\n",ret);
ret = sscanf(foo, "%*s%n", &bar);
foo += bar;
printf("#m2 foo:%s\n",foo);
printf("#m2 bar:%d\n",bar);
printf("#m2 ret:%d\n\n",ret);
if(bar > 0)
{
ret = -10;
ret = sscanf(foo, "%*s%n", &bar);
foo += bar;
}
printf("#m3 foo:%s\n",foo);
printf("#m3 bar:%d\n",bar);
printf("#m3 ret:%d\n",ret);
}
测试两种情况的输出:
./a.out
#m1 foo: blah bleee bleckk
#m1 bar:0
#m1 ret:-10
#m2 foo: bleee bleckk
#m2 bar:6
#m2 ret:0
#m3 foo: bleckk
#m3 bar:7
#m3 ret:0
./a.out
#m1 foo: blah
#m1 bar:0
#m1 ret:-10
#m2 foo:
#m2 bar:6
#m2 ret:0
#m3 foo:oo:%s
#m3 bar:6
#m3 ret:-1
问题是对于失败的sscanf调用,条形值未设置为零。
答案 1 :(得分:1)
如果忽略空格,正确的方法是在sscanf()返回值中测试EOF。 EOF表示%* s没有读取任何内容。如果你没有忽略空格,解决方案是微不足道的:如果在fscanf之前* foo!= 0,那么sscanf会读取一些内容。
答案 2 :(得分:1)
...阅读并丢掉前两个词:
const char* foo = " blah blee bleck ";
int bar = 0;
sscanf(foo, "%*s%*s% %n", &bar);
if (bar) {
printf("Success: string with first two words thrown away:'%s'\n", &foo[bar]);
}
上面在"%n"
之前添加了一个空格,以便在&#34; blee&#34;之后扔掉空格。
判断第二个sscanf是否读了什么?我需要0吗?
是的,重置bar = 0;
是一种简单的方法。除非前面的"%n"
扫描了一些非空格,否则"%*s"
不会被采取行动。
char* foo = " blah blee bleck ";
int bar = 0;
sscanf(foo, "%*s%n", &bar);
foo += bar;
if(bar > 0) {
puts("first sscanf read something.");
bar = 0;
sscanf(foo, "%*s%n", &bar);
if (bar) puts("second sscanf read something.");
}
答案 3 :(得分:0)
更好的方法可能是使用一些适当的标记化代码,而不是构建在sscanf()
上。我可能会写这样的东西:
const char * skip_word(const char *s)
{
while(isspace(*s))
++s;
while(*s && !isspace(*s))
++s;
return s;
}
这可用于跳过前导空格后跟一个单词,其中一个单词被非常宽松地定义为&#34;非空白字符&#34;。然后你可以通过调用上面的两次来提取第三个单词,当然检查中间返回值是否敏感。这样的事情。
但是,是的,当然,您必须清除bar
以获得新的解释。
规范似乎有点混淆了%n
是否包含在返回值中,仅此一点告诉我它不是最好的方法。
答案 4 :(得分:-1)
来自sscanf()
文档:
返回值
这些函数返回成功匹配的输入项数 分配,可以少于提供,或者甚至为零 早期匹配失败。
因此,如果sscanf()
没有返回您预期的匹配数,那么它可能无法读取您想要的内容。