如何仅使用fread()和vsscanf()

时间:2016-05-27 13:24:46

标签: c pointers stream scanf fread

我正在使用类似C的API的嵌入式平台上移植一些代码。原始代码使用fscanf()来读取和解析文件中的数据。不幸的是,在我的API中,我没有fscanf()等效项,因此在实际移植之前,我正在尝试使用fscanf()fread()获取vsscanf()的相同行为(我有)。我也相当于fseek()ftell()

编辑:请记住,对嵌入式文件系统的访问非常有限(fread - fseek - ftell - fgetc - 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-char字符串如下:

  

12 ba r 13 foo 5678901234567890123456789012345678 9

fscanf()将匹配int 12,字符串bar,指针将指向“bar”中的“r”,因此我可以再次调用它并读取{{ 1}}

另一方面,13 foo将指针放在50个元素序列中的最后一个字符之后,这是错误的:我仍然必须阅读fread()但是如果我再次调用13 foo指针位于第51位。

我必须使用wrapped_fscanf()回滚到第一场比赛的结尾,但我该怎么做?如何计算fseek()

的值

offset返回匹配的数量,而不是字符串的长度,我无法知道有多少空格字符分隔匹配的元素(还是我?

即。我得到了相同的输出({var,str,read} == {9,“xyz”,2})

vsscanf()

9 xyz

是否有一些我不知道的技巧,或者除了9 xyz fscanf() fread()和{{1 }}?

谢谢

2 个答案:

答案 0 :(得分:1)

假设您的vsscanf()实现支持它,您替换fscanf()可以在提供的格式末尾添加%n字段描述符。只要在vsscanf()到达该字段之前没有失败,它就会在相应的参数中存储到该点消耗的字符数。然后,您可以使用该结果来适当地重新定位流。这需要一些争吵,可能需要一些宏观帮助,但我认为可以让它起作用。

答案 1 :(得分:0)

您将需要一些中间缓冲代码,它将抓取数据块(使用fread),并扫描缓冲区中的模式。如果找到模式,则截断缓冲区,如果找不到模式,则追加更多数据。这实际上是fscanf将要做的事情。