【问题标题】:Trying to search a random access file using a string尝试使用字符串搜索随机访问文件
【发布时间】:2019-03-27 20:48:35
【问题描述】:

我可以毫无问题地搜索随机访问文件,但问题是我不明白它实际上是如何工作的。

之前我使用方法搜索了一个随机访问文件

 FILE fpnt = fopen(FILE_NAME, "rb+");

 User tempUser = {"", "", 0, "", 0};
 printf("Enter the id number of the user to find\n");
 scanf("%d", idNum);
 fseek(fpnt, (idNum - )* sizeof(User), SEEK_SET);
 fread(&tempUser, sizeof(User), 1, fpnt) != EOF && found == 0;

我不明白当偏移量不一定与我假设的 ID 相同时,它如何总能找到正确的用户。但问题在于当我尝试使用整数以外的数据访问文件时。

例如,我试图通过字符串名称来查找用户。我使用的方法如下:

 typedef enum tUserLevel {
     MANAGER = 1,
     CLERK = 0,
     NOTFOUND = 9001
 }level;


 typedef struct tUser {
     char userName[20];
     char password[20];
     level priviledgeLevel;
 }User;

do {
    fseek(fpnt, offSet * sizeof(User), SEEK_SET);
    if (fread(&tempUser, sizeof(User), 1, fpnt) == EOF)
        endOfFile = EOF;        
    rewind(fpnt);
    offSet++;
} while (endOfFile!=EOF && !strcmp(username, tempUser.userName));

if (endOfFile==EOF&& strcmp(username, tempUser.userName)) {
    printf("The User was not found\n");
    return noUser;

    //return noUser;
}

所以应该发生的是文件将检查每个用户输入的用户名(即名为 username 的变量)并比较两者,如果两者都正确则停止。我不确定这实际上是如何循环的,或者偏移量是否会以我想要的方式影响文件中的指针。发生的事情是我总是得到 EOF,因此即使在一次阅读之后,这部分代码也总是运行。我有 4 个测试用户有没有更好的方法来按字符串搜索这些文件,以便我可以读取它们并在文件中编辑它们,或者这是最好的方法,我在某个地方搞砸了?

【问题讨论】:

  • fseekrewind 在这里毫无意义。代码返回到文件的开头(倒带),然后立即转身回到与刚才完全相同的位置(fseek)。这两个调用可以直接删除。
  • fread() 何时返回 EOF?
  • Zing,偏移量被初始化为零,是的,所以它会从头开始并递增。我不确定指针位置是否会在迭代之间保持在相同的位置,所以我手动偏移它。

标签: c file search io


【解决方案1】:

您的第一个示例假设文件由固定长度的 User 记录组成,按 id 编号排列,没有间隙。 id 1 的记录将在偏移量 0 处,id N 的记录将在 (N - 1) * sizeof(User)。如果这是文件实际包含的内容,这是一个合理的假设。

您问题底部的代码似乎正遭受身份危机。它无法确定记录是否按 id 顺序排列,或者是否需要通过匹配 username 来搜索文件。这是两种不同查找方法的不可行混合。您需要选择一种方法并使用它。

如果文件按 id 排序并且不包含空白(并且您正在按 id 搜索),则无需在 while 循环中搜索。

另一方面,如果文件是无序的,或者包含间隙,则有必要进行搜索。在这种情况下,就不需要fseekrewind 调用。只需从文件的开头开始,依次读取每条记录,一次一条,直到找到与请求的用户名匹配的记录。

另外,比较freadEOF 的返回值是错误的。 fread 函数返回实际读取的项目数。如果返回的数字不等于您在调用中指定的项目数,则可能存在读取错误,或者您已到达文件末尾。 EOF 常量适用于像 fgetc 这样返回 character 值的函数。

【讨论】:

  • 所以如果我反复调用 fread() 它会像 fscanf() 那样在文件中移动指针?
  • 谢谢。我现在明白了这一点。我应该按顺序阅读,并将每次阅读与输入的数据进行比较。至于你提到的间隙,以确保我不会留下间隙,我应该假设我可以按顺序读取,直到找到一个空结构或“已删除结构”并覆盖它。并且要实际编辑数据,我必须将指针负偏移我正在编写的结构的大小。谢谢你的解释。
  • @Deeswoc 通过“间隙”,我指的是文件中 id 值序列中的间隙。不是数据中的空白,例如,只有零或类似的东西。关键是,如果您通过 id 查找并计算文件中该 id 的偏移量,那么您假设直到该点为止的序列中的每个 id 都存在于文件中。例如,如果您正在查找 id 5,但您的文件仅包含 id 1、2 和 5 的记录,那么您如何计算正确的偏移量?当然不是(id - 1) * sizeof(User)
  • @Deeswoc 当然,这意味着重复的 id 也不存在,例如,id 为 1、1、2、3、4、4、5 的文件。在这种情况下,(id - 1) * sizeof(User) 也会给出不正确的偏移量,即使没有间隙。
猜你喜欢
  • 2022-11-21
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多