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

世話をすることがたくさんあります。
1. ファイルが正しく閉じられていません。

プログラムの開始時にファイルを開いています。そして閉店したことはありません。ファイルに書き込むものはすべて、実際にはすぐには書き込まれず、バッファリングされます。ファイルをフラッシュするか、ファイルを閉じる必要があります。そのため、ファイルに対して他の操作を行う前に、ファイルがフラッシュされていることを確認してください。

2. レコードはファイルから読み戻されません。

ファイルからレコードを読み戻していません。常に構造の現在の値を検索しますrec。比較する前に、各レコードを構造体に読み込む必要があります。また、ファイルを読み取らないと、ファイル ポインタが進むことはなく、制御は永遠にループにとどまります。

3. 改行は扱いません。

各レコードの後に​​追加の改行があります。ファイルからレコードを読み戻しながら、それらを処理する必要があります。gets行末の改行を 1 つ消費します。そのため、追加の を手動で処理する必要があります\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したがって、このコードでは、最後のレコード whereがファイルから読み取られた後、ループがもう一度続きます。すべてのレコードを印刷しようとしない限り、これは問題ではありません。その場合は、別の終了条件を使用してください。

于 2013-04-02T12:28:06.320 に答える
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 に答える
0

コードを正しく読んだ場合、ファイルを閉じずにファイルに書き込んだ後、レコードを検索しようとしています。これを行いたい場合は、rewind または fseek を呼び出して先頭に移動する必要があります。

これを行う前にファイルの位置を保存する (ftell) か、さらにレコードを追加する前に、append more を閉じて開く必要があることに注意してください。

John が上で指摘したように、読み取りは +a モードでもまったく機能しない可能性があります。ケースごとにファイルを閉じ、正しいモードで開くことをお勧めします。

于 2013-04-01T22:51:06.267 に答える
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+ が機能しないため、ケース 2 のファイルを読み取りモードで開きます。

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 に答える