Project Progress
0%
Capstone Project  ·  Structs + Arrays + Pointers + Functions

Simple Banking System

A complete, menu-driven C program that manages bank accounts — deposit, withdraw, transfer, and search — built to deliberately showcase structs, arrays, pointers, and functions working together in one project.

Account struct & array
Find by pointer
Deposit/withdraw via pointer
Transfer between accounts
Main menu
📖

Project Overview

Each bank account is a struct holding an account number, name, and balance. All accounts live in one array — but instead of passing array indices around everywhere, every operation works directly on pointers to Account. This is the key design choice of this project: once you find an account, you get its address, and every function after that modifies the real account directly — no copies, no re-searching.

  • Create/Initialize Accounts — pre-loads a small array of accounts
  • Find Account — returns a pointer to the matching account, or NULL
  • Deposit / Withdraw — functions that take an Account* and modify it directly
  • Transfer — calls withdraw and deposit on two different pointers
  • Display All — loops through the array showing every account
ConceptWhere it's used
structAccount record: number, name, balance
ArrayAccount bank[TOTAL_ACCOUNTS] holds every account
PointersfindAccount() returns Account*; deposit/withdraw/transfer all take pointers
FunctionsOne function per operation, each modifying data through a pointer
-> operatorAccessing struct fields through a pointer: acc->balance
part 1
1

Account Struct & Bank Initialization

Data model

Every account is one Account struct. initBank() pre-loads 4 accounts so the program has data to work with immediately.

Part 1 · bank.c — structs & setup
bank.c
C
#include <stdio.h>
#include <string.h>

#define TOTAL_ACCOUNTS 4

typedef struct {
    int   accNo;
    char  name[40];
    float balance;
} Account;

Account bank[TOTAL_ACCOUNTS];   // the entire bank lives in this array

void initBank() {
    char *names[]  = {"Asha Rao", "Vikram Singh", "Meera Nair", "Karan Mehta"};
    float balances[] = {5000, 12000, 750, 30000};

    for (int i = 0; i < TOTAL_ACCOUNTS; i++) {
        bank[i].accNo = 1001 + i;
        strcpy(bank[i].name, names[i]);
        bank[i].balance = balances[i];
    }
}
💡 accNo starts at 1001 so account numbers look realistic and never collide with array index 0 — a common small touch in real account systems.
part 2
2

Finding an Account — Returning a Pointer

The pointer at the center of the project

findAccount() is the function every other operation depends on. Instead of returning an index or a copy of the account, it returns &bank[i] — the actual address of the matching account. Whatever the caller does to that pointer changes the real data in the array.

Part 2 · bank.c — find & display
bank.c
C
Account* findAccount(int accNo) {
    for (int i = 0; i < TOTAL_ACCOUNTS; i++) {
        if (bank[i].accNo == accNo)
            return &bank[i];   // return the ADDRESS, not a copy
    }
    return NULL;   // not found
}

void displayAll() {
    printf("\n%-8s %-16s %-12s\n", "AccNo", "Name", "Balance");
    for (int i = 0; i < TOTAL_ACCOUNTS; i++) {
        printf("%-8d %-16s Rs %-10.2f\n",
               bank[i].accNo, bank[i].name, bank[i].balance);
    }
}

void searchAccount() {
    int accNo;
    printf("Enter account number: ");
    scanf("%d", &accNo);

    Account *acc = findAccount(accNo);   // acc now points directly at the account
    if (acc == NULL) {
        printf("Account not found.\n");
        return;
    }

    printf("Account %d | %s | Balance: Rs %.2f\n",
           acc->accNo, acc->name, acc->balance);   // -> reads through the pointer
}
⚠️ Always check for NULL. If findAccount() doesn't find a match, it returns NULL. Using acc->balance without checking for NULL first would crash the program (a "null pointer dereference").
part 3
3

Deposit, Withdraw & Transfer — All Through Pointers

Functions that modify data via Account*

Each of these functions receives an Account* and changes the balance directly through the pointer — no return value is needed, because the change happens at the account's real address in the array. transferMoney() reuses both functions on two different pointers.

Part 3 · bank.c — deposit, withdraw, transfer
bank.c
C
void deposit(Account *acc, float amount) {
    acc->balance += amount;   // modifies the real account through the pointer
    printf("Deposited Rs %.2f. New balance: Rs %.2f\n", amount, acc->balance);
}

int withdraw(Account *acc, float amount) {
    if (amount > acc->balance) {
        printf("Insufficient balance.\n");
        return 0;   // failed
    }
    acc->balance -= amount;
    printf("Withdrew Rs %.2f. New balance: Rs %.2f\n", amount, acc->balance);
    return 1;   // success
}

void transferMoney() {
    int fromNo, toNo;
    float amount;

    printf("From account: "); scanf("%d", &fromNo);
    printf("To account: ");   scanf("%d", &toNo);
    printf("Amount: ");       scanf("%f", &amount);

    Account *from = findAccount(fromNo);
    Account *to   = findAccount(toNo);

    if (from == NULL || to == NULL) {
        printf("One or both accounts not found.\n");
        return;
    }

    if (withdraw(from, amount)) {   // only deposit if withdraw succeeded
        deposit(to, amount);
        printf("Transferred Rs %.2f from %d to %d.\n", amount, fromNo, toNo);
    }
}
💡 transferMoney() never touches balance directly. It reuses withdraw() and deposit() on two separate pointers — this is exactly why passing pointers matters: the same two functions work for a single account OR for moving money between two.
part 4
4

The Main Menu

do-while + switch

Same pattern as the Hotel, Library, and Hospital projects — a thin main() that loops and routes choices. The difference here is that deposit and withdraw need an account pointer first, obtained via findAccount() right inside the menu case.

Part 4 · bank.c — main()
bank.c
C
int main() {
    initBank();
    int choice, accNo;
    float amount;
    Account *acc;

    do {
        printf("\n===== SIMPLE BANKING SYSTEM =====\n");
        printf("1. Display All Accounts\n");
        printf("2. Search Account\n");
        printf("3. Deposit\n");
        printf("4. Withdraw\n");
        printf("5. Transfer Between Accounts\n");
        printf("6. Exit\n");
        printf("Enter choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                displayAll();
                break;
            case 2:
                searchAccount();
                break;
            case 3:
                printf("Account number: "); scanf("%d", &accNo);
                acc = findAccount(accNo);
                if (acc) { printf("Amount: "); scanf("%f", &amount); deposit(acc, amount); }
                else printf("Account not found.\n");
                break;
            case 4:
                printf("Account number: "); scanf("%d", &accNo);
                acc = findAccount(accNo);
                if (acc) { printf("Amount: "); scanf("%f", &amount); withdraw(acc, amount); }
                else printf("Account not found.\n");
                break;
            case 5:
                transferMoney();
                break;
            case 6:
                printf("Exiting... Thank you!\n");
                break;
            default:
                printf("Invalid choice.\n");
        }
    } while (choice != 6);

    return 0;
}
terminal — sample session
output
===== SIMPLE BANKING SYSTEM =====
1. Display All Accounts
2. Search Account
3. Deposit
4. Withdraw
5. Transfer Between Accounts
6. Exit
Enter choice: 1

AccNo    Name             Balance
1001     Asha Rao         Rs 5000.00
1002     Vikram Singh     Rs 12000.00
1003     Meera Nair       Rs 750.00
1004     Karan Mehta      Rs 30000.00

Enter choice: 5
From account: 1004
To account: 1003
Amount: 2000
Withdrew Rs 2000.00. New balance: Rs 28000.00
Deposited Rs 2000.00. New balance: Rs 2750.00
Transferred Rs 2000.00 from 1004 to 1003.

Enter choice: 4
Account number: 1003
Amount: 10000
Insufficient balance.

Enter choice: 6
Exiting... Thank you!
extend it

Ways to Extend This Project

Each upgrade below reuses a concept from earlier lessons — and most of them lean even further into pointers:

  • Transaction history — a linked list per account, storing every deposit/withdraw as a node
  • Save/load accounts to a filefprintf/fscanf, exactly like the Hotel/Library/Hospital projects
  • Dynamic account count — replace the fixed array with malloc-allocated Account* memory
  • PIN/password protection — add a PIN field to the struct, check it before deposit/withdraw
  • Interest calculation — a function that takes an array of Account* pointers and applies interest to each
  • Sort accounts by balance — plug in any algorithm from the Sorting lesson, swapping whole structs or pointers
ExtensionConcept it reuses
Transaction historyLinked Lists lesson
Save/load to fileFile I/O lesson
Dynamic accountsDynamic memory (malloc/realloc) lesson
Sort by balanceSorting Algorithms lesson

Project Checklist

  • I understand the Account struct and what each field stores
  • I understand why findAccount() returns a pointer, not a copy or index
  • I always check for NULL before dereferencing a found account
  • I understand how -> accesses struct fields through a pointer
  • I can trace deposit() and withdraw() modifying data via a pointer
  • I understand how transferMoney() reuses withdraw() and deposit() on two pointers
  • I can trace the do-while + switch main menu loop
  • I compiled and ran the full program myself
  • I picked at least one extension to try next