二进制文件复制了更新的帐户

时间:2018-07-31 22:44:36

标签: c binaryfiles

我编写了一个程序,其中涉及为客户创建银行帐户。但是,当我从该帐户“存入”资金时,它将更新,但它将添加该更新的帐户并保留旧的帐户,如下所示:

First Name: her
Middle Name: m.
Last Name: an
Account Number: 1
Balance: $5600.00


First Name: her
Middle Name: m.
Last Name: an
Account Number: 1
Balance: $11600.00

我相信在我的switch语句之前,它将在我的代码开头处理我的“ fopen”。如果我将“ ab +”更改为除此之外的任何内容,则不会保存我的“帐户”。并在我再次运行可执行文件时将其删除。

 FILE *aPtr;
    aPtr = fopen( "accounts.dat", "ab+");
    if ( aPtr == NULL ) {
            printf ( "File could not be opened" );
            exit(1);
    }

    fseek( aPtr, 0, SEEK_SET ); /* Moving pointer to start of file*/

    while ( fread(accounts + i, sizeof(data), 1, aPtr) )
            i++;

            n = i; /* Num. of records in file */

下面提供了当我“保存”时的代码,我相信复制数据的原因可能与我使用“ fwrite”的方式以及保存位置有关。但是我似乎无法弄清楚问题是什么。

在正确方向上的任何帮助将不胜感激。

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

typedef struct
{
    char first[15];
    char middle[2];
    char last[15];
    float balance;
    long int acct;
 }data;

int main()
{
    int choice = -1, i = 0, n = 0;
    long int number;
    double amount;
    data accounts[50];

    FILE *aPtr;
    aPtr = fopen( "accounts.dat", "ab+");
    if ( aPtr == NULL ) {
            printf ( "File could not be opened" );
            exit(1);
    }

    fseek( aPtr, 0, SEEK_SET ); /* Moving pointer to start of file*/

    while ( fread(accounts + i, sizeof(data), 1, aPtr) )
            i++;

            n = i; /* Num. of records in file */

            do
            {

                    printf ( "Select Option\n" );
                    printf ( "0: Exit\n1: Deposit\n2: Withdrawl\n3: Add Account\n4: Remove Account\n5: Balance Inquiry\n6: View Accounts\n: ");
                    scanf ( "%d", &choice );
                    printf("\n\n");

                    switch (choice)
                    {
                            case 0: /* Exit */
                                    fclose ( aPtr );
                                    break;

                            case 1: /* Deposit*/
                                    fseek( aPtr, 0, SEEK_SET );

                                    printf ( "Enter account number:\n" );
                                    scanf ( "%ld", &number );
                                    printf ( "Enter amount to be deposited:\n" );
                                    scanf ( "%lf", &amount );

                                    for ( i = 0; i < n; i++ ) {
                                            if ( accounts[i].acct == number ) {

                                                    accounts[i].balance = accounts[i].balance + amount;
                                                    fseek( aPtr, i*sizeof(data), SEEK_SET ); /* Pointer goes to accountlocation in file*/
                                                    fwrite( &accounts[i], sizeof(data), 1, aPtr ); /* Write modified account into file */

                                                    printf("New Balanace: $%.2f\n\n", accounts[i].balance);
                                                    break;
                                            }
                                    }

                                    if ( i == n) {
                                            printf("Account does not exist\n\n");
                                            break;
                                    }
                                    break;

                            case 2: /* Withdrawal */
                                    fseek( aPtr, 0, SEEK_SET);

                                    printf("Enter the account to withdrawal:\n");
                                    scanf("%ld", &number);
                                    printf("Enter amount to withdrawal\n");
                                    scanf("%lf", &amount);

                                    for (i = 0; i < n; i++) {
                                            if (accounts[i].acct == number) {
                                                    if (accounts[i].balance < amount) { /* checks for required balance */
                                                            printf ("Not a sufficient balance\n\n");
                                                            break;
                                                    }

                                                    accounts[i].balance = accounts[i].balance - amount;
                                                    fseek(aPtr, i * sizeof(data), SEEK_SET);
                                                    fwrite(accounts+i, sizeof(data), 1, aPtr);
                                                    printf("New Balance: $%.2f\n\n", accounts[i].balance);
                                                    break;
                                            }
                                    }

                                    if(i == n )
                                            printf("Account number does not exist\n\n");

                                    break;

                            case 3: /* Add */
                                    printf ("Enter account number (1-99):\n");
                                    scanf ("%ld", &number);

                                    for (i = 0; i < n; i++) {
                                            if (accounts[i].acct == number) {
                                                    printf("Account already exist\n\n");
                                                    break;
                                            }
                                    }

                                    if (i == n) {
                                            printf("Enter First Name:\n");
                                            scanf("%s", accounts[i].first);
                                            printf("Enter Middle Initial:\n");
                                            scanf("%s", accounts[i].middle);
                                            printf("Enter Last Name:\n");
                                            scanf("%s", accounts[i].last);
                                            accounts[i].acct = number;
                                            printf("Enter Deposit Amount:\n");
                                            scanf("%f", &accounts[i].balance);
                                            printf("\n\n");

                                            fseek(aPtr, 0, SEEK_END);
                                            fwrite(accounts+i, sizeof(data), 1, aPtr);

                                            n++;
                                    }

                                    break;

                            case 4: /* Delete */
                                    fseek(aPtr, 0, SEEK_SET);
                                    printf("Enter account wished to be deleted:\n");
                                    scanf("%ld", &number);

                                    for(i = 0; i < n; i++) {
                                            if(accounts[i].acct == number)
                                                    break;
                                            }

                                            if( i == n ) {
                                                    printf("Account number does not exist\n\n");
                                            }

                                            else {
                                                    while ( i < n ) {
                                                            strcpy(accounts[i].first, accounts[i+1].first);
                                                            strcpy(accounts[i].middle, accounts[i+1].middle);
                                                            strcpy(accounts[i].last, accounts[i+1].last);
                                                            accounts[i].acct = accounts[i+1].acct;
                                                            accounts[i].balance = accounts[i+1].balance;
                                                            n--;
                                                    }




                                            aPtr = fopen("accounts.dat", "wb");

                                            for(i = 0; i < n; i++)
                                                    fwrite(accounts+i, sizeof(data), 1, aPtr); /* Writes records w/o deleted record */
                                            fclose(aPtr);

                                            fopen("accounts.dat", "ab+");

                                    }
                                    break;

                            case 5: /* Print Required Account */
                                    printf("Enter Account Number:\n");
                                    scanf("%ld", &number);

                                    for(i = 0; i < n; i++) {
                                            if(accounts[i].acct == number) {
                                                    printf("First Name: %s\n", accounts[i].first);
                                                    printf("Middile Initial: %s.\n", accounts[i].middle);
                                                    printf("Last Name: %s\n", accounts[i].last);
                                                    printf("Account Number: %ld\n", accounts[i].acct);
                                                    printf("Balance: $%.2f\n\n", accounts[i].balance);
                                                    printf("\n\n");

                                                    break;
                                            }
                                    }
                                    if ( i == n ) {
                                            printf("Account does not exist\n\n");
                                            break;
                                    }
                                    break;
                            case 6: /* Print All */
                                    for(i = 0; i < n; i++) {
                                            printf("First Name: %s\n", accounts[i].first);
                                            printf("Middle Name: %s.\n",accounts[i].middle);
                                            printf("Last Name: %s\n", accounts[i].last);
                                            printf("Account Number: %ld\n", accounts[i].acct);
                                            printf("Balance: $%.2f\n", accounts[i].balance);
                                            printf("\n\n");
                                    }

                    }

            } while ( choice != 0 );

    return 0;

}

1 个答案:

答案 0 :(得分:2)

代码缺少错误检查,因此未能防止缓冲区溢出。

scanf("%s", ...就像弱gets()。使用宽度限制。

typedef struct {
  char first[15];
  char middle[2];
  char last[15];
  float balance;
  long int acct;
} data;

//scanf("%s", accounts[i].first);
scanf("%14s", accounts[i].first);// Max 14 characters to read and save a string in first[15]
//scanf("%s", accounts[i].middle);
scanf("%1s", accounts[i].middle);
//scanf("%s", accounts[i].first);
scanf("%14s", accounts[i].first);

更好的代码将检查返回值以确保其为1。

if (scanf("%14s", accounts[i].first) != 1) {
  printf("Bad input\n");
  return EXIT_FAILURE;  // or other error handing.
}

甚至更好的代码也将废弃所有scanf()的调用,并替换为fgets()和可靠的解析-但将其保留一天。


"m."输入char middle[2];的情况下,代码遇到未定义的行为(UB)。还有wheels fell off the bus。代码可能需要更大的名称字符数组。在最长名中搜索一些想法。


存在其他问题。

@user3386109 Open file mode

“平衡”->“平衡”

避免使用float来赚钱。建议使用最小货币单位的doublelong long。这是一个涉及许多问题的深层问题,至少不要使用float

名称可能包含空格。 "%s"对此不起作用。