将函数转换为从C中读取字符串而不是文件

时间:2010-03-15 21:43:43

标签: c scanf

我的任务是更新一个当前从磁盘读取配置文件并填充结构的函数:

static int LoadFromFile(FILE *Stream, ConfigStructure *cs)
{
  int tempInt;

   ...

  if ( fscanf( Stream, "Version: %d\n",&tempInt) != 1 )
  {
    printf("Unable to read version number\n");
    return 0;
  }
  cs->Version = tempInt;
   ...

}

允许我们绕过将配置写入磁盘并将其直接传递到内存中,大致相当于:

static int LoadFromString(char *Stream, ConfigStructure *cs)

有几点需要注意:

  • 当前的LoadFromFile函数非常密集和复杂,以向后兼容的方式读取几十个版本的配置文件,这使得整个逻辑的重复非常痛苦。
  • 生成配置文件的函数和读取它的函数源于旧系统的完全不同的部分,因此不共享任何数据结构,因此我无法直接传递它们。我可以写一个包装器,但同样,它需要以向后兼容的方式处理传入的任何结构。
  • 我很想将文件作为字符串传递(如上面的原型)并将所有fscanf转换为sscanf但是我必须处理递增指针(并可能处理缓冲区溢出错误) )手动。
  • 这必须保留在C中,因此没有像流这样的C ++功能可以帮助

我错过了更好的选择吗?有没有办法创建一个实际上只指向内存而不是磁盘上的位置的FILE *?任何指针,建议或其他帮助都非常感谢。

3 个答案:

答案 0 :(得分:3)

如果您无法传递结构并且必须将数据作为字符串传递,那么您应该能够调整函数以从字符串而不是文件中读取。如果函数与您描述的一样复杂,那么转换fscanf - > sscanf可能是最简单的方法。

这是使用上面的函数原型的想法。读入整个数据字符串(不处理任何数据字符串)并将其存储在本地缓冲区中。这样,代码可以随意访问数据,因为它可以使用文件并使缓冲区溢出更容易预测和避免。从malloc一个合理大小的缓冲区开始,将数据复制到其中,并根据需要realloc自己增加空间。获得整个数据缓冲区的本地副本后,扫描它并提取所需的任何数据。

请注意,如果'\0'字符是有效输入,这可能会变得棘手。在这种情况下,您必须添加额外的逻辑来测试这是输入字符串的结尾还是零字节(困难取决于数据缓冲区的特定格式)。

答案 1 :(得分:2)

由于您尝试将文件数据保留在内存中,因此您应该可以使用 shared memory 。 POSIX共享内存实际上是映射内存的变体。如有必要,可以使用 mmap() 将共享内存对象映射到进程地址空间。共享内存通常用作IPC机制,但您应该能够根据自己的情况使用它。

以下示例代码使用POSIX共享内存( shm_open() & shm_unlink() )与FILE *一起编写将文本写入共享内存对象,然后将其读回。

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>

#define MAX_LEN 1024

int main(int argc, char ** argv)
{
    int    fd;
    FILE * fp;
    char * buf[MAX_LEN];

    fd = shm_open("/test", O_CREAT | O_RDWR, 0600);

    ftruncate(fd, MAX_LEN);

    fp = fdopen(fd, "r+");

    fprintf(fp, "Hello_World!\n");

    rewind(fp);

    fscanf(fp, "%s", buf);

    fprintf(stdout, "%s\n", buf);

    fclose(fp);

    shm_unlink("/test");

    return 0;
}

注意:在Linux上使用gcc编译此示例时,我必须将-lrt传递给链接器。

答案 2 :(得分:1)

  • 使用mkstemp()创建临时文件。它需要char *作为参数,并将其用作文件名称的模板。但是,它将返回一个文件描述符。

  • 使用tmpfile()。它返回FILE *,但有一些security issues,而且你必须自己复制字符串。

  • 使用mmap()Beej's Guide寻求帮助)