0

我正在使用 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 上进行了测试。

4

5 回答 5

1

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

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

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

下面是修改后的代码,

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;
}
于 2013-04-02T06:08:56.140 回答
1

有很多事情要照顾。
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因此,在这段代码中,循环在从文件中读取的最后一条记录之后再继续一次。除非您尝试打印所有记录,否则这不是问题。在这种情况下,请使用不同的退出条件。

于 2013-04-02T12:28:06.320 回答
0

让我先理解你的问题,

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

可以说这部分的代码:

 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..
    }
}

希望这可以帮助, :)

于 2013-03-31T17:41:21.613 回答
0

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

要在一行上写入一个字段,请更改fputs(rec.name,f1)fprintf(f1,"%s\n",rec.name),与其他字段类似。现在,一条记录由特定序列中固定数量的行组成——具体来说,一行 forname和一行 for sur。然后,您可以通过两次调用来读取记录fgets

于 2013-04-01T19:55:09.640 回答
0

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

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

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

于 2013-04-01T22:51:06.267 回答