我正在使用类似C的API的嵌入式平台上移植一些代码。原始代码使用fscanf()
从文件中读取和解析数据。不幸的是,在我的API上,我没有fscanf()
等价物,所以在实际移植之前,我试图使用fread()
和vsscanf()
(我确实有)获得fscanf()
的相同行为。我还有fseek()
和ftell()
的等价物。
EDIT:请记住,对嵌入式文件系统的访问非常有限(fread-fsek-ftell-fgets-fgets),因此我需要一个处理内存中字符串的解决方案,而不是以其他方式访问文件。
代码看起来像这样:
int main()
{
[...] /* variable declarations and definitions */
do
{
read = wrapped_fscanf(pFile, "%d %s", &val, str);
} while (read == 2);
fclose(pFile);
return 0;
}
int wrapped_fscanf(FILE *f, const char *template, ...)
{
va_list args;
va_start(args, template);
char tmpstr[50];
fread(tmpstr, sizeof(char), sizeof(tmpstr), f);
int ret = vsscanf(tmpstr, template, args);
long offset = /* ??? */
fseek(f, offset, SEEK_CUR);
va_end(args);
return ret;
}
问题是fscanf()
将指针移到匹配结束时文件流中的位置,而使用fread()
,我读取的数据量固定(在本例中为50字节),我应该找到将指针移回匹配字符串末尾的方法。
假设我从文件中读取的50个字符的字符串如下:
12 bar13 foo 5678901234567890123456789012345 6789
fscanf()
将与int12
匹配,字符串bar
和指针将直接指向"bar"中的"r"之后,因此我可以再次调用它并读取13 foo
另一方面,fread()
将指针放在50元素序列中的最后一个字符之后,这是错误的:我仍然必须读取13 foo
,但如果我再次调用wrapped_fscanf()
,指针就在第51个位置。
我必须使用fseek()
才能回到第一场比赛的最后,但我该怎么做呢?如何计算offset
的值?
vsscanf()
返回匹配的数量,而不是字符串的长度,我无法知道有多少空白字符分隔了匹配的元素(还是I?)
也就是说,我得到了与相同的输出({var,str,read}=={9,"xyz",2})
9 xyz
和
9 xyz
除了用fread()
、vsscanf()
、ftell()
和fseek()
包装fscanf()
之外,还有什么我不知道的技巧吗?
谢谢
假设vsscanf()
实现支持它,那么fscanf()
的替代品可以在所提供格式的末尾附加一个%n
字段描述符。只要在vsscanf()
到达该字段之前没有失败,它就会在相应的参数中存储到该点为止消耗的字符数。然后,您可以使用该结果来适当地重新定位流。这需要一些varargs的争论,可能还需要一些宏观援助,但我认为这是可行的。
您将需要一些中间缓冲代码,它将抓取数据块(使用fread),并扫描缓冲区以查找模式。如果找到了模式,则截断缓冲区;如果找不到模式,则追加更多数据。这实际上就是fscanf要做的。