C 文件处理和匹配帮助

标签 c

我在大学有一个作业,我们需要读取两个 .dat (aascii) 文件,这些文件是我们用早期程序创建的,这两个文件都是排序的。

一个是包含客户余额、帐号和名称的客户帐户文件,另一个是包含帐号和该帐户交易的交易文件。

该程序必须匹配帐号并创建一个新的和更新的客户文件,方法是根据帐号将交易金额添加到客户的余额中。

我的工作正常,除非有重复的交易,例如,如果交易文件包含第二个客户的 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();
}

最佳答案

虽然我不敢相信他们实际上仍在教授 COBOL(以 C 为幌子),但我会帮助你,因为与一些在这里寻求帮助的人不同,你实际上已经投入了大量工作:- )

诀窍是不要在每次更新后打印,而是等到帐号转换后打印出之前的最终详细信息。

而且,由于在处理最后一个帐户时您将到达交易文件的末尾,因此您必须在退出循环后再执行一次。

这是详细的步骤。

再引入三个变量,char lastname[30] , int lastaccountdouble lastbalance .确保 lastaccount初始化为 -1 .

然后您的代码可以通过简单地检查 lastaccount 的值来捕获帐号的转换。和 account .所有三个字段的存储是为了确保您可以打印出以前帐户的详细信息,即使您已经阅读了新帐户的详细信息。

之前 matches = 1 ,插入以下代码:

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

您还需要包含 string.h获取 strcpy 的原型(prototype).

这将捕获帐号的转换并打印最后一个的详细信息(除非最后一个是帐号-1,当然因为这意味着没有前一个)。但无论它是否打印,它都会为下一个过渡做好准备。

紧接在 balance = total 之后, 添加 lastbalance = balance; .这将保持当前账户的最新余额,以便在转换时打印。

与帐号和名称不同,这必须针对每笔交易而不是每个账户进行。这是因为帐户/名称不会更改帐户,但期末余额会更改(对于每笔交易)。

在循环之外,紧接在 fclose (cfPtr2); 之前,放上代码:
if (lastaccount != -1)
    printf("  %-10d%-10s%.2lf\n", lastaccount, lastname, lastbalance);

这将打印最终帐户的详细信息,假设有任何已处理。如前所述,这是必需的,因为由于帐号更改,您将到达文件末尾而无需进行转换。

并且,作为最终要求,请:
  • 摆脱conio.h并使用 getchar()而不是 getch() .
  • 如果可能,放弃 Turbo 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
    

    对于它的值(value),我不确定我是否完全同意将交易文件视为主要元素。由于您的工作是复制需要修改的帐户文件(如交易文件中指定的那样),因此我更愿意将帐户文件作为主要单位进行处理。

    这样对我来说似乎更干净。

    而且,为了完整起见,这是我想出的代码。我不建议将此作为作业提交,因为有很多事情可能会降低你的分数,这些事情在现实世界中的重要性要小得多,但教育 worker 在他们的帽子里有一个特别的蜜蜂:-) 像多个返回点,使用 #define而不是 enum , 等等。
    #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;
    }
    

    鉴于 clients.dat的:
    0 Mary 99.9
    1 Pax 4.2
    2 Bob 7
    4 Roger 0
    5 Nobody 9
    

    transactions.dat的:
    1 1/2/3 112.3
    1 2/3/4 -22.1
    4 3/4/5 7
    

    这输出:
    +--------+------------+--------+--------+--------+
    |  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的:
    0 Mary 99.90
    1 Pax 94.40
    2 Bob 7.00
    4 Roger 7.00
    5 Nobody 9.00
    

    随意将该代码用于任何目的,而不是将其作为您自己的作业。

    关于C 文件处理和匹配帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4940874/

    相关文章:

    c - 我如何查看不透明数据类型的内部?

    c - 在一个大的整数中插入逗号

    c - 积分推广

    c - OS X Xcode/clang 构建 Windows 可执行文件?

    c - short int 和 unsigned short 的输出?

    C 指针与结构的直接成员访问

    c++ - 主要参数处理问题

    c - 结构..有人能弄清楚吗?

    c - Geany编译

    c - ftp服务器初学者问题