1

I have written a program involving creating a bank account for customers. However when I "deposit" money from the account, it will update, but it will add that updated account and keep the old one, when it should not be there as seen below:

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

I believe it deals with my 'fopen' in the beginning of my code prior to my switch statement. If i change the "ab+" to anything besides that, my 'accounts' do not get saved. And are erased when I run the executable again.

 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 */

The code for when I 'deposit' is provided below, I believe the reason for the copying of data may have something to do with how I am using 'fwrite' and where it is saving. But i can not seem to figure out what the issue would be.

Any help in the right direction would be greatly appreciated.

#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;

}
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • You forgot to post the rest of your code. Can you [edit] your post to do so? – Ken White Jul 31 '18 at 22:50
  • @KenWhite it is upated –  Jul 31 '18 at 22:57
  • The answer to [your other question](https://stackoverflow.com/questions/51597686) was correct: when you use `"ab+"`, any write to the file appends to the end, ignoring any intervening `fseek` (§7.21.5.3/6). So you need to check if the file exists using `"rb+"`. If that fails, create the file with `"wb+"`. – user3386109 Jul 31 '18 at 23:14
  • If you truly were creating a *bank account for customers*, you would not being using `float balance` (or any floating point number for handling currency) Customers get quite irate when you begin losing money out of their accounts due to rounding errors. See [How to Read and Store Currency Values in C](http://stackoverflow.com/questions/33979478/how-to-read-and-store-currency-values-in-c) – David C. Rankin Aug 01 '18 at 00:00
  • @DavidC.Rankin There are [many issues with money](https://stackoverflow.com/a/32214586/2410359) and using an integer is OK for learner code. The best type is application dependent. Given that other languages readily support decimal FP, I'd consider that over C. – chux - Reinstate Monica Aug 01 '18 at 15:54
  • 1
    @chux - A shameless plug... but I like it `:)`. The External Links in the Wikipedia page do a good job introducing Fixed Point and its myriad of incarnations. The lyrics link is almost as good as your wheels-flying-off picture. – David C. Rankin Aug 01 '18 at 19:50

1 Answers1

2

Code lacks error checking and so failed to prevent buffer over-run.

scanf("%s", ... is like the weak gets(). Use width limits.

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);

Better code would check the return value to insure it is 1.

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

Even better code would scrap all scanf() calls and replace with fgets() and robust parsing - but leave that for another day.


With input "m." for char middle[2];, code experienced undefined behavior (UB). And the wheels fell off the bus. Code likely needs bigger name character arrays. Search longest name for some ideas.


Other issues exist.

@user3386109 Open file mode

"Balanace" --> "Balance"

Avoid using float for money. Recommend double or long long of smallest monetary unit. This is a deep issue with various concerns, just at least, do not use float.

Names may contain spaces. "%s" will not work for that.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256