2011-02-09 9 views
1

私は、以前のプログラムで作成した2つの.dat(aascii)ファイルを読み込む必要があり、どちらもソートされています。Cファイル処理とマッチングヘルプ

1つはクライアントの残高とアカウント番号と名前を含むクライアントアカウントファイルで、もう1つはアカウント番号とそのアカウントのトランザクションを含むトランザクションファイルです。

このプログラムは、口座番号に一致し、取引金額を口座番号に基づいてクライアントの残高に追加することによって、新規で更新されたクライアントファイルを作成する必要があります。

たとえば、トランザクションファイルに2番目のクライアントの2つのトランザクションが含まれている場合など、重複トランザクションがある場合を除いて、この正常に機能します。

誰もがこの問題の解決方法を明らかにできるかどうかは不思議です。私のコードが添付されています、ありがとうございます。

#include <stdio.h> 
#include <conio.h> 
int main() 
{ 
    int account,matches=0;  /* account number */ 
    char date[ 30 ]; /* account Date */ 
    double balance, saleamount,total=0, x; /* account SaleAmount */ 
    int transaccount; 
    char name [ 30 ]; 



    FILE *cfPtr;  /* cfPtr = clients.dat file pointer */ 
    FILE *ctPtr; /* cfPtr = transaction.dat file pointer */ 
    FILE *cfPtr2; /* cfPtr2 = new client file */ 

    cfPtr2 = fopen("clientupdate.dat", "w"); 

    /* fopen opens file; exits program if file cannot be opened */ 
    if ((cfPtr = fopen("clients.dat", "r")) == NULL) { 
     printf("clients could not be opened\n"); 
     fflush(stdin); 
    } /* end if */ 
    else 
     if((ctPtr = fopen("transactions.dat", "r")) == NULL) 
     { 
      printf("File could not be opened\n"); 
      fflush(stdin); 
     } 
    else { /* read account, date,name, balance and SaleAmount from files */ 
     fscanf(cfPtr, "%d%s%lf", &account, &name, &balance); 
     fflush(stdin); 

     fscanf(ctPtr, "%d%s%lf", &transaccount, &date, &saleamount); 
     fflush(stdin); 

     printf("%-13s%-10s%s\n", " Account", "Name", "Balance"); 
     printf("|----------------------------------|\n"); 
     while(!feof(ctPtr)) 
     { 

      while(!feof(cfPtr) &&matches==0) 
      { 

       if(account == transaccount) 
       { 
        matches=1; 
        total=0; 
        x = balance+saleamount; 
        total = total + x; 
        balance = total; 

       printf(" %-10d%-10s%.2lf\n", account, name, total); 
       } 
       else 
       { 

        fscanf(cfPtr, "%d%s%lf", &account, &name, &balance); 
        fflush(stdin); 
       } 

      } 
      fprintf(cfPtr2, "%d %s %.2lf\n", account, name, total); 
      fscanf(ctPtr, "%d%s%lf", &transaccount, &date, &saleamount); 
      fflush(stdin); 
      matches=0; 

     } 

     fclose(cfPtr2); 
     getch(); 
} 

答えて

0

paxの助けを借りて、自分のコードで遊んでいる間、私はこの解決策を考え出しました。助けてくれてありがとう、ありがとう。

#include <stdio.h> 
#include <string.h> 
int main(void) 
{ 
    int account;  /* account number */ 
    char date[ 30 ]; /* account Date */ 
    double balance, saleamount; /* account SaleAmount */ 
    int transaccount; 
    char name [ 30 ]; 
    int newaccount; 
    char newname[ 30]; 
    double newbalance; 
    int match=0; 



    FILE *cfPtr;  /* cfPtr = clients.dat file pointer */ 
    FILE *ctPtr; /* cfPtr = transaction.dat file pointer */ 
    FILE *cfPtr2; /* cfPtr2 = new client file */ 

    cfPtr2 = fopen("clientupdate.dat", "w"); 

    /* fopen opens file; exits program if file cannot be opened */ 
    if ((cfPtr = fopen("clients.dat", "r")) == NULL) { 
     printf("clients could not be opened\n"); 

    } /* end if */ 
    else 
     if((ctPtr = fopen("transactions.dat", "r")) == NULL) 
     { 
      printf("File could not be opened\n"); 

     } 
    else { /* read account, date,name, balance and SaleAmount from files */ 
     fscanf(cfPtr, "%d%s%lf", &account, &name, &balance); 


     fscanf(ctPtr, "%d%s%lf", &transaccount, &date, &saleamount); 
     fscanf(cfPtr2, "%d%s%lf", &newaccount, &newname, &newbalance); 
     while (!feof(cfPtr)) 
     { 
      transaccount=1; 
      newbalance=balance; 
      while (!feof(ctPtr)) 
      { 
       if(transaccount==account&&match==0) 
       { 
       newbalance = balance + saleamount; 
       match++; 
       } 
       else 
        if(transaccount==account&&match>0) 
        newbalance = newbalance + saleamount; 

       fscanf(ctPtr, "%d%s%lf", &transaccount, date, &saleamount); 
      } 
      rewind(ctPtr); 
      match=0; 

     fprintf(cfPtr2, "%d %s %.2f\n", account, name, newbalance); 
     fscanf(cfPtr, "%d%s%lf", &account, name, &balance); 
     } 

     rewind(cfPtr2); 
    } 
     fclose(cfPtr2); 
     fclose(cfPtr); 
     fclose(ctPtr); 
     getchar(); 
    return 0; 
} 
0

結果をすぐにprintfで出力する代わりに、結果を配列に入れてください。

whileループが終了したら、forループを使用して、格納されたデータの配列を調べ、重複したトランザクションを探し、一緒に結合してマージされたトランザクションを出力します。

+0

私は、画面への印刷を除き、あなたはある程度ニックに何を意味するか理解は、私の主な目標が何であるかを私自身の利益のために、新しいクライアントが重複なしでファイルを作成することで、その私に長い時間がかかっそれはファイルにバランスとfprintfを更新する段階に到達するために、私はその情報をすべて格納してマージするのに十分な能力を持っているのか分かりません。 – James

0

私はあなたが見てきた問題が関連しているわからないんだけど、:

  1. fflush(stdin)は未定義の動作を与える - それをしません。次の改行まですべてスキップしたい場合は、scanf("%*[^\n'");
  2. while(!feof(ctPtr))が問題を起こすことがほぼ保証されています。通常、ファイルからの最後の読み取りが2回起こっているように見えますが、データを複製する。

「複製トランザクション」はおそらく後者に由来すると思われます。

+0

ありがとう、ジェリー、私はこの場合にフラッシングが必要かどうかは確かではなかったし、eof ptrに関しては、私はそれが課題の別の部分で起こったとして理解している...しかし、重複に関しては、元のトランザクションファイルに重複トランザクションがあるので、2つのファイルを読み込んだときに、更新されたクライアント残高は両方のトランザクションを考慮してバランスを1回だけ更新しますが、出力は次のようになります。 1 james 540.00 2 john 662.00 2 john 762.00 ここで、johnsの2番目の取引は100.00 – James

4

私は彼らがCOBOL(Cの装いの下で)をまだ教えているとは思えませんが、ここで助けを求めている人たちとは違って、

最新の更新の後ではなく、口座番号が変わるまでお待ちください。の前にの詳細を印刷してください。

最後のアカウントを処理している間にトランザクションファイルの最後に到達するため、ループを終了してからもう一度実行する必要があります。

詳細な手順は次のとおりです。


はさらに3つの変数、char lastname[30]int lastaccountdouble lastbalanceを紹介します。 lastaccount-1に初期化されていることを確認してください。

コードでは、lastaccountaccountの値を確認するだけで、アカウント番号の遷移をキャッチできます。3つのフィールドをすべて保存すると、既に新しいアカウントの詳細を読み込んでいても、以前のアカウントの詳細を印刷できるようになります。あなたはまた、strcpyのプロトタイプを得るためにstring.hを含める必要があります

if (lastaccount != account) { 
    if (lastaccount != -1) 
     printf(" %-10d%-10s%.2lf\n", lastaccount, lastname, lastbalance); 
    lastaccount = account; 
    strcpy (lastname, name); 
} 


matches = 1する前に、次のコードを挿入します。

これは、口座番号の遷移をキャッチし、(それはなし以前のものがあることを意味するので、最後の1はもちろんの口座番号-1でない限り)最後の1について詳細を印刷します。しかし、それが印刷されるかどうかに関係なく、次の移行のために設定されます。


すぐbalance = total後、lastbalance = balance;を追加します。これにより、現在の勘定科目の最新の残高が維持され、移行時に印刷できるようになります。

口座番号と名前とは違って、これはすべてのトランザクションではなく、すべてのアカウントのために行う必要があります。これは、アカウントのアカウント/名前は変更されませんが、締め切り残高は(1回のトランザクションごとに)変更されるためです。ループの外


、すぐfclose (cfPtr2);前に、コードを置く:

if (lastaccount != -1) 
    printf(" %-10d%-10s%.2lf\n", lastaccount, lastname, lastbalance); 

をこれがすべてで処理いずれかがあったと仮定して、最終的にアカウントの詳細を印刷します。先に述べたように、これは、変更されたアカウント番号のために移行を行わずにファイルの最後に到達するために必要です。


そして、最終的な要求としてしてください:

  • conio.hを取り除くとgetchar()の代わりgetch()を使用しています。
  • 、可能溝ターボCとgccを使う場合 - それは
  • んではないfflush(stdin) :-)そうはるかに優れです。
  • 標準int main (void) ...を使用してください。
  • mainから何かを戻してください(後のバージョンの標準ではリラックスしていますが)。

(あなたはそれが宿題ではありません保証しなければ)私は私の実際のコードを投稿しませんが、次の転写物は、それらの変更は、あなたの現在の問題を修正するために十分でなければならないことを示しています。

$ cat clients.dat 
1 Pax 4.2 
2 Roger 0 

$ cat transactions.dat 
1 1/2/3 112.3 
1 2/3/4 -22.1 
2 3/4/5 7 

$ ./qq 
    Account Name  Balance 
|----------------------------------| 
    1   Pax  94.40 
    2   Roger  7.00 

価値があることについては、私は、トランスアーションファイルを主要な要素として扱うことに全く同意していません。あなたの仕事は(トランザクションファイルで指定されているように)必要な変更を加えてアカウントファイルをコピーすることなので、アカウントファイルをプライマリユニットとして処理したいと思っています。

それは私にはそんなにクリーンなようです。

そして、完全性のために、私が思いついたコードはここにあります。あなたのマークを減らす可能性のあるものがたくさんあるので、これを譲渡として伝えることはお勧めしません。実際の世界では問題はほとんどありませんが、教育者はボンネットに特定の蜂を持っています。 enumの代わりに#defineを使用するなど、複数の戻り点があります。この出力は

1 1/2/3 112.3 
1 2/3/4 -22.1 
4 3/4/5 7 

0 Mary 99.9 
1 Pax 4.2 
2 Bob 7 
4 Roger 0 
5 Nobody 9 

とのtransactions.dat

+--------+------------+--------+--------+--------+ 
| Acct | Name | Date | Amount | Balnce | 
+--------+------------+--------+--------+--------+ 
|  0 | Mary  |  |  | 99.90 | <-- 
|  |   |  |  | 99.90 | --> 
+--------+------------+--------+--------+--------+ 
|  1 | Pax  |  |  | 4.20 | <-- 
|  |   | 1/2/3 | 112.30 | 116.50 | 
|  |   | 2/3/4 | -22.10 | 94.40 | 
|  |   |  |  | 94.40 | --> 
+--------+------------+--------+--------+--------+ 
|  2 | Bob  |  |  | 7.00 | <-- 
|  |   |  |  | 7.00 | --> 
+--------+------------+--------+--------+--------+ 
|  4 | Roger  |  |  | 0.00 | <-- 
|  |   | 3/4/5 | 7.00 | 7.00 | 
|  |   |  |  | 7.00 | --> 
+--------+------------+--------+--------+--------+ 
|  5 | Nobody  |  |  | 9.00 | <-- 
|  |   |  |  | 9.00 | --> 
+--------+------------+--------+--------+--------+ 

clientupdate.datを作成するclients.dat考える

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

#define HDR_LINE 0 
#define HDR_FULL 1 

static void outHeader (int withHeading) { 
    printf ("+-%-6s-+-%-10s-+-%-6s-+-%-6s-+-%-6s-+\n", 
     "------", "----------", "------", "------", "------"); 
    if (withHeading) 
     printf ("| %-6s | %-10s | %-6s | %-6s | %-6s |\n", 
      " Acct ", " Name ", " Date ", "Amount", "Balnce"); 
} 

static void closeFiles (FILE *pfCli, FILE *pfTxn, FILE *pfNew) { 
    if (pfCli) fclose (pfCli); 
    if (pfTxn) fclose (pfTxn); 
    if (pfNew) fclose (pfNew); 
} 

static int openFiles (FILE **pfCli, FILE **pfTxn, FILE **pfNew) { 
    *pfCli = *pfTxn = *pfNew = NULL; 

    if ((*pfCli = fopen ("clients.dat", "r")) == NULL) { 
     printf ("File clients.dat could not be opened\n"); 
     closeFiles (*pfCli, *pfTxn, *pfNew); 
     return 0; 
    } 

    if ((*pfTxn = fopen ("transactions.dat", "r")) == NULL) { 
     printf ("File transactions.dat could not be opened\n"); 
     closeFiles (*pfCli, *pfTxn, *pfNew); 
     return 0; 
    } 

    if ((*pfNew = fopen ("clientupdate.dat", "w")) == NULL) { 
     printf ("File clientupdate.dat could not be opened\n"); 
     closeFiles (*pfCli, *pfTxn, *pfNew); 
     return 0; 
    } 

    return 1; 
} 

static void outCli (int acct, char *nm, double bal, char *ind) { 
    if (acct == -1) 
     printf ("| %6s | %-10s | %6s | %6s | %6.2lf | %s\n", 
      "", nm, "", "", bal, ind); 
    else 
     printf ("| %6d | %-10s | %6s | %6s | %6.2lf | %s\n", 
      acct, nm, "", "", bal, ind); 
} 

static void outTxn (char *date, double amt, double bal) { 
    printf ("| %6s | %10s | %-6s | %6.2lf | %6.2lf |\n", 
     "", "", date, amt, bal); 
} 

static void getTxn (FILE *fh, int *acct, char *date, double *amt) { 
    if (feof (fh)) 
     *acct = -1; 
    else 
     fscanf (fh, "%d%s%lf\n", acct, date, amt); 
} 

static void getCli (FILE *fh, int *last, int *acct, char *nm, double *bal) { 
    if (*last != -1) 
     outCli (-1, "", *bal, "-->"); 
    *last = *acct; 
    fscanf (fh, "%d%s%lf\n", acct, nm, bal); 
} 

int main (void) { 
    int cli_acct, txn_acct, last_acct = -1; 
    char txn_date[10], cli_nm[10]; 
    double cli_bal, txn_amt; 
    FILE *fCli, *fTxn, *fNew; 

    // Open all files, output header and load up first transaction. 

    if (!openFiles (&fCli, &fTxn, &fNew)) 
     return 1; 

    outHeader (HDR_FULL); 

    getTxn (fTxn, &txn_acct, txn_date, &txn_amt); 

    // Process every account. 

    while (!feof (fCli)) { 
     // Bring in an account and print starting balance. 

     getCli (fCli, &last_acct, &cli_acct, cli_nm, &cli_bal); 
     outHeader (HDR_LINE); 
     outCli (cli_acct, cli_nm, cli_bal, "<--"); 

     // While account is not yet up to txn, output and read new. 

     while (cli_acct < txn_acct) { 
      fprintf (fNew, "%d %s %.2lf\n", cli_acct, cli_nm, cli_bal); 
      outCli (-1, "", cli_bal, "-->"); 
      outHeader (HDR_LINE); 
      fscanf (fCli, "%d%s%lf\n", &cli_acct, &cli_nm, &cli_bal); 
      outCli (cli_acct, cli_nm, cli_bal, "<--"); 
     } 

     // If they don't match, you have a orphan transaction. 

     if ((cli_acct != txn_acct) && (txn_acct != -1)) { 
      printf ("Orphan transaction for account # %d\n", txn_acct); 
      closeFiles (fCli, fTxn, fNew); 
      return 1; 
     } 

     // While account and transaction match, process transaction lines. 

     while (cli_acct == txn_acct) { 
      cli_bal = cli_bal + txn_amt; 
      outTxn (txn_date, txn_amt, cli_bal); 
      if (feof (fTxn)) 
       txn_acct = -1; 
      else 
       fscanf (fTxn, "%d%s%lf\n", &txn_acct, &txn_date, &txn_amt); 
     } 
     fprintf (fNew, "%d %s %.2lf\n", cli_acct, cli_nm, cli_bal); 
    } 

    // Output final lines if needed. 

    if (last_acct != -1) 
     outCli (-1, "", cli_bal, "-->"); 
    outHeader (HDR_LINE); 

    // Close all files and exit successfully. 

    closeFiles (fCli, fTxn, fNew); 
    return 0; 
} 

of:

0 Mary 99.90 
1 Pax 94.40 
2 Bob 7.00 
4 Roger 7.00 
5 Nobody 9.00 

あなたの宿題として渡す以外の目的で、このコードを自由に使用することができます。

+0

です。私は実際に何をする必要があるかを実際に理解できるように、ヘルプを非常に高く評価しています。 conio.hなどを使わないことを覚えておいてください!再度、感謝します。 – James

+0

ちょうどそこにコードが変更されました。私の問題は解決しました。私は、最新の残高が更新されている現在のアカウントに対して保持される必要があることに気づきませんでした。アウトプットは今すぐ役立ちますので、このラボの別の部分を解読してください。 – James

+0

あなたは私を嫌いになるだろうが、私はちょうどそこにいくつかのものをテストし、コードが画面に結果を印刷するための素晴らしい作品が、私のために、私はまだ 1ジェームズ540.00 2ジョン662.00 2ジョン762.00 を取得していますこのファイルに書いたのは2ジョン762ではなく、残念ながら新しいファイルがスクリーンにプリントされているのではなく、アップデートされていることが増えている=( – James