我正在解析一个遵循可预测模式的字符串:
例如:
s5:stuff
我可以很容易地看到如何用PCRE等来解析它,但为了速度,我宁愿坚持使用普通的字符串操作。
我知道我需要分两步完成,因为在知道其长度之前我无法分配目标字符串。我的问题是优雅地获得所述字符串的 start 的偏移量。一些代码:
unsigned start = 0;
char type = serialized[start++]; // get the type tag
int len = 0;
char* dest = NULL;
char format[20];
//...
switch (type) {
//...
case 's':
// Figure out the length of the target string...
sscanf(serialized + start, "%d", &len);
// <code type='graceful'>
// increment start by the STRING LENGTH of whatever %d was
// </code>
// Don't forget to skip over the colon...
++start;
// Build a format string which accounts for length...
sprintf(format, "%%%ds", len);
// Finally, grab the target string...
sscanf(serialized + start, format, string);
break;
//...
}
这段代码大致取自我所拥有的(由于手头的问题而无法完成),但它应该得到重点。也许我完全采取了错误的做法。 最优雅的方法是什么?解决方案可以是C或C ++(如果有足够的响应,我实际上希望看到竞争方法。)
答案 0 :(得分:8)
您可以使用%n
转换说明符,它不使用任何输入 - 而是需要int *
参数,并将输入中消耗的字符数写入其中:
int consumed;
sscanf(serialized + start, "%d%n", &len, &consumed);
start += consumed;
(但不要忘记检查sscanf()
返回&gt; 0!)
答案 1 :(得分:1)
使用%n
格式说明符将到目前为止读取的字符数写入整数参数。
答案 2 :(得分:1)
这是一个C ++解决方案,它可能更好,并且专门用于处理您的示例输入的硬编码,但不需要太多修改才能正常工作。
std::stringstream ss;
char type;
unsigned length;
char dummy;
std::string value;
ss << "s5:Helloxxxxxxxxxxx";
ss >> type;
ss >> length;
ss >> dummy;
ss.width(length);
ss >> value;
std::cout << value << std::endl;
我是C ++的菜鸟。
答案 3 :(得分:0)
你可能只是使用会忽略冒号的atoi。
e.g。 len = atoi(序列化+开始);
atoi唯一的一点是,如果它返回零,则可能意味着转换失败,或者长度真的为零。所以它并不总是最合适的功能。
答案 4 :(得分:0)
如果用空格替换你的冒号,scanf会停在它上面,你可以得到大小为malloc的大小,然后运行另一个scanf来得到其余的字符串。
int main (int argc, const char * argv[]) {
char foo[20];
char *test;
scanf("%s",foo); //"hello world"
printf("foo = %s\n", foo);//prints hello
//get size
test = malloc(sizeof(char)* 10);//replace 10 with your string size
scanf("%s", test);
printf("test = %s\n", test);//prints world
return 0;
}
`
答案 5 :(得分:0)
似乎格式过于规范......(使用可变长度字段指定可变长度字段的长度)。
如果您正在使用GCC,我建议
if (sscanf(serialized,"%c%d:%as",&type,&len,&dest)<3) return -1;
/* use type, dest; ignore len */
free(dest);
return 0;