我有一个SPARQL查询,例如“select?Y?Z where ......”。我想要做的就是提取变量“?Y”和“?Z”。我写了以下循环:
char *p = "select ?Y ?Z where condition";
char *array[2];
p += strlen("select"); /* advancing the pointer */
for(int i = 0; i < 2; i++)
{
sscanf(p, "%m[?a-zA-Z] %[^\n]", array[i], p); /* 'm' tells sscanf to perform dynamic memory allocation */
printf("%s, ", array[i]);
printf("%s, ", p);
}
但是,我没有得到预期的行为。 array [1]包含garbage,array [2]包含null。
答案 0 :(得分:2)
基于http://man7.org/linux/man-pages/man3/scanf.3.html
例如,有
char *p;
n = scanf("%m[a-z]", &p);
我认为你应该改变你的
sscanf(p, "%m[?a-zA-Z] %[^\n]", array[i], p);
到
sscanf(p, "%m[?a-zA-Z] %[^\n]", &array[i], p);
了解%m
与char **
的搭配方式与char*
的搭配方式。
我建议您阅读THIS讨论。
我还注意到你的p
是char *
,你用字符串常量初始化它,然后尝试通过调用sscanf来覆盖它。
除此之外,您在同一个函数调用中读取和写入内存p
。我不是100%肯定在这里,但那可能是未定义的行为。
希望它有所帮助。
答案 1 :(得分:1)
你有几个问题。其中zubergu answer正确诊断出两个:{1}通过char *
需要char **
(见scanf()
),以及(2)试图覆盖你正在扫描的字符串,它首先是readonly,并且在任何情况下都会调用未定义的行为。
另一个原因是你没有从sscanf()
检查退货状态。你可能需要这样的东西:
char *p = "select ?Y ?Z where condition";
char *array[2];
p += strlen("select");
for (int i = 0; i < 2; i++)
{
int offset;
if (sscanf(p, " %m[?a-zA-Z]%n", &array[i], &offset) != 1)
...report error and break loop...
printf("%s, ", array[i]);
p += offset;
}
注意转换规范之前的空白以跳过前导空格。
如果您的sscanf()
版本支持该表示法,则此代码应该可以正常运行:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *p = "select ?Y ?Z where condition";
char *array[2] = { 0, 0 };
int i;
int j;
p += strlen("select");
for (i = 0; i < 2; i++)
{
int offset;
printf("p = <<%s>>\n", p);
if (sscanf(p, " %m[?a-zA-Z]%n", &array[i], &offset) != 1)
break;
printf("%d: <<%s>> (offset = %d)\n", i, array[i], offset);
p += offset;
}
printf("%d: all done\n", i);
for (j = 0; j < i; j++)
free(array[j]);
return 0;
}
Mac OS X 10.9不支持m
修饰符;老版本的Linux也没有(注意自己:必须更新可用的VM)。在Ubuntu 12.04衍生产品上测试时,我得到了输出:
p = << ?Y ?Z where condition>>
0: <<?Y>> (offset = 3)
p = << ?Z where condition>>
1: <<?Z>> (offset = 3)
2: all done