【问题标题】:Search a record in a file with C [closed]使用 C 搜索文件中的记录 [关闭]
【发布时间】:2013-03-19 15:09:52
【问题描述】:

我正在使用 C 和文件管理进行练习,我能够打开文件、在文件上写入记录、关闭文件,但是我无法找到已经写入的记录。这是我的练习:(案例 2 中的搜索)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main(){
    struct info{
        char name[40];
        char sur[40];
    };
    struct info rec;
    FILE *f1, *f2;
    int sel, ser, res;
    char cmp[40];
    int cont=0;

    f1=fopen("lis.txt","a+");

    do{
        do{
            printf("1> Add account\n");
            printf("2> Search account\n");
            printf("3> Modify account\n");
            printf("4> Exit\n");
            printf("Type your choice -> ");
            scanf("%d", &sel);
            if(sel<1 || sel>4){
                printf("ERROR: The choice isn't allowed\n");
            }
        }while(sel<1 || sel>4);

        getchar();
        switch(sel){
            case 1:
                printf("Insert new account\n");
                printf("Write name: ");
                fgets(rec.name, sizeof(rec.name), stdin);
                printf("Write surname: ");
                fgets(rec.sur, sizeof(rec.sur), stdin);

                fputs(rec.name,f1);
                fputs(rec.sur,f1);
                fprintf(f1,"\n");

                printf("Account added!\n");
                break;
            case 2:
                printf("Search account\n");
                printf("Write surname to search: ");
                fgets(cmp, sizeof(cmp), stdin);
                while(!feof(f1)){
                    if(strcmp(cmp,rec.sur)==0){
                        printf("ENT\n");
                    }
                }
                break;
    //      case 3:
    //          printf("Modify account\n");
    //          //funzione ricerca qua
    //          printf("Account modificato correttamente!\n");
    //          break;
            case 4:
                printf("Closing...\n");
                break;
            default:
                printf("ERROR!\n");
                break;
        }
    }while(sel!=4);
}

程序还没有完成,所以我稍后会修复很多未使用的东西。 它在 OpenVMS 上进行了测试。

【问题讨论】:

  • 请明确您的问题(尤其是question)。
  • 情况2中的循环,我想这是一个feof错误但我不知道如何解决
  • 在案例 2 中,您如何期望该循环每次提前文件指针到达 EOF ?
  • 标准循环是while (fgets(cmp, sizeof(cmp), stdin) != 0) { ... }。只有在 I/O 函数报告 EOF(例如 fgets() 返回 NULL)后,才使用 feof() 来区分 EOF 和 I/O 错误。基本上,如果你忘记了feof() 的存在,你就不会出错。
  • @AlessioMTX,请阅读this StackOverflow thread 以获取有关您的feof() 问题的更多信息。

标签: c file-management


【解决方案1】:

先让我理解你的问题,

你的意思是你找不到以前输入的记录。

让我们说这部分的代码:

 printf("Search account\n");
 printf("Write surname to search: ");

 fgets(cmp, sizeof(cmp), stdin);
      while(!feof(f1)){
          if(strcmp(cmp,rec.sur)==0){
              printf("ENT\n");
          }
      }
      break;

读取文件,然后....

如果你这样写代码:

以读取模式打开文件,因为如果您尝试读取文件,a+ 将不起作用

f1 = fopen("lis.txt", "r");

if (!f1) {
    printf("lis.txt, no such file exits\n");
    return -1;
}

while (feof(f1)) {
    fgets(str, len, f1);
    if (strcmp(str, sur) == 0) {
        /// Do what ever you want, printing the record e.t.c..
    }
}

希望这会有所帮助,:)

【讨论】:

    【解决方案2】:

    问题始于您写入文件的格式。您可以为每条记录写完整的struct info,也可以将每个字段写在一行上。在第一种情况下,文件将被称为“二进制”;第二种情况“文本”。您似乎更喜欢文本文件格式。

    要将字段写入一行,请将fputs(rec.name,f1) 更改为fprintf(f1,"%s\n",rec.name),其他字段类似。现在,一条记录包含特定序列中固定数量的行——具体而言,一行用于name,一行用于sur。然后,您可以通过两次调用 fgets 来读取记录。

    【讨论】:

      【解决方案3】:

      如果我正确阅读了代码,那么您在将记录写入文件后尝试搜索记录而不关闭文件。如果你想这样做,你需要调用 rewind 或 fseek 来回到开头。

      请记住,您要么需要在执行此操作之前存储文件位置 (ftell),要么在添加更多记录之前以追加方式关闭和打开。

      正如约翰在上面指出的那样,在 +a 模式下阅读也可能根本不起作用。最好在每个案例后关闭文件并以正确的模式打开它。

      【讨论】:

        【解决方案4】:

        feof()的使用总是有问题,所以请避免使用它...

        为什么不使用 feof() 作为循环退出条件。请here是链接。

        here 是一个很好的教程的链接,我已经将它与你的代码结合起来,它就像魅力一样工作......请查看它。

        下面是修改后的代码,

        struct info
        {
            char name[40];
            char sur[40];
        };
        
        int Search_in_File(char *fname, char *str) {
            FILE *fp;
            int line_num = 1;
            int find_result = 0;
            char temp[40];
        
            if((fp = fopen(fname, "r")) == NULL) {
                return(-1);
            }
        
            while(fgets(temp, 40, fp) != NULL) {
                if((strstr(temp, str)) != NULL) {
                    printf("A match found on line: %d\n", line_num);
                    printf("\n%s\n", temp);
                    find_result++;
                }
                line_num++;
            }
        
            if(find_result == 0) {
                printf("\nSorry, couldn't find a match.\n");
            }
        
            //Close the file if still open.
            if(fp) {
                fclose(fp);
            }
            return(0);
        }
        
        
        int main()
        {
        
            struct info rec;
            FILE *f1; //*f2;
            int sel;// ser, res;
            char cmp[40];
            char fname[10] = "lis.txt";
            int err = -1;
        //    int cont=0;
        
        
            do{
                do{
                    printf("1> Add account\n");
                    printf("2> Search account\n");
                    printf("3> Modify account\n");
                    printf("4> Exit\n");
                    printf("Type your choice -> ");
                    scanf("%d", &sel);
                    if(sel<1 || sel>4){
                        printf("ERROR: The choice isn't allowed\n");
                    }
                }while(sel<1 || sel>4);
        
                getchar();
                switch(sel){
                    case 1:
                        f1=fopen(fname ,"a+");
                        if (!f1) 
                        {
                            printf("lis.txt, no such file exits\n");
                            return -1;
                        }            
                        printf("Insert new account\n");
                        printf("Write name: ");
                        fgets(rec.name, sizeof(rec.name), stdin);
                        printf("Write surname: ");
                        fgets(rec.sur, sizeof(rec.sur), stdin);
        
                        fprintf(f1,"%s",rec.name);
                        fprintf(f1,"%s\n",rec.sur);
        
                        fflush(f1);
                        printf("Account added!\n");
                        fclose(f1);
                        break;
                    case 2:
                        printf("Search account\n");
                        printf("Write surname to search: ");
                        fgets(cmp, 40, stdin);
                        err = Search_in_File(fname, cmp);
                        if(err < 0)
                        {
                            return err;
                        }
                        break;
                  case 3:
                      printf("Modify account\n");
                      break;
                    case 4:
                        printf("Closing...\n");
                        break;
                    default:
                        printf("ERROR!\n");
                        break;
                }
            }while(sel!=4);
        
            return 0;
        }
        

        【讨论】:

          【解决方案5】:

          有很多事情需要照顾。
          1.文件未正确关闭。

          您在程序开始时打开了文件。并且从未关闭。 您写入文件的任何内容都不会立即实际写入,它们会被缓冲。 您需要刷新它或关闭文件。因此,在对文件执行任何其他操作之前,请确保它已被刷新。

          2。不会从文件中读回记录。

          您尚未从文件中读回记录。您总是搜索rec 结构的当前值。在比较之前,您需要将每条记录读取到结构中。此外,如果您不读取文件,则文件指针永远不会前进,并且控件将永远处于循环中。

          3。不处理新行。

          每条记录后都有新的行。您需要在从文件中读回记录时处理这些问题。 gets 在行尾使用一个换行符。所以你需要手动处理额外的\n

          此外,如果您找到记录,则需要从 while 循环中中断。除非您期望重复,否则留在那里毫无意义。

          以下内容对您的代码进行了一些修改。这对我有用。你可以试试这个:

          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          
          main(){
              struct info{
                  char name[40];
                  char sur[40];
              };
              struct info rec;
              FILE *f1, *f2;
              int sel, ser, res;
              char cmp[40];
              char dummy;
              int cont=0;
          
              do{
                  do{
                      printf("1> Add account\n");
                      printf("2> Search account\n");
                      printf("3> Modify account\n");
                      printf("4> Exit\n");
                      printf("Type your choice -> ");
                      scanf("%d", &sel);
                      if(sel<1 || sel>4){
                          printf("ERROR: The choice isn't allowed\n");
                      }
                  }while(sel<1 || sel>4);
          
                  getchar();
                  switch(sel){
                      case 1:
                          printf("Insert new account\n");
                          printf("Write name: ");
                          fgets(rec.name, sizeof(rec.name), stdin);
                          printf("Write surname: ");
                          fgets(rec.sur, sizeof(rec.sur), stdin);
                          f1=fopen("lis.txt","a+"); //<- open file for writing
                          fputs(rec.name,f1);
                          fputs(rec.sur,f1);
                          fprintf(f1,"\n");
                          fclose(f1); // close the file. this will flush the buffer.
                          printf("Account added!\n");
                          break;
                      case 2:
                          printf("Search account\n");
                          printf("Write surname to search: ");
                          fgets(cmp, sizeof(cmp), stdin);
                          f1=fopen("lis.txt","r"); //<- open the file for reading
                          while(!feof(f1)){
                                fgets(rec.name,sizeof(rec.name),f1); //<- read both the data. this will update the file pointer.
                                fgets(rec.sur,sizeof(rec.sur),f1);
                                fscanf(f1,"%c",&dummy); //<- this handles the additional newline
                              if(strcmp(cmp,rec.sur)==0){
                                  printf("RECORD FOUND::\nName:%sSurname:%s\n\n",rec.name,rec.sur);
                                  break; //<- break if record is found
                              }
                          }
                          fclose(f1); //<- close the file after you are done.
                          break;
              //      case 3:
              //          printf("Modify account\n");
              //          //funzione ricerca qua
              //          printf("Account modificato correttamente!\n");
              //          break;
                      case 4:
                          printf("Closing...\n");
                          break;
                      default:
                          printf("ERROR!\n");
                          break;
                  }
              }while(sel!=4);
          }
          

          注意:当我们使用feof() 退出循环时,我们必须读取EOF 来满足退出条件。因此,在这段代码中,循环在从文件中读取EOF 的最后一条记录之后再继续一次。除非您尝试打印所有记录,否则这不是问题。在这种情况下,请使用不同的退出条件。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-04
            • 1970-01-01
            • 1970-01-01
            • 2017-07-07
            • 2010-11-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多