【问题标题】:Reading specific lines from a file with different datatypes in C [closed]从C中具有不同数据类型的文件中读取特定行[关闭]
【发布时间】:2017-11-29 22:07:20
【问题描述】:

我的代码存在严重问题。我正在通过以下方式保存一些数据:

void savetofile()
{
  fprintf(savefile, "%d\n", run); // here are 1 or 2 characters
  fprintf(savefile, "%d\n", gender); // 1 character
  fprintf(savefile, "%s\n", name); // here is string, max 20 characters
  fprintf(savefile, "%d\n", points1); // between 1 and 3 characters
  fprintf(savefile, "%d\n", points2); // between 1 and 3 characters
}

保存后如何阅读?我可以以某种方式具体说明:

fscanf(savefile, "%d", &gender);

要特别阅读第 2 行?

也许当我将数据保存到文件时:

void savetofile()
{
  fprintf(savefile, "%d ", run); // here are 1 or 2 characters
  fprintf(savefile, "%d ", gender); // 1 character
  fprintf(savefile, "%s ", name); // here is string, max 20 characters
  fprintf(savefile, "%d ", points1); // between 1 and 3 characters
  fprintf(savefile, "%d ", points2); // between 1 and 3 characters
}

会更容易阅读吗?

【问题讨论】:

  • 如果您在文件中打印了 5 行,您应该从该文件中读取这 5 行,使用与写入每一行时相同的格式。
  • 1) 使用第一个 void savetofile() 2) 发布您的输出示例。 3) 发布变量的定义。
  • gender 真的是int(或者您打算将其存储为int),还是char?考虑使用fgets() 从文件中读取输入行,并使用sscanf() 解析每一行。
  • 提示:写名字的时候,记得有些名字里面有空格。因此,请使用fprintf(savefile, "<%s>\n", name); 之类的标记来编写。然后阅读更容易检测到格式错误的数据。
  • 您的主要问题是指定文件格式。完成后,对解析器进行编码是常见的做法,您会发现很多关于解析的书籍(和编译:大多数编译器书籍都在第一部分研究解析技术)

标签: c file scanf ansi-c


【解决方案1】:

许多方法可以解决这个问题 - 每种方法都有优点和缺点。

用“标签”的单行,文件中的标记来指示数据 ID 怎么样?

void savetofile(int run, int gender, char *name, int points1, int points2) {
  fprintf(savefile, "r:%d g:%d n:\"%s\" p1:%d p2:%d\n", 
    run, gender, name, points1, points2);
}

// return 1: success, EOF:no more 0:problem data
int readfile(int &run, int &gender, char *name, int *points1, int *points2) {
  char buf[100];  // Size: 2x longest expected line
  if (fgets(buf, sizeof buf, savefile) == NULL) return EOF;
  if (sscanf(buf, "r:%2d g:%1d n:\"%19[^\"]\" p1:%3d p2:%3d", 
    &run, &gender, name, &points1, &points2) != 5) return 0;
  return 1;
}

其他各种可能的改进,尤其是额外的错误检查,但以上是为了实现一些想法。

【讨论】:

    【解决方案2】:

    fscanf 不知道也不关心 lines 因为行尾标记(例如换行符)被认为是一些空格字符。特别是,fscanf 格式控制字符串中的空格、制表符、换行符起着相同的作用(跳过类似空格的字符),并且在作为输入出现时同样由fscanf 处理。

    如果您关心特定 行,则应逐行阅读输入文件。使用getlinehere(或fgets)来读取行。换句话说,如果您关心行,则需要进行顺序读取。

    您可以解析您的文件两次,并记住(例如,在一些动态分配的数组中)第一次传递中行的所有偏移量(在第二次传递中使用ftell 和稍后的fseek;直接访问是唯一可能的到某个字节offset,而不是某个行号)。

    一旦您阅读了某行,您就可以使用常见的parsing 技术(尤其是sscanf%n,或者您的recursive descent parser)来解析它。

    请务必在纸上指定您的文本file format的语法,例如在EBNF 符号中。换行符的作用由您选择(您可以将它们视为空格,通过使用lexing 并在整个文件上解析技术,或者您可以通过读取每一行并解析该行来逐行处理)。

    顺便说一句,您的用例宁愿建议一些其他方法。例如。使用数据库(可能是 Sqlite),使用索引文件 à la gdbm,以 JSON、XML 或 YAML 等文本格式对数据进行编码(您会找到许多库)。

    请注意,大多数关于compilers(尤其是Dragon Book)的书籍都以对各种解析技术的解释开始。你应该阅读那部分。

    【讨论】:

    • 不,我必须使用 .txt 文件,这是本项目的重点之一。
    • 读取每一行(带getline
    • 顺便说一句,JSON 是一种可读性很强的文本格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多